feat(@angular-devkit/build-angular): provide default and abbreviated build target support for dev-server and extract-i18n

The `buildTarget` options for both the `dev-server` and `extract-i8n` builders
now have default values that reflect the recommended and new project generated
values. The defaults are as follows where `<current-project>` is the name of the project
where the `dev-server` or `extract-i18n` builder target is located:
* `dev-server` --> `<current-project>:build:development`
* `extract-i18n` --> `<current-project>:build`

Additionally, abbreviated target specifiers are now supported for these
options. This allows target specifiers such as `::production` which would expand
to `<current-project>:build:production` for either builder.
Abbreviated target specifiers are only supported for the `buildTarget` option in
the `dev-server` and `extract-i18n` builders.
This commit is contained in:
Charles Lyding 2024-01-08 16:51:20 -05:00 committed by Douglas Parker
parent 6e691230f0
commit 8f47f1e965
6 changed files with 20 additions and 13 deletions

View File

@ -503,7 +503,7 @@ namespace strategy {
export type Target = json.JsonObject & Target_2; export type Target = json.JsonObject & Target_2;
// @public // @public
export function targetFromTargetString(str: string): Target; export function targetFromTargetString(specifier: string, abbreviatedProjectName?: string, abbreviatedTargetName?: string): Target;
// @public // @public
export function targetStringFromTarget({ project, target, configuration }: Target): string; export function targetStringFromTarget({ project, target, configuration }: Target): string;

View File

@ -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 { export function targetFromTargetString(
const tuple = str.split(/:/, 3); specifier: string,
abbreviatedProjectName?: string,
abbreviatedTargetName?: string,
): Target {
const tuple = specifier.split(':', 3);
if (tuple.length < 2) { if (tuple.length < 2) {
throw new Error('Invalid target string: ' + JSON.stringify(str)); throw new Error('Invalid target string: ' + JSON.stringify(specifier));
} }
return { return {
project: tuple[0], project: tuple[0] || abbreviatedProjectName || '',
target: tuple[1], target: tuple[1] || abbreviatedTargetName || '',
...(tuple[2] !== undefined && { configuration: tuple[2] }), ...(tuple[2] !== undefined && { configuration: tuple[2] }),
}; };
} }

View File

@ -34,8 +34,9 @@ export async function normalizeOptions(
const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot); const cacheOptions = normalizeCacheOptions(projectMetadata, workspaceRoot);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // Target specifier defaults to the current project's build target using a development configuration
const buildTarget = targetFromTargetString(options.buildTarget ?? options.browserTarget!); const buildTargetSpecifier = options.buildTarget ?? options.browserTarget ?? `::development`;
const buildTarget = targetFromTargetString(buildTargetSpecifier, projectName, 'build');
// Initial options to keep // Initial options to keep
const { const {

View File

@ -13,7 +13,7 @@
"buildTarget": { "buildTarget": {
"type": "string", "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`.", "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": { "port": {
"type": "number", "type": "number",

View File

@ -33,8 +33,9 @@ export async function normalizeOptions(
const projectMetadata = await context.getProjectMetadata(projectName); const projectMetadata = await context.getProjectMetadata(projectName);
const projectRoot = path.join(workspaceRoot, (projectMetadata.root as string | undefined) ?? ''); const projectRoot = path.join(workspaceRoot, (projectMetadata.root as string | undefined) ?? '');
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // Target specifier defaults to the current project's build target with no specified configuration
const buildTarget = targetFromTargetString(options.buildTarget ?? options.browserTarget!); const buildTargetSpecifier = options.buildTarget ?? options.browserTarget ?? ':';
const buildTarget = targetFromTargetString(buildTargetSpecifier, projectName, 'build');
const i18nOptions = createI18nOptions(projectMetadata); const i18nOptions = createI18nOptions(projectMetadata);

View File

@ -13,7 +13,7 @@
"buildTarget": { "buildTarget": {
"type": "string", "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`.", "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": { "format": {
"type": "string", "type": "string",