From 46b54b957d16e07018e18364f42d7e8c172bd3ae Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Tue, 29 Apr 2025 11:57:53 -0400 Subject: [PATCH] refactor(@angular/build): use utility helper to get project root paths The `application`, `karma`, and `unit-test` builders now all use the same utility function to get the project root and project source root paths. This helps ensure consistent behavior and removes repeat code within each. --- .../build/src/builders/application/options.ts | 23 +----------- .../src/builders/karma/application_builder.ts | 5 ++- .../build/src/builders/unit-test/options.ts | 8 +--- .../build/src/utils/project-metadata.ts | 37 +++++++++++++++++++ 4 files changed, 44 insertions(+), 29 deletions(-) create mode 100644 packages/angular/build/src/utils/project-metadata.ts diff --git a/packages/angular/build/src/builders/application/options.ts b/packages/angular/build/src/builders/application/options.ts index 5600c1e633ad..60b240eb9d74 100644 --- a/packages/angular/build/src/builders/application/options.ts +++ b/packages/angular/build/src/builders/application/options.ts @@ -24,6 +24,7 @@ import { generateSearchDirectories, loadPostcssConfiguration, } from '../../utils/postcss-configuration'; +import { getProjectRootPaths, normalizeDirectoryPath } from '../../utils/project-metadata'; import { urlJoin } from '../../utils/url'; import { Schema as ApplicationBuilderOptions, @@ -160,12 +161,7 @@ export async function normalizeOptions( // ref: https://github.com/nodejs/node/issues/7726 realpathSync(context.workspaceRoot); const projectMetadata = await context.getProjectMetadata(projectName); - const projectRoot = normalizeDirectoryPath( - path.join(workspaceRoot, (projectMetadata.root as string | undefined) ?? ''), - ); - const projectSourceRoot = normalizeDirectoryPath( - path.join(workspaceRoot, (projectMetadata.sourceRoot as string | undefined) ?? 'src'), - ); + const { projectRoot, projectSourceRoot } = getProjectRootPaths(workspaceRoot, projectMetadata); // Gather persistent caching option and provide a project specific cache location const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot); @@ -613,21 +609,6 @@ function normalizeEntryPoints( } } -/** - * Normalize a directory path string. - * Currently only removes a trailing slash if present. - * @param path A path string. - * @returns A normalized path string. - */ -function normalizeDirectoryPath(path: string): string { - const last = path[path.length - 1]; - if (last === '/' || last === '\\') { - return path.slice(0, -1); - } - - return path; -} - function normalizeGlobalEntries( rawEntries: ({ bundleName?: string; input: string; inject?: boolean } | string)[] | undefined, defaultName: string, diff --git a/packages/angular/build/src/builders/karma/application_builder.ts b/packages/angular/build/src/builders/karma/application_builder.ts index b88d333a24e7..c73dbbe7fbe6 100644 --- a/packages/angular/build/src/builders/karma/application_builder.ts +++ b/packages/angular/build/src/builders/karma/application_builder.ts @@ -18,6 +18,7 @@ import { globSync } from 'tinyglobby'; import { BuildOutputFileType } from '../../tools/esbuild/bundler-context'; import { emitFilesToDisk } from '../../tools/esbuild/utils'; import { createVirtualModulePlugin } from '../../tools/esbuild/virtual-module-plugin'; +import { getProjectRootPaths } from '../../utils/project-metadata'; import { buildApplicationInternal } from '../application/index'; import { ApplicationBuilderInternalOptions } from '../application/options'; import { Result, ResultFile, ResultKind } from '../application/results'; @@ -317,9 +318,9 @@ async function getProjectSourceRoot(context: BuilderContext): Promise { } const projectMetadata = await context.getProjectMetadata(projectName); - const sourceRoot = (projectMetadata.sourceRoot ?? projectMetadata.root ?? '') as string; + const { projectSourceRoot } = getProjectRootPaths(context.workspaceRoot, projectMetadata); - return path.join(context.workspaceRoot, sourceRoot); + return projectSourceRoot; } function normalizePolyfills(polyfills: string | string[] | undefined): [string[], string[]] { diff --git a/packages/angular/build/src/builders/unit-test/options.ts b/packages/angular/build/src/builders/unit-test/options.ts index 9290d2e6a4b7..2cd09a3b03e9 100644 --- a/packages/angular/build/src/builders/unit-test/options.ts +++ b/packages/angular/build/src/builders/unit-test/options.ts @@ -9,6 +9,7 @@ import { type BuilderContext, targetFromTargetString } from '@angular-devkit/architect'; import path from 'node:path'; import { normalizeCacheOptions } from '../../utils/normalize-cache'; +import { getProjectRootPaths } from '../../utils/project-metadata'; import type { Schema as UnitTestOptions } from './schema'; export type NormalizedUnitTestOptions = Awaited>; @@ -21,12 +22,7 @@ export async function normalizeOptions( // Setup base paths based on workspace root and project information const workspaceRoot = context.workspaceRoot; const projectMetadata = await context.getProjectMetadata(projectName); - const projectRoot = normalizeDirectoryPath( - path.join(workspaceRoot, (projectMetadata.root as string | undefined) ?? ''), - ); - const projectSourceRoot = normalizeDirectoryPath( - path.join(workspaceRoot, (projectMetadata.sourceRoot as string | undefined) ?? 'src'), - ); + const { projectRoot, projectSourceRoot } = getProjectRootPaths(workspaceRoot, projectMetadata); // Gather persistent caching option and provide a project specific cache location const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot); diff --git a/packages/angular/build/src/utils/project-metadata.ts b/packages/angular/build/src/utils/project-metadata.ts new file mode 100644 index 000000000000..bc997652fef1 --- /dev/null +++ b/packages/angular/build/src/utils/project-metadata.ts @@ -0,0 +1,37 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { join } from 'node:path'; + +/** + * Normalize a directory path string. + * Currently only removes a trailing slash if present. + * @param path A path string. + * @returns A normalized path string. + */ +export function normalizeDirectoryPath(path: string): string { + const last = path[path.length - 1]; + if (last === '/' || last === '\\') { + return path.slice(0, -1); + } + + return path; +} + +export function getProjectRootPaths( + workspaceRoot: string, + projectMetadata: { root?: string; sourceRoot?: string }, +) { + const projectRoot = normalizeDirectoryPath(join(workspaceRoot, projectMetadata.root ?? '')); + const rawSourceRoot = projectMetadata.sourceRoot; + const projectSourceRoot = normalizeDirectoryPath( + rawSourceRoot === undefined ? join(projectRoot, 'src') : join(workspaceRoot, rawSourceRoot), + ); + + return { projectRoot, projectSourceRoot }; +}