@angular/cli 14.0.0-next.5 → 14.0.0-next.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/lib/cli/index.d.ts +0 -1
  2. package/lib/cli/index.js +3 -30
  3. package/lib/config/schema.json +26 -7
  4. package/lib/config/workspace-schema.d.ts +6 -1
  5. package/lib/init.js +7 -6
  6. package/package.json +17 -20
  7. package/src/analytics/analytics-collector.js +7 -1
  8. package/src/analytics/analytics.d.ts +10 -23
  9. package/src/analytics/analytics.js +99 -184
  10. package/src/command-builder/architect-base-command-module.d.ts +8 -1
  11. package/src/command-builder/architect-base-command-module.js +61 -7
  12. package/src/command-builder/architect-command-module.d.ts +0 -1
  13. package/src/command-builder/architect-command-module.js +16 -12
  14. package/src/command-builder/command-module.d.ts +5 -2
  15. package/src/command-builder/command-module.js +21 -8
  16. package/src/command-builder/command-runner.d.ts +1 -2
  17. package/src/command-builder/command-runner.js +54 -48
  18. package/src/command-builder/schematics-command-module.d.ts +19 -7
  19. package/src/command-builder/schematics-command-module.js +268 -50
  20. package/src/command-builder/utilities/command.d.ts +13 -0
  21. package/src/command-builder/utilities/command.js +27 -0
  22. package/src/command-builder/utilities/json-help.d.ts +16 -14
  23. package/src/command-builder/utilities/json-help.js +26 -22
  24. package/{models → src/command-builder/utilities}/schematic-engine-host.d.ts +0 -0
  25. package/{models → src/command-builder/utilities}/schematic-engine-host.js +0 -0
  26. package/src/command-builder/utilities/schematic-workflow.d.ts +14 -0
  27. package/src/command-builder/utilities/schematic-workflow.js +68 -0
  28. package/src/commands/add/cli.d.ts +11 -1
  29. package/src/commands/add/cli.js +325 -6
  30. package/src/commands/add/long-description.md +1 -4
  31. package/src/commands/analytics/cli.d.ts +5 -10
  32. package/src/commands/analytics/cli.js +15 -50
  33. package/src/commands/analytics/info/cli.d.ts +16 -0
  34. package/src/commands/analytics/info/cli.js +26 -0
  35. package/src/commands/analytics/settings/cli.d.ts +35 -0
  36. package/src/commands/analytics/settings/cli.js +61 -0
  37. package/src/commands/cache/clean/cli.d.ts +17 -0
  38. package/src/commands/cache/clean/cli.js +32 -0
  39. package/src/commands/cache/cli.d.ts +17 -0
  40. package/src/commands/cache/cli.js +38 -0
  41. package/src/commands/cache/info/cli.d.ts +20 -0
  42. package/src/commands/cache/info/cli.js +82 -0
  43. package/src/commands/cache/long-description.md +53 -0
  44. package/src/commands/cache/settings/cli.d.ts +27 -0
  45. package/src/commands/cache/settings/cli.js +42 -0
  46. package/src/commands/cache/utilities.d.ts +11 -0
  47. package/src/commands/cache/utilities.js +50 -0
  48. package/src/commands/config/cli.d.ts +5 -2
  49. package/src/commands/config/cli.js +128 -6
  50. package/src/commands/deploy/cli.d.ts +2 -1
  51. package/src/commands/deploy/cli.js +27 -13
  52. package/src/commands/doc/cli.d.ts +1 -1
  53. package/src/commands/doc/cli.js +5 -1
  54. package/src/commands/e2e/cli.d.ts +3 -2
  55. package/src/commands/e2e/cli.js +14 -13
  56. package/src/commands/generate/cli.d.ts +14 -2
  57. package/src/commands/generate/cli.js +83 -36
  58. package/src/commands/lint/cli.d.ts +2 -1
  59. package/src/commands/lint/cli.js +6 -9
  60. package/src/commands/new/cli.d.ts +7 -3
  61. package/src/commands/new/cli.js +52 -6
  62. package/src/commands/update/cli.d.ts +31 -5
  63. package/src/commands/update/cli.js +709 -8
  64. package/src/commands/update/schematic/index.js +32 -19
  65. package/src/commands/version/cli.d.ts +0 -1
  66. package/src/commands/version/cli.js +19 -43
  67. package/src/typings-bazel.d.ts +14 -0
  68. package/src/typings.d.ts +0 -13
  69. package/src/utilities/color.js +5 -1
  70. package/src/utilities/config.d.ts +1 -1
  71. package/src/utilities/config.js +22 -11
  72. package/src/utilities/environment-options.d.ts +12 -0
  73. package/src/utilities/environment-options.js +24 -0
  74. package/src/utilities/find-up.js +5 -1
  75. package/src/utilities/memoize.d.ts +15 -0
  76. package/src/utilities/memoize.js +69 -0
  77. package/src/utilities/package-manager.d.ts +33 -5
  78. package/src/utilities/package-manager.js +252 -71
  79. package/src/utilities/package-metadata.d.ts +15 -37
  80. package/src/utilities/package-metadata.js +15 -27
  81. package/src/utilities/package-tree.d.ts +2 -2
  82. package/src/utilities/package-tree.js +5 -1
  83. package/src/utilities/project.js +5 -1
  84. package/src/utilities/prompt.d.ts +2 -0
  85. package/src/utilities/prompt.js +25 -4
  86. package/bin/postinstall/analytics-prompt.js +0 -27
  87. package/bin/postinstall/script.js +0 -16
  88. package/models/command.d.ts +0 -29
  89. package/models/command.js +0 -50
  90. package/models/interface.d.ts +0 -19
  91. package/models/interface.js +0 -9
  92. package/models/schematic-command.d.ts +0 -43
  93. package/models/schematic-command.js +0 -378
  94. package/src/commands/add/add-impl.d.ts +0 -22
  95. package/src/commands/add/add-impl.js +0 -331
  96. package/src/commands/analytics/long-description.md +0 -10
  97. package/src/commands/config/config-impl.d.ts +0 -17
  98. package/src/commands/config/config-impl.js +0 -151
  99. package/src/commands/generate/generate-impl.d.ts +0 -19
  100. package/src/commands/generate/generate-impl.js +0 -49
  101. package/src/commands/new/new-impl.d.ts +0 -18
  102. package/src/commands/new/new-impl.js +0 -38
  103. package/src/commands/update/update-impl.d.ts +0 -40
  104. package/src/commands/update/update-impl.js +0 -728
  105. package/src/utilities/install-package.d.ts +0 -16
  106. package/src/utilities/install-package.js +0 -193
  107. package/src/utilities/package-json.d.ts +0 -249
  108. package/src/utilities/package-json.js +0 -9
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.io/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.addCommandModuleToYargs = exports.demandCommandFailureMessage = void 0;
11
+ exports.demandCommandFailureMessage = `You need to specify a command before moving on. Use '--help' to view the available commands.`;
12
+ function addCommandModuleToYargs(localYargs, commandModule, context) {
13
+ const cmd = new commandModule(context);
14
+ const describe = context.args.options.jsonHelp ? cmd.fullDescribe : cmd.describe;
15
+ return localYargs.command({
16
+ command: cmd.command,
17
+ aliases: cmd.aliases,
18
+ describe:
19
+ // We cannot add custom fields in help, such as long command description which is used in AIO.
20
+ // Therefore, we get around this by adding a complex object as a string which we later parse when generating the help files.
21
+ typeof describe === 'object' ? JSON.stringify(describe) : describe,
22
+ deprecated: cmd.deprecated,
23
+ builder: (argv) => cmd.builder(argv),
24
+ handler: (args) => cmd.handler(args),
25
+ });
26
+ }
27
+ exports.addCommandModuleToYargs = addCommandModuleToYargs;
@@ -5,20 +5,6 @@
5
5
  * Use of this source code is governed by an MIT-style license that can be
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
- export interface JsonHelp {
9
- name: string;
10
- shortDescription?: string;
11
- command: string;
12
- longDescription?: string;
13
- longDescriptionRelativePath?: string;
14
- options: JsonHelpOption[];
15
- subcommands?: {
16
- name: string;
17
- description: string;
18
- aliases: string[];
19
- deprecated: string | boolean;
20
- }[];
21
- }
22
8
  interface JsonHelpOption {
23
9
  name: string;
24
10
  type?: string;
@@ -30,5 +16,21 @@ interface JsonHelpOption {
30
16
  enum?: string[];
31
17
  description?: string;
32
18
  }
19
+ interface JsonHelpDescription {
20
+ shortDescription?: string;
21
+ longDescription?: string;
22
+ longDescriptionRelativePath?: string;
23
+ }
24
+ interface JsonHelpSubcommand extends JsonHelpDescription {
25
+ name: string;
26
+ aliases: string[];
27
+ deprecated: string | boolean;
28
+ }
29
+ export interface JsonHelp extends JsonHelpDescription {
30
+ name: string;
31
+ command: string;
32
+ options: JsonHelpOption[];
33
+ subcommands?: JsonHelpSubcommand[];
34
+ }
33
35
  export declare function jsonHelpUsage(): string;
34
36
  export {};
@@ -12,8 +12,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
13
  exports.jsonHelpUsage = void 0;
14
14
  const yargs_1 = __importDefault(require("yargs"));
15
+ const yargsDefaultCommandRegExp = /^\$0|\*/;
15
16
  function jsonHelpUsage() {
16
- var _a, _b, _c;
17
+ var _a, _b, _c, _d, _e;
17
18
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
19
  const localYargs = yargs_1.default;
19
20
  const { deprecatedOptions, alias: aliases, array, string, boolean, number, choices, demandedOptions, default: defaultVal, hiddenOptions = [], } = localYargs.getOptions();
@@ -54,37 +55,40 @@ function jsonHelpUsage() {
54
55
  }
55
56
  // https://github.com/yargs/yargs/blob/00e4ebbe3acd438e73fdb101e75b4f879eb6d345/lib/usage.ts#L124
56
57
  const subcommands = usageInstance.getCommands()
57
- .map(([name, description, _, aliases, deprecated]) => ({
58
- name: name.split(' ', 1)[0],
59
- command: name,
60
- description,
58
+ .map(([name, rawDescription, isDefault, aliases, deprecated]) => ({
59
+ name: name.split(' ', 1)[0].replace(yargsDefaultCommandRegExp, ''),
60
+ command: name.replace(yargsDefaultCommandRegExp, ''),
61
+ default: isDefault || undefined,
62
+ ...parseDescription(rawDescription),
61
63
  aliases,
62
64
  deprecated,
63
65
  }))
64
66
  .sort((a, b) => a.name.localeCompare(b.name));
65
- const parseDescription = (rawDescription) => {
66
- try {
67
- const { longDescription, describe: shortDescription, longDescriptionRelativePath, } = JSON.parse(rawDescription);
68
- return {
69
- shortDescription,
70
- longDescriptionRelativePath,
71
- longDescription,
72
- };
73
- }
74
- catch {
75
- return {
76
- shortDescription: rawDescription,
77
- };
78
- }
79
- };
80
67
  const [command, rawDescription] = (_c = usageInstance.getUsage()[0]) !== null && _c !== void 0 ? _c : [];
68
+ const defaultSubCommand = (_e = (_d = subcommands.find((x) => x.default)) === null || _d === void 0 ? void 0 : _d.command) !== null && _e !== void 0 ? _e : '';
69
+ const otherSubcommands = subcommands.filter((s) => !s.default);
81
70
  const output = {
82
71
  name: [...context.commands].pop(),
83
- command: command === null || command === void 0 ? void 0 : command.replace('$0', localYargs['$0']),
72
+ command: `${command === null || command === void 0 ? void 0 : command.replace(yargsDefaultCommandRegExp, localYargs['$0'])}${defaultSubCommand}`,
84
73
  ...parseDescription(rawDescription),
85
74
  options: normalizeOptions.sort((a, b) => a.name.localeCompare(b.name)),
86
- subcommands: subcommands.length ? subcommands : undefined,
75
+ subcommands: otherSubcommands.length ? otherSubcommands : undefined,
87
76
  };
88
77
  return JSON.stringify(output, undefined, 2);
89
78
  }
90
79
  exports.jsonHelpUsage = jsonHelpUsage;
80
+ function parseDescription(rawDescription) {
81
+ try {
82
+ const { longDescription, describe: shortDescription, longDescriptionRelativePath, } = JSON.parse(rawDescription);
83
+ return {
84
+ shortDescription,
85
+ longDescriptionRelativePath,
86
+ longDescription,
87
+ };
88
+ }
89
+ catch {
90
+ return {
91
+ shortDescription: rawDescription,
92
+ };
93
+ }
94
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @license
3
+ * Copyright Google LLC All Rights Reserved.
4
+ *
5
+ * Use of this source code is governed by an MIT-style license that can be
6
+ * found in the LICENSE file at https://angular.io/license
7
+ */
8
+ import { logging } from '@angular-devkit/core';
9
+ import { NodeWorkflow } from '@angular-devkit/schematics/tools';
10
+ export declare function subscribeToWorkflow(workflow: NodeWorkflow, logger: logging.LoggerApi): {
11
+ files: Set<string>;
12
+ error: boolean;
13
+ unsubscribe: () => void;
14
+ };
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright Google LLC All Rights Reserved.
5
+ *
6
+ * Use of this source code is governed by an MIT-style license that can be
7
+ * found in the LICENSE file at https://angular.io/license
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.subscribeToWorkflow = void 0;
11
+ const core_1 = require("@angular-devkit/core");
12
+ const color_1 = require("../../utilities/color");
13
+ function subscribeToWorkflow(workflow, logger) {
14
+ const files = new Set();
15
+ let error = false;
16
+ let logs = [];
17
+ const reporterSubscription = workflow.reporter.subscribe((event) => {
18
+ // Strip leading slash to prevent confusion.
19
+ const eventPath = event.path.charAt(0) === '/' ? event.path.substring(1) : event.path;
20
+ switch (event.kind) {
21
+ case 'error':
22
+ error = true;
23
+ const desc = event.description == 'alreadyExist' ? 'already exists' : 'does not exist';
24
+ logger.error(`ERROR! ${eventPath} ${desc}.`);
25
+ break;
26
+ case 'update':
27
+ logs.push(core_1.tags.oneLine `
28
+ ${color_1.colors.cyan('UPDATE')} ${eventPath} (${event.content.length} bytes)
29
+ `);
30
+ files.add(eventPath);
31
+ break;
32
+ case 'create':
33
+ logs.push(core_1.tags.oneLine `
34
+ ${color_1.colors.green('CREATE')} ${eventPath} (${event.content.length} bytes)
35
+ `);
36
+ files.add(eventPath);
37
+ break;
38
+ case 'delete':
39
+ logs.push(`${color_1.colors.yellow('DELETE')} ${eventPath}`);
40
+ files.add(eventPath);
41
+ break;
42
+ case 'rename':
43
+ const eventToPath = event.to.charAt(0) === '/' ? event.to.substring(1) : event.to;
44
+ logs.push(`${color_1.colors.blue('RENAME')} ${eventPath} => ${eventToPath}`);
45
+ files.add(eventPath);
46
+ break;
47
+ }
48
+ });
49
+ const lifecycleSubscription = workflow.lifeCycle.subscribe((event) => {
50
+ if (event.kind == 'end' || event.kind == 'post-tasks-start') {
51
+ if (!error) {
52
+ // Output the logging queue, no error happened.
53
+ logs.forEach((log) => logger.info(log));
54
+ }
55
+ logs = [];
56
+ error = false;
57
+ }
58
+ });
59
+ return {
60
+ files,
61
+ error,
62
+ unsubscribe: () => {
63
+ reporterSubscription.unsubscribe();
64
+ lifecycleSubscription.unsubscribe();
65
+ },
66
+ };
67
+ }
68
+ exports.subscribeToWorkflow = subscribeToWorkflow;
@@ -8,7 +8,7 @@
8
8
  import { Argv } from 'yargs';
9
9
  import { CommandModuleImplementation, Options, OtherOptions } from '../../command-builder/command-module';
10
10
  import { SchematicsCommandArgs, SchematicsCommandModule } from '../../command-builder/schematics-command-module';
11
- export interface AddCommandArgs extends SchematicsCommandArgs {
11
+ interface AddCommandArgs extends SchematicsCommandArgs {
12
12
  collection: string;
13
13
  verbose?: boolean;
14
14
  registry?: string;
@@ -18,6 +18,16 @@ export declare class AddCommandModule extends SchematicsCommandModule implements
18
18
  command: string;
19
19
  describe: string;
20
20
  longDescriptionPath: string;
21
+ protected allowPrivateSchematics: boolean;
22
+ private readonly schematicName;
21
23
  builder(argv: Argv): Promise<Argv<AddCommandArgs>>;
22
24
  run(options: Options<AddCommandArgs> & OtherOptions): Promise<number | void>;
25
+ private isProjectVersionValid;
26
+ reportAnalytics(options: OtherOptions, paths: string[]): Promise<void>;
27
+ private getCollectionName;
28
+ private isPackageInstalled;
29
+ private executeSchematic;
30
+ private findProjectVersion;
31
+ private hasMismatchedPeer;
23
32
  }
33
+ export {};
@@ -6,21 +6,44 @@
6
6
  * Use of this source code is governed by an MIT-style license that can be
7
7
  * found in the LICENSE file at https://angular.io/license
8
8
  */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
9
12
  Object.defineProperty(exports, "__esModule", { value: true });
10
13
  exports.AddCommandModule = void 0;
14
+ const core_1 = require("@angular-devkit/core");
15
+ const tools_1 = require("@angular-devkit/schematics/tools");
16
+ const npm_package_arg_1 = __importDefault(require("npm-package-arg"));
11
17
  const path_1 = require("path");
18
+ const semver_1 = require("semver");
19
+ const workspace_schema_1 = require("../../../lib/config/workspace-schema");
20
+ const analytics_1 = require("../../analytics/analytics");
12
21
  const schematics_command_module_1 = require("../../command-builder/schematics-command-module");
13
- const add_impl_1 = require("./add-impl");
22
+ const color_1 = require("../../utilities/color");
23
+ const package_metadata_1 = require("../../utilities/package-metadata");
24
+ const prompt_1 = require("../../utilities/prompt");
25
+ const spinner_1 = require("../../utilities/spinner");
26
+ const tty_1 = require("../../utilities/tty");
27
+ /**
28
+ * The set of packages that should have certain versions excluded from consideration
29
+ * when attempting to find a compatible version for a package.
30
+ * The key is a package name and the value is a SemVer range of versions to exclude.
31
+ */
32
+ const packageVersionExclusions = {
33
+ // @angular/localize@9.x versions do not have peer dependencies setup
34
+ '@angular/localize': '9.x',
35
+ };
14
36
  class AddCommandModule extends schematics_command_module_1.SchematicsCommandModule {
15
37
  constructor() {
16
38
  super(...arguments);
17
39
  this.command = 'add <collection>';
18
40
  this.describe = 'Adds support for an external library to your project.';
19
41
  this.longDescriptionPath = (0, path_1.join)(__dirname, 'long-description.md');
42
+ this.allowPrivateSchematics = true;
43
+ this.schematicName = 'ng-add';
20
44
  }
21
45
  async builder(argv) {
22
- const localYargs = await super.builder(argv);
23
- return localYargs
46
+ const localYargs = (await super.builder(argv))
24
47
  .positional('collection', {
25
48
  description: 'The package to be added.',
26
49
  type: 'string',
@@ -38,11 +61,307 @@ class AddCommandModule extends schematics_command_module_1.SchematicsCommandModu
38
61
  type: 'boolean',
39
62
  default: false,
40
63
  })
64
+ // Prior to downloading we don't know the full schema and therefore we cannot be strict on the options.
65
+ // Possibly in the future update the logic to use the following syntax:
66
+ // `ng add @angular/localize -- --package-options`.
41
67
  .strict(false);
68
+ const collectionName = await this.getCollectionName();
69
+ const workflow = await this.getOrCreateWorkflowForBuilder(collectionName);
70
+ try {
71
+ const collection = workflow.engine.createCollection(collectionName);
72
+ const options = await this.getSchematicOptions(collection, this.schematicName, workflow);
73
+ return this.addSchemaOptionsToCommand(localYargs, options);
74
+ }
75
+ catch (error) {
76
+ // During `ng add` prior to the downloading of the package
77
+ // we are not able to resolve and create a collection.
78
+ // Or when the the collection value is a path to a tarball.
79
+ }
80
+ return localYargs;
81
+ }
82
+ // eslint-disable-next-line max-lines-per-function
83
+ async run(options) {
84
+ var _a;
85
+ const { logger, packageManager } = this.context;
86
+ const { verbose, registry, collection, skipConfirmation } = options;
87
+ packageManager.ensureCompatibility();
88
+ let packageIdentifier;
89
+ try {
90
+ packageIdentifier = (0, npm_package_arg_1.default)(collection);
91
+ }
92
+ catch (e) {
93
+ logger.error(e.message);
94
+ return 1;
95
+ }
96
+ if (packageIdentifier.name &&
97
+ packageIdentifier.registry &&
98
+ this.isPackageInstalled(packageIdentifier.name)) {
99
+ const validVersion = await this.isProjectVersionValid(packageIdentifier);
100
+ if (validVersion) {
101
+ // Already installed so just run schematic
102
+ logger.info('Skipping installation: Package already installed');
103
+ return this.executeSchematic({ ...options, collection: packageIdentifier.name });
104
+ }
105
+ }
106
+ const spinner = new spinner_1.Spinner();
107
+ spinner.start('Determining package manager...');
108
+ const usingYarn = packageManager.name === workspace_schema_1.PackageManager.Yarn;
109
+ spinner.info(`Using package manager: ${color_1.colors.grey(packageManager.name)}`);
110
+ if (packageIdentifier.name && packageIdentifier.type === 'tag' && !packageIdentifier.rawSpec) {
111
+ // only package name provided; search for viable version
112
+ // plus special cases for packages that did not have peer deps setup
113
+ spinner.start('Searching for compatible package version...');
114
+ let packageMetadata;
115
+ try {
116
+ packageMetadata = await (0, package_metadata_1.fetchPackageMetadata)(packageIdentifier.name, logger, {
117
+ registry,
118
+ usingYarn,
119
+ verbose,
120
+ });
121
+ }
122
+ catch (e) {
123
+ spinner.fail(`Unable to load package information from registry: ${e.message}`);
124
+ return 1;
125
+ }
126
+ // Start with the version tagged as `latest` if it exists
127
+ const latestManifest = packageMetadata.tags['latest'];
128
+ if (latestManifest) {
129
+ packageIdentifier = npm_package_arg_1.default.resolve(latestManifest.name, latestManifest.version);
130
+ }
131
+ // Adjust the version based on name and peer dependencies
132
+ if ((latestManifest === null || latestManifest === void 0 ? void 0 : latestManifest.peerDependencies) &&
133
+ Object.keys(latestManifest.peerDependencies).length === 0) {
134
+ spinner.succeed(`Found compatible package version: ${color_1.colors.grey(packageIdentifier.toString())}.`);
135
+ }
136
+ else if (!latestManifest || (await this.hasMismatchedPeer(latestManifest))) {
137
+ // 'latest' is invalid so search for most recent matching package
138
+ const versionExclusions = packageVersionExclusions[packageMetadata.name];
139
+ const versionManifests = Object.values(packageMetadata.versions).filter((value) => {
140
+ // Prerelease versions are not stable and should not be considered by default
141
+ if ((0, semver_1.prerelease)(value.version)) {
142
+ return false;
143
+ }
144
+ // Deprecated versions should not be used or considered
145
+ if (value.deprecated) {
146
+ return false;
147
+ }
148
+ // Excluded package versions should not be considered
149
+ if (versionExclusions && (0, semver_1.satisfies)(value.version, versionExclusions)) {
150
+ return false;
151
+ }
152
+ return true;
153
+ });
154
+ versionManifests.sort((a, b) => (0, semver_1.compare)(a.version, b.version, true));
155
+ let newIdentifier;
156
+ for (const versionManifest of versionManifests) {
157
+ if (!(await this.hasMismatchedPeer(versionManifest))) {
158
+ newIdentifier = npm_package_arg_1.default.resolve(versionManifest.name, versionManifest.version);
159
+ break;
160
+ }
161
+ }
162
+ if (!newIdentifier) {
163
+ spinner.warn("Unable to find compatible package. Using 'latest' tag.");
164
+ }
165
+ else {
166
+ packageIdentifier = newIdentifier;
167
+ spinner.succeed(`Found compatible package version: ${color_1.colors.grey(packageIdentifier.toString())}.`);
168
+ }
169
+ }
170
+ else {
171
+ spinner.succeed(`Found compatible package version: ${color_1.colors.grey(packageIdentifier.toString())}.`);
172
+ }
173
+ }
174
+ let collectionName = packageIdentifier.name;
175
+ let savePackage;
176
+ try {
177
+ spinner.start('Loading package information from registry...');
178
+ const manifest = await (0, package_metadata_1.fetchPackageManifest)(packageIdentifier.toString(), logger, {
179
+ registry,
180
+ verbose,
181
+ usingYarn,
182
+ });
183
+ savePackage = (_a = manifest['ng-add']) === null || _a === void 0 ? void 0 : _a.save;
184
+ collectionName = manifest.name;
185
+ if (await this.hasMismatchedPeer(manifest)) {
186
+ spinner.warn('Package has unmet peer dependencies. Adding the package may not succeed.');
187
+ }
188
+ else {
189
+ spinner.succeed(`Package information loaded.`);
190
+ }
191
+ }
192
+ catch (e) {
193
+ spinner.fail(`Unable to fetch package information for '${packageIdentifier}': ${e.message}`);
194
+ return 1;
195
+ }
196
+ if (!skipConfirmation) {
197
+ const confirmationResponse = await (0, prompt_1.askConfirmation)(`\nThe package ${color_1.colors.blue(packageIdentifier.raw)} will be installed and executed.\n` +
198
+ 'Would you like to proceed?', true, false);
199
+ if (!confirmationResponse) {
200
+ if (!(0, tty_1.isTTY)()) {
201
+ logger.error('No terminal detected. ' +
202
+ `'--skip-confirmation' can be used to bypass installation confirmation. ` +
203
+ `Ensure package name is correct prior to '--skip-confirmation' option usage.`);
204
+ }
205
+ logger.error('Command aborted.');
206
+ return 1;
207
+ }
208
+ }
209
+ if (savePackage === false) {
210
+ // Temporary packages are located in a different directory
211
+ // Hence we need to resolve them using the temp path
212
+ const { success, tempNodeModules } = await packageManager.installTemp(packageIdentifier.raw, registry ? [`--registry="${registry}"`] : undefined);
213
+ const resolvedCollectionPath = require.resolve((0, path_1.join)(collectionName, 'package.json'), {
214
+ paths: [tempNodeModules],
215
+ });
216
+ if (!success) {
217
+ return 1;
218
+ }
219
+ collectionName = (0, path_1.dirname)(resolvedCollectionPath);
220
+ }
221
+ else {
222
+ const success = await packageManager.install(packageIdentifier.raw, savePackage, registry ? [`--registry="${registry}"`] : undefined);
223
+ if (!success) {
224
+ return 1;
225
+ }
226
+ }
227
+ return this.executeSchematic({ ...options, collection: collectionName });
228
+ }
229
+ async isProjectVersionValid(packageIdentifier) {
230
+ if (!packageIdentifier.name) {
231
+ return false;
232
+ }
233
+ let validVersion = false;
234
+ const installedVersion = await this.findProjectVersion(packageIdentifier.name);
235
+ if (installedVersion) {
236
+ if (packageIdentifier.type === 'range' && packageIdentifier.fetchSpec) {
237
+ validVersion = (0, semver_1.satisfies)(installedVersion, packageIdentifier.fetchSpec);
238
+ }
239
+ else if (packageIdentifier.type === 'version') {
240
+ const v1 = (0, semver_1.valid)(packageIdentifier.fetchSpec);
241
+ const v2 = (0, semver_1.valid)(installedVersion);
242
+ validVersion = v1 !== null && v1 === v2;
243
+ }
244
+ else if (!packageIdentifier.rawSpec) {
245
+ validVersion = true;
246
+ }
247
+ }
248
+ return validVersion;
249
+ }
250
+ async reportAnalytics(options, paths) {
251
+ const collection = await this.getCollectionName();
252
+ const dimensions = [];
253
+ // Add the collection if it's safe listed.
254
+ if (collection && (0, analytics_1.isPackageNameSafeForAnalytics)(collection)) {
255
+ dimensions[core_1.analytics.NgCliAnalyticsDimensions.NgAddCollection] = collection;
256
+ }
257
+ return super.reportAnalytics(options, paths, dimensions);
258
+ }
259
+ async getCollectionName() {
260
+ const [, collectionName] = this.context.args.positional;
261
+ return collectionName;
262
+ }
263
+ isPackageInstalled(name) {
264
+ try {
265
+ require.resolve((0, path_1.join)(name, 'package.json'), { paths: [this.context.root] });
266
+ return true;
267
+ }
268
+ catch (e) {
269
+ if (e.code !== 'MODULE_NOT_FOUND') {
270
+ throw e;
271
+ }
272
+ }
273
+ return false;
274
+ }
275
+ async executeSchematic(options) {
276
+ try {
277
+ const { verbose, skipConfirmation, interactive, force, dryRun, registry, defaults, collection: collectionName, ...schematicOptions } = options;
278
+ return await this.runSchematic({
279
+ schematicOptions,
280
+ schematicName: this.schematicName,
281
+ collectionName,
282
+ executionOptions: {
283
+ interactive,
284
+ force,
285
+ dryRun,
286
+ defaults,
287
+ packageRegistry: registry,
288
+ },
289
+ });
290
+ }
291
+ catch (e) {
292
+ if (e instanceof tools_1.NodePackageDoesNotSupportSchematics) {
293
+ this.context.logger.error(core_1.tags.oneLine `
294
+ The package that you are trying to add does not support schematics. You can try using
295
+ a different version of the package or contact the package author to add ng-add support.
296
+ `);
297
+ return 1;
298
+ }
299
+ throw e;
300
+ }
301
+ }
302
+ async findProjectVersion(name) {
303
+ var _a, _b;
304
+ const { logger, root } = this.context;
305
+ let installedPackage;
306
+ try {
307
+ installedPackage = require.resolve((0, path_1.join)(name, 'package.json'), {
308
+ paths: [root],
309
+ });
310
+ }
311
+ catch { }
312
+ if (installedPackage) {
313
+ try {
314
+ const installed = await (0, package_metadata_1.fetchPackageManifest)((0, path_1.dirname)(installedPackage), logger);
315
+ return installed.version;
316
+ }
317
+ catch { }
318
+ }
319
+ let projectManifest;
320
+ try {
321
+ projectManifest = await (0, package_metadata_1.fetchPackageManifest)(root, logger);
322
+ }
323
+ catch { }
324
+ if (projectManifest) {
325
+ const version = ((_a = projectManifest.dependencies) === null || _a === void 0 ? void 0 : _a[name]) || ((_b = projectManifest.devDependencies) === null || _b === void 0 ? void 0 : _b[name]);
326
+ if (version) {
327
+ return version;
328
+ }
329
+ }
330
+ return null;
42
331
  }
43
- run(options) {
44
- const command = new add_impl_1.AddCommandModule(this.context, 'add');
45
- return command.validateAndRun(options);
332
+ async hasMismatchedPeer(manifest) {
333
+ for (const peer in manifest.peerDependencies) {
334
+ let peerIdentifier;
335
+ try {
336
+ peerIdentifier = npm_package_arg_1.default.resolve(peer, manifest.peerDependencies[peer]);
337
+ }
338
+ catch {
339
+ this.context.logger.warn(`Invalid peer dependency ${peer} found in package.`);
340
+ continue;
341
+ }
342
+ if (peerIdentifier.type === 'version' || peerIdentifier.type === 'range') {
343
+ try {
344
+ const version = await this.findProjectVersion(peer);
345
+ if (!version) {
346
+ continue;
347
+ }
348
+ const options = { includePrerelease: true };
349
+ if (!(0, semver_1.intersects)(version, peerIdentifier.rawSpec, options) &&
350
+ !(0, semver_1.satisfies)(version, peerIdentifier.rawSpec, options)) {
351
+ return true;
352
+ }
353
+ }
354
+ catch {
355
+ // Not found or invalid so ignore
356
+ continue;
357
+ }
358
+ }
359
+ else {
360
+ // type === 'tag' | 'file' | 'directory' | 'remote' | 'git'
361
+ // Cannot accurately compare these as the tag/location may have changed since install
362
+ }
363
+ }
364
+ return false;
46
365
  }
47
366
  }
48
367
  exports.AddCommandModule = AddCommandModule;
@@ -1,10 +1,7 @@
1
1
  Adds the npm package for a published library to your workspace, and configures
2
- the project in the current working directory (or the default project if you are
3
- not in a project directory) to use that library, as specified by the library's schematic.
2
+ the project in the current working directory to use that library, as specified by the library's schematic.
4
3
  For example, adding `@angular/pwa` configures your project for PWA support:
5
4
 
6
5
  ```bash
7
6
  ng add @angular/pwa
8
7
  ```
9
-
10
- The default project is the value of `defaultProject` in `angular.json`.
@@ -6,16 +6,11 @@
6
6
  * found in the LICENSE file at https://angular.io/license
7
7
  */
8
8
  import { Argv } from 'yargs';
9
- import { CommandModule, Options } from '../../command-builder/command-module';
10
- interface AnalyticsCommandArgs {
11
- 'setting-or-project': 'on' | 'off' | 'ci' | 'project' | 'prompt' | string;
12
- 'project-setting'?: 'on' | 'off' | 'prompt' | string;
13
- }
14
- export declare class AnalyticsCommandModule extends CommandModule<AnalyticsCommandArgs> {
9
+ import { CommandModule, CommandModuleImplementation, Options } from '../../command-builder/command-module';
10
+ export declare class AnalyticsCommandModule extends CommandModule implements CommandModuleImplementation {
15
11
  command: string;
16
12
  describe: string;
17
- longDescriptionPath: string;
18
- builder(localYargs: Argv): Argv<AnalyticsCommandArgs>;
19
- run({ settingOrProject, projectSetting, }: Options<AnalyticsCommandArgs>): Promise<number | void>;
13
+ longDescriptionPath?: string;
14
+ builder(localYargs: Argv): Argv;
15
+ run(_options: Options<{}>): void;
20
16
  }
21
- export {};