public override async initialize()

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;
      }
    }
  }