diff --git a/goldens/public-api/angular_devkit/core/index.api.md b/goldens/public-api/angular_devkit/core/index.api.md index 748faf2bbeb4..12d18bc0d3d0 100644 --- a/goldens/public-api/angular_devkit/core/index.api.md +++ b/goldens/public-api/angular_devkit/core/index.api.md @@ -982,7 +982,7 @@ interface SimpleMemoryHostStats { // @public (undocumented) interface SmartDefaultProvider { // (undocumented) - (schema: JsonObject): T | Observable; + (schema: JsonObject): T | Observable | Promise; } // @public diff --git a/packages/angular/cli/src/command-builder/architect-base-command-module.ts b/packages/angular/cli/src/command-builder/architect-base-command-module.ts index fb3508777d74..25c294efbf20 100644 --- a/packages/angular/cli/src/command-builder/architect-base-command-module.ts +++ b/packages/angular/cli/src/command-builder/architect-base-command-module.ts @@ -189,7 +189,7 @@ export abstract class ArchitectBaseCommandModule } catch (e) { assertIsError(e); if (e.code === 'MODULE_NOT_FOUND') { - this.warnOnMissingNodeModules(); + await this.warnOnMissingNodeModules(); throw new CommandModuleError(`Could not find the '${builderConf}' builder's node package.`); } @@ -203,7 +203,7 @@ export abstract class ArchitectBaseCommandModule ); } - private warnOnMissingNodeModules(): void { + private async warnOnMissingNodeModules(): Promise { const basePath = this.context.workspace?.basePath; if (!basePath) { return; @@ -218,7 +218,9 @@ export abstract class ArchitectBaseCommandModule } catch {} this.context.logger.warn( - `Node packages may not be installed. Try installing with '${this.context.packageManager.name} install'.`, + `Node packages may not be installed. Try installing with '${ + (await this.context.packageManager).name + } install'.`, ); } diff --git a/packages/angular/cli/src/command-builder/command-module.ts b/packages/angular/cli/src/command-builder/command-module.ts index e5cc6f70473a..f7bdfe04fa29 100644 --- a/packages/angular/cli/src/command-builder/command-module.ts +++ b/packages/angular/cli/src/command-builder/command-module.ts @@ -153,10 +153,12 @@ export abstract class CommandModule implements CommandModuleI ['version', 'update', 'analytics'].includes(this.commandName), ); + const packageManager = await this.context.packageManager; + return userId ? new AnalyticsCollector(this.context.logger, userId, { - name: this.context.packageManager.name, - version: await this.context.packageManager.getVersion(), + name: packageManager.name, + version: await packageManager.getVersion(), }) : undefined; } diff --git a/packages/angular/cli/src/command-builder/command-runner.ts b/packages/angular/cli/src/command-builder/command-runner.ts index 452f9afe8f68..55fabd0faa24 100644 --- a/packages/angular/cli/src/command-builder/command-runner.ts +++ b/packages/angular/cli/src/command-builder/command-runner.ts @@ -18,7 +18,7 @@ import { RootCommands, RootCommandsAliases, } from '../commands/command-config'; -import { createPackageManager } from '../package-managers'; +import { PackageManager, createPackageManager } from '../package-managers'; import { ConfiguredPackageManagerInfo } from '../package-managers/factory'; import { colors } from '../utilities/color'; import { AngularWorkspace, getProjectByCwd, getWorkspace } from '../utilities/config'; @@ -65,20 +65,8 @@ export async function runCommand(args: string[], logger: logging.Logger): Promis } const root = workspace?.basePath ?? process.cwd(); - const cacheConfig = workspace && getCacheConfig(workspace); - const packageManager = await createPackageManager({ - cwd: root, - logger, - dryRun: dryRun || help || jsonHelp || getYargsCompletions, - tempDirectory: cacheConfig?.enabled ? cacheConfig.path : undefined, - configuredPackageManager: await getConfiguredPackageManager( - root, - workspace, - globalConfiguration, - ), - }); - const localYargs = yargs(args); + let packageManager: Promise | undefined; const context: CommandContext = { globalConfiguration, workspace, @@ -86,7 +74,23 @@ export async function runCommand(args: string[], logger: logging.Logger): Promis currentDirectory: process.cwd(), yargsInstance: localYargs, root, - packageManager, + get packageManager() { + return (packageManager ??= (async () => { + const cacheConfig = workspace && getCacheConfig(workspace); + + return createPackageManager({ + cwd: root, + logger, + dryRun: dryRun || help || jsonHelp || getYargsCompletions, + tempDirectory: cacheConfig?.enabled ? cacheConfig.path : undefined, + configuredPackageManager: await getConfiguredPackageManager( + root, + workspace, + globalConfiguration, + ), + }); + })()); + }, args: { positional: positional.map((v) => v.toString()), options: { diff --git a/packages/angular/cli/src/command-builder/definitions.ts b/packages/angular/cli/src/command-builder/definitions.ts index d552b432b685..d6d79292bd29 100644 --- a/packages/angular/cli/src/command-builder/definitions.ts +++ b/packages/angular/cli/src/command-builder/definitions.ts @@ -28,7 +28,7 @@ export interface CommandContext { workspace?: AngularWorkspace; globalConfiguration: AngularWorkspace; logger: logging.Logger; - packageManager: PackageManager; + readonly packageManager: Promise; yargsInstance: Argv<{}>; /** Arguments parsed in free-from without parser configuration. */ diff --git a/packages/angular/cli/src/command-builder/schematics-command-module.ts b/packages/angular/cli/src/command-builder/schematics-command-module.ts index c74b44101e93..e3ddf4d496ce 100644 --- a/packages/angular/cli/src/command-builder/schematics-command-module.ts +++ b/packages/angular/cli/src/command-builder/schematics-command-module.ts @@ -108,9 +108,9 @@ export abstract class SchematicsCommandModule collectionName: string, options: SchematicsExecutionOptions, ): Promise { - const { logger, root, packageManager } = this.context; + const { logger, root } = this.context; + const packageManager = await this.context.packageManager; const { force, dryRun, packageRegistry } = options; - const workflow = new NodeWorkflow(root, { force, dryRun, diff --git a/packages/angular/cli/src/commands/add/cli.ts b/packages/angular/cli/src/commands/add/cli.ts index 136704947e69..ba87bfd93484 100644 --- a/packages/angular/cli/src/commands/add/cli.ts +++ b/packages/angular/cli/src/commands/add/cli.ts @@ -199,8 +199,8 @@ export default class AddCommandModule [ { title: 'Determining Package Manager', - task: (_context, task) => - (task.output = `Using package manager: ${color.dim(this.context.packageManager.name)}`), + task: async (_context, task) => + (task.output = `Using package manager: ${color.dim((await this.context.packageManager).name)}`), rendererOptions: { persistentOutput: true }, }, { @@ -318,7 +318,7 @@ export default class AddCommandModule ): Promise { const { registry, verbose } = options; const { packageIdentifier } = context; - const { packageManager } = this.context; + const packageManager = await this.context.packageManager; const packageName = packageIdentifier.name; assert(packageName, 'Registry package identifiers should always have a name.'); @@ -416,7 +416,7 @@ export default class AddCommandModule }, ): Promise { const { packageIdentifier } = context; - const { packageManager } = this.context; + const packageManager = await this.context.packageManager; const { registry, verbose, rejectionReasons } = options; const packageName = packageIdentifier.name; assert(packageName, 'Package name must be defined.'); @@ -494,7 +494,9 @@ export default class AddCommandModule let manifest; try { - manifest = await this.context.packageManager.getManifest(context.packageIdentifier, { + manifest = await ( + await this.context.packageManager + ).getManifest(context.packageIdentifier, { registry, }); } catch (e) { @@ -567,7 +569,7 @@ export default class AddCommandModule ): Promise { const { registry } = options; const { packageIdentifier, savePackage } = context; - const { packageManager } = this.context; + const packageManager = await this.context.packageManager; // Only show if installation will actually occur task.title = 'Installing package'; diff --git a/packages/angular/cli/src/commands/new/cli.ts b/packages/angular/cli/src/commands/new/cli.ts index 6e6545e66421..6a7a1b7b7208 100644 --- a/packages/angular/cli/src/commands/new/cli.ts +++ b/packages/angular/cli/src/commands/new/cli.ts @@ -75,7 +75,7 @@ export default class NewCommandModule workflow.registry.addSmartDefaultProvider('ng-cli-version', () => VERSION.full); workflow.registry.addSmartDefaultProvider( 'packageManager', - () => this.context.packageManager.name, + async () => (await this.context.packageManager).name, ); return this.runSchematic({ diff --git a/packages/angular/cli/src/commands/update/cli.ts b/packages/angular/cli/src/commands/update/cli.ts index de6d7f53fea0..7cfb96422e73 100644 --- a/packages/angular/cli/src/commands/update/cli.ts +++ b/packages/angular/cli/src/commands/update/cli.ts @@ -163,7 +163,8 @@ export default class UpdateCommandModule extends CommandModule): Promise { - const { logger, packageManager } = this.context; + const { logger } = this.context; + const packageManager = await this.context.packageManager; // Check if the current installed CLI version is older than the latest compatible version. // Skip when running `ng update` without a package name as this will not trigger an actual update. @@ -517,7 +518,7 @@ export default class UpdateCommandModule extends CommandModule { - (schema: JsonObject): T | Observable; + (schema: JsonObject): T | Observable | Promise; } export interface SchemaKeywordValidator { diff --git a/packages/angular_devkit/core/src/json/schema/registry.ts b/packages/angular_devkit/core/src/json/schema/registry.ts index 11632b64f86a..550227d9b726 100644 --- a/packages/angular_devkit/core/src/json/schema/registry.ts +++ b/packages/angular_devkit/core/src/json/schema/registry.ts @@ -99,7 +99,7 @@ export class CoreSchemaRegistry implements SchemaRegistry { private _smartDefaultKeyword = false; private _promptProvider?: PromptProvider; - private _sourceMap = new Map>(); + private _sourceProvider = new Map>(); constructor(formats: SchemaFormat[] = []) { this._ajv = new Ajv({ @@ -387,11 +387,11 @@ export class CoreSchemaRegistry implements SchemaRegistry { } addSmartDefaultProvider(source: string, provider: SmartDefaultProvider): void { - if (this._sourceMap.has(source)) { + if (this._sourceProvider.has(source)) { throw new Error(source); } - this._sourceMap.set(source, provider as unknown as SmartDefaultProvider<{}>); + this._sourceProvider.set(source, provider as unknown as SmartDefaultProvider<{}>); if (!this._smartDefaultKeyword) { this._smartDefaultKeyword = true; @@ -632,17 +632,17 @@ export class CoreSchemaRegistry implements SchemaRegistry { ): Promise { for (const [pointer, schema] of smartDefaults.entries()) { const fragments = JSON.parse(pointer) as string[]; - const source = this._sourceMap.get(schema.$source as string); + const source = this._sourceProvider.get(schema.$source as string); if (!source) { continue; } let value = source(schema); if (isObservable(value)) { - value = (await lastValueFrom(value)) as {}; + value = lastValueFrom(value) as {}; } - CoreSchemaRegistry._set(data, fragments, value); + CoreSchemaRegistry._set(data, fragments, await value); } }