diff --git a/goldens/public-api/angular_devkit/architect/index.md b/goldens/public-api/angular_devkit/architect/index.md index 1dc0c183e10e..2abd6489bcea 100644 --- a/goldens/public-api/angular_devkit/architect/index.md +++ b/goldens/public-api/angular_devkit/architect/index.md @@ -503,7 +503,7 @@ namespace strategy { export type Target = json.JsonObject & Target_2; // @public -export function targetFromTargetString(str: string): Target; +export function targetFromTargetString(specifier: string, abbreviatedProjectName?: string, abbreviatedTargetName?: string): Target; // @public export function targetStringFromTarget({ project, target, configuration }: Target): string; diff --git a/packages/angular_devkit/architect/src/api.ts b/packages/angular_devkit/architect/src/api.ts index f3ab909a3489..0b995013194d 100644 --- a/packages/angular_devkit/architect/src/api.ts +++ b/packages/angular_devkit/architect/src/api.ts @@ -330,17 +330,22 @@ export function targetStringFromTarget({ project, target, configuration }: Targe } /** - * Return a Target tuple from a string. + * Return a Target tuple from a specifier string. + * Supports abbreviated target specifiers (examples: `::`, `::development`, or `:build:production`). */ -export function targetFromTargetString(str: string): Target { - const tuple = str.split(/:/, 3); +export function targetFromTargetString( + specifier: string, + abbreviatedProjectName?: string, + abbreviatedTargetName?: string, +): Target { + const tuple = specifier.split(':', 3); if (tuple.length < 2) { - throw new Error('Invalid target string: ' + JSON.stringify(str)); + throw new Error('Invalid target string: ' + JSON.stringify(specifier)); } return { - project: tuple[0], - target: tuple[1], + project: tuple[0] || abbreviatedProjectName || '', + target: tuple[1] || abbreviatedTargetName || '', ...(tuple[2] !== undefined && { configuration: tuple[2] }), }; } diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/options.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/options.ts index 2102c9284a4e..3aa8983e57a9 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/options.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/options.ts @@ -34,8 +34,9 @@ export async function normalizeOptions( const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const buildTarget = targetFromTargetString(options.buildTarget ?? options.browserTarget!); + // Target specifier defaults to the current project's build target using a development configuration + const buildTargetSpecifier = options.buildTarget ?? options.browserTarget ?? `::development`; + const buildTarget = targetFromTargetString(buildTargetSpecifier, projectName, 'build'); // Initial options to keep const { diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/schema.json b/packages/angular_devkit/build_angular/src/builders/dev-server/schema.json index 93ce53407a27..2d224e30a4a9 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/schema.json +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/schema.json @@ -13,7 +13,7 @@ "buildTarget": { "type": "string", "description": "A build builder target to serve in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.", - "pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$" + "pattern": "^[^:\\s]*:[^:\\s]*(:[^\\s]+)?$" }, "port": { "type": "number", diff --git a/packages/angular_devkit/build_angular/src/builders/extract-i18n/options.ts b/packages/angular_devkit/build_angular/src/builders/extract-i18n/options.ts index b65039ccb775..57bea269d9d6 100644 --- a/packages/angular_devkit/build_angular/src/builders/extract-i18n/options.ts +++ b/packages/angular_devkit/build_angular/src/builders/extract-i18n/options.ts @@ -33,8 +33,9 @@ export async function normalizeOptions( const projectMetadata = await context.getProjectMetadata(projectName); const projectRoot = path.join(workspaceRoot, (projectMetadata.root as string | undefined) ?? ''); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const buildTarget = targetFromTargetString(options.buildTarget ?? options.browserTarget!); + // Target specifier defaults to the current project's build target with no specified configuration + const buildTargetSpecifier = options.buildTarget ?? options.browserTarget ?? ':'; + const buildTarget = targetFromTargetString(buildTargetSpecifier, projectName, 'build'); const i18nOptions = createI18nOptions(projectMetadata); diff --git a/packages/angular_devkit/build_angular/src/builders/extract-i18n/schema.json b/packages/angular_devkit/build_angular/src/builders/extract-i18n/schema.json index 22bb8c36b460..1b3943d8cee4 100644 --- a/packages/angular_devkit/build_angular/src/builders/extract-i18n/schema.json +++ b/packages/angular_devkit/build_angular/src/builders/extract-i18n/schema.json @@ -13,7 +13,7 @@ "buildTarget": { "type": "string", "description": "A builder target to extract i18n messages in the format of `project:target[:configuration]`. You can also pass in more than one configuration name as a comma-separated list. Example: `project:target:production,staging`.", - "pattern": "^[^:\\s]+:[^:\\s]+(:[^\\s]+)?$" + "pattern": "^[^:\\s]*:[^:\\s]*(:[^\\s]+)?$" }, "format": { "type": "string",