in packages/angular/cli/models/architect-command.ts [59:246]
public override async initialize(options: T & Arguments): Promise<number | void> {
this._registry = new json.schema.CoreSchemaRegistry();
this._registry.addPostTransform(json.schema.transforms.addUndefinedDefaults);
this._registry.useXDeprecatedProvider((msg) => this.logger.warn(msg));
if (!this.workspace) {
this.logger.fatal('A workspace is required for this command.');
return 1;
}
this._architectHost = new WorkspaceNodeModulesArchitectHost(
this.workspace,
this.workspace.basePath,
);
this._architect = new Architect(this._architectHost, this._registry);
if (!this.target) {
if (options.help) {
// This is a special case where we just return.
return;
}
const specifier = this._makeTargetSpecifier(options);
if (!specifier.project || !specifier.target) {
this.logger.fatal('Cannot determine project or target for command.');
return 1;
}
return;
}
let projectName = options.project;
if (projectName && !this.workspace.projects.has(projectName)) {
this.logger.fatal(`Project '${projectName}' does not exist.`);
return 1;
}
const commandLeftovers = options['--'];
const targetProjectNames: string[] = [];
for (const [name, project] of this.workspace.projects) {
if (project.targets.has(this.target)) {
targetProjectNames.push(name);
}
}
if (projectName && !targetProjectNames.includes(projectName)) {
return await this.onMissingTarget(projectName);
}
if (targetProjectNames.length === 0) {
return await this.onMissingTarget();
}
if (!projectName && commandLeftovers && commandLeftovers.length > 0) {
const builderNames = new Set<string>();
const leftoverMap = new Map<string, { optionDefs: Option[]; parsedOptions: Arguments }>();
let potentialProjectNames = new Set<string>(targetProjectNames);
for (const name of targetProjectNames) {
const builderName = await this._architectHost.getBuilderNameForTarget({
project: name,
target: this.target,
});
if (this.multiTarget) {
builderNames.add(builderName);
}
let builderDesc;
try {
builderDesc = await this._architectHost.resolveBuilder(builderName);
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND') {
await this.warnOnMissingNodeModules(this.workspace.basePath);
this.logger.fatal(`Could not find the '${builderName}' builder's node package.`);
return 1;
}
throw e;
}
const optionDefs = await parseJsonSchemaToOptions(
this._registry,
builderDesc.optionSchema as json.JsonObject,
);
const parsedOptions = parseArguments([...commandLeftovers], optionDefs);
const builderLeftovers = parsedOptions['--'] || [];
leftoverMap.set(name, { optionDefs, parsedOptions });
potentialProjectNames = new Set(
builderLeftovers.filter((x) => potentialProjectNames.has(x)),
);
}
if (potentialProjectNames.size === 1) {
projectName = [...potentialProjectNames][0];
// remove the project name from the leftovers
const optionInfo = leftoverMap.get(projectName);
if (optionInfo) {
const locations = [];
let i = 0;
while (i < commandLeftovers.length) {
i = commandLeftovers.indexOf(projectName, i + 1);
if (i === -1) {
break;
}
locations.push(i);
}
delete optionInfo.parsedOptions['--'];
for (const location of locations) {
const tempLeftovers = [...commandLeftovers];
tempLeftovers.splice(location, 1);
const tempArgs = parseArguments([...tempLeftovers], optionInfo.optionDefs);
delete tempArgs['--'];
if (JSON.stringify(optionInfo.parsedOptions) === JSON.stringify(tempArgs)) {
options['--'] = tempLeftovers;
break;
}
}
}
}
if (!projectName && this.multiTarget && builderNames.size > 1) {
this.logger.fatal(tags.oneLine`
Architect commands with command line overrides cannot target different builders. The
'${this.target}' target would run on projects ${targetProjectNames.join()} which have the
following builders: ${'\n ' + [...builderNames].join('\n ')}
`);
return 1;
}
}
if (!projectName && !this.multiTarget) {
const defaultProjectName = this.workspace.extensions['defaultProject'] as string;
if (targetProjectNames.length === 1) {
projectName = targetProjectNames[0];
} else if (defaultProjectName && targetProjectNames.includes(defaultProjectName)) {
projectName = defaultProjectName;
} else if (options.help) {
// This is a special case where we just return.
return;
} else {
this.logger.fatal(
this.missingTargetError || 'Cannot determine project or target for command.',
);
return 1;
}
}
options.project = projectName;
const builderConf = await this._architectHost.getBuilderNameForTarget({
project: projectName || (targetProjectNames.length > 0 ? targetProjectNames[0] : ''),
target: this.target,
});
let builderDesc;
try {
builderDesc = await this._architectHost.resolveBuilder(builderConf);
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND') {
await this.warnOnMissingNodeModules(this.workspace.basePath);
this.logger.fatal(`Could not find the '${builderConf}' builder's node package.`);
return 1;
}
throw e;
}
this.description.options.push(
...(await parseJsonSchemaToOptions(
this._registry,
builderDesc.optionSchema as json.JsonObject,
)),
);
// Update options to remove analytics from options if the builder isn't safelisted.
for (const o of this.description.options) {
if (o.userAnalytics && !isPackageNameSafeForAnalytics(builderConf)) {
o.userAnalytics = undefined;
}
}
}