@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
@@ -8,7 +8,11 @@
8
8
  */
9
9
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
10
  if (k2 === undefined) k2 = k;
11
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
12
16
  }) : (function(o, m, k, k2) {
13
17
  if (k2 === undefined) k2 = k;
14
18
  o[k2] = m[k];
@@ -29,13 +33,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
29
33
  return (mod && mod.__esModule) ? mod : { "default": mod };
30
34
  };
31
35
  Object.defineProperty(exports, "__esModule", { value: true });
32
- exports.createAnalytics = exports.getSharedAnalytics = exports.getWorkspaceAnalytics = exports.hasWorkspaceAnalyticsConfiguration = exports.getGlobalAnalytics = exports.hasGlobalAnalyticsConfiguration = exports.promptProjectAnalytics = exports.promptGlobalAnalytics = exports.setAnalyticsConfig = exports.isPackageNameSafeForAnalytics = exports.analyticsPackageSafelist = exports.AnalyticsProperties = void 0;
36
+ exports.getAnalyticsInfoString = exports.createAnalytics = exports.getSharedAnalytics = exports.getAnalytics = exports.promptAnalytics = exports.setAnalyticsConfig = exports.isPackageNameSafeForAnalytics = exports.analyticsPackageSafelist = exports.AnalyticsProperties = void 0;
33
37
  const core_1 = require("@angular-devkit/core");
34
38
  const debug_1 = __importDefault(require("debug"));
35
- const inquirer = __importStar(require("inquirer"));
36
39
  const uuid_1 = require("uuid");
37
40
  const color_1 = require("../utilities/color");
38
41
  const config_1 = require("../utilities/config");
42
+ const environment_options_1 = require("../utilities/environment-options");
39
43
  const tty_1 = require("../utilities/tty");
40
44
  const version_1 = require("../utilities/version");
41
45
  const analytics_collector_1 = require("./analytics-collector");
@@ -51,12 +55,10 @@ exports.AnalyticsProperties = {
51
55
  }
52
56
  const v = version_1.VERSION.full;
53
57
  // The logic is if it's a full version then we should use the prod GA property.
54
- if (/^\d+\.\d+\.\d+$/.test(v) && v !== '0.0.0') {
55
- _defaultAngularCliPropertyCache = exports.AnalyticsProperties.AngularCliProd;
56
- }
57
- else {
58
- _defaultAngularCliPropertyCache = exports.AnalyticsProperties.AngularCliStaging;
59
- }
58
+ _defaultAngularCliPropertyCache =
59
+ /^\d+\.\d+\.\d+$/.test(v) && v !== '0.0.0'
60
+ ? exports.AnalyticsProperties.AngularCliProd
61
+ : exports.AnalyticsProperties.AngularCliStaging;
60
62
  return _defaultAngularCliPropertyCache;
61
63
  },
62
64
  };
@@ -82,10 +84,11 @@ function isPackageNameSafeForAnalytics(name) {
82
84
  exports.isPackageNameSafeForAnalytics = isPackageNameSafeForAnalytics;
83
85
  /**
84
86
  * Set analytics settings. This does not work if the user is not inside a project.
85
- * @param level Which config to use. "global" for user-level, and "local" for project-level.
87
+ * @param global Which config to use. "global" for user-level, and "local" for project-level.
86
88
  * @param value Either a user ID, true to generate a new User ID, or false to disable analytics.
87
89
  */
88
- function setAnalyticsConfig(level, value) {
90
+ function setAnalyticsConfig(global, value) {
91
+ const level = global ? 'global' : 'local';
89
92
  analyticsDebug('setting %s level analytics to: %s', level, value);
90
93
  const [config, configPath] = (0, config_1.getWorkspaceRaw)(level);
91
94
  if (!config || !configPath) {
@@ -108,84 +111,36 @@ exports.setAnalyticsConfig = setAnalyticsConfig;
108
111
  * @param force Whether to ask regardless of whether or not the user is using an interactive shell.
109
112
  * @return Whether or not the user was shown a prompt.
110
113
  */
111
- async function promptGlobalAnalytics(force = false) {
112
- analyticsDebug('prompting global analytics.');
113
- if (force || (0, tty_1.isTTY)()) {
114
- const answers = await inquirer.prompt([
115
- {
116
- type: 'confirm',
117
- name: 'analytics',
118
- message: core_1.tags.stripIndents `
119
- Would you like to share anonymous usage data with the Angular Team at Google under
120
- Google’s Privacy Policy at https://policies.google.com/privacy? For more details and
121
- how to change this setting, see https://angular.io/analytics.
122
- `,
123
- default: false,
124
- },
125
- ]);
126
- setAnalyticsConfig('global', answers.analytics);
127
- if (answers.analytics) {
128
- console.log('');
129
- console.log(core_1.tags.stripIndent `
130
- Thank you for sharing anonymous usage data. If you change your mind, the following
131
- command will disable this feature entirely:
132
-
133
- ${color_1.colors.yellow('ng analytics off')}
134
- `);
135
- console.log('');
136
- // Send back a ping with the user `optin`.
137
- const ua = new analytics_collector_1.AnalyticsCollector(exports.AnalyticsProperties.AngularCliDefault, 'optin');
138
- ua.pageview('/telemetry/optin');
139
- await ua.flush();
140
- }
141
- else {
142
- // Send back a ping with the user `optout`. This is the only thing we send.
143
- const ua = new analytics_collector_1.AnalyticsCollector(exports.AnalyticsProperties.AngularCliDefault, 'optout');
144
- ua.pageview('/telemetry/optout');
145
- await ua.flush();
146
- }
147
- return true;
148
- }
149
- else {
150
- analyticsDebug('Either STDOUT or STDIN are not TTY and we skipped the prompt.');
151
- }
152
- return false;
153
- }
154
- exports.promptGlobalAnalytics = promptGlobalAnalytics;
155
- /**
156
- * Prompt the user for usage gathering permission for the local project. Fails if there is no
157
- * local workspace.
158
- * @param force Whether to ask regardless of whether or not the user is using an interactive shell.
159
- * @return Whether or not the user was shown a prompt.
160
- */
161
- async function promptProjectAnalytics(force = false) {
114
+ async function promptAnalytics(global, force = false) {
162
115
  analyticsDebug('prompting user');
163
- const [config, configPath] = (0, config_1.getWorkspaceRaw)('local');
116
+ const level = global ? 'global' : 'local';
117
+ const [config, configPath] = (0, config_1.getWorkspaceRaw)(level);
164
118
  if (!config || !configPath) {
165
- throw new Error(`Could not find a local workspace. Are you in a project?`);
119
+ throw new Error(`Could not find a ${level} workspace. Are you in a project?`);
166
120
  }
167
121
  if (force || (0, tty_1.isTTY)()) {
168
- const answers = await inquirer.prompt([
122
+ const { prompt } = await Promise.resolve().then(() => __importStar(require('inquirer')));
123
+ const answers = await prompt([
169
124
  {
170
125
  type: 'confirm',
171
126
  name: 'analytics',
172
127
  message: core_1.tags.stripIndents `
173
128
  Would you like to share anonymous usage data about this project with the Angular Team at
174
- Google under Google’s Privacy Policy at https://policies.google.com/privacy? For more
129
+ Google under Google’s Privacy Policy at https://policies.google.com/privacy. For more
175
130
  details and how to change this setting, see https://angular.io/analytics.
176
131
 
177
132
  `,
178
133
  default: false,
179
134
  },
180
135
  ]);
181
- setAnalyticsConfig('local', answers.analytics);
136
+ setAnalyticsConfig(global, answers.analytics);
182
137
  if (answers.analytics) {
183
138
  console.log('');
184
139
  console.log(core_1.tags.stripIndent `
185
140
  Thank you for sharing anonymous usage data. Should you change your mind, the following
186
141
  command will disable this feature entirely:
187
142
 
188
- ${color_1.colors.yellow('ng analytics project off')}
143
+ ${color_1.colors.yellow(`ng analytics disable${global ? ' --global' : ''}`)}
189
144
  `);
190
145
  console.log('');
191
146
  // Send back a ping with the user `optin`.
@@ -199,109 +154,34 @@ async function promptProjectAnalytics(force = false) {
199
154
  ua.pageview('/telemetry/project/optout');
200
155
  await ua.flush();
201
156
  }
157
+ process.stderr.write(await getAnalyticsInfoString());
202
158
  return true;
203
159
  }
204
160
  return false;
205
161
  }
206
- exports.promptProjectAnalytics = promptProjectAnalytics;
207
- async function hasGlobalAnalyticsConfiguration() {
208
- try {
209
- const globalWorkspace = await (0, config_1.getWorkspace)('global');
210
- const analyticsConfig = globalWorkspace && globalWorkspace.getCli() && globalWorkspace.getCli()['analytics'];
211
- if (analyticsConfig !== null && analyticsConfig !== undefined) {
212
- return true;
213
- }
214
- }
215
- catch { }
216
- return false;
217
- }
218
- exports.hasGlobalAnalyticsConfiguration = hasGlobalAnalyticsConfiguration;
162
+ exports.promptAnalytics = promptAnalytics;
219
163
  /**
220
- * Get the global analytics object for the user. This returns an instance of UniversalAnalytics,
221
- * or undefined if analytics are disabled.
164
+ * Get the analytics object for the user.
222
165
  *
223
- * If any problem happens, it is considered the user has been opting out of analytics.
166
+ * @returns
167
+ * - `AnalyticsCollector` when enabled.
168
+ * - `analytics.NoopAnalytics` when disabled.
169
+ * - `undefined` when not configured.
224
170
  */
225
- async function getGlobalAnalytics() {
226
- analyticsDebug('getGlobalAnalytics');
227
- const propertyId = exports.AnalyticsProperties.AngularCliDefault;
228
- if ('NG_CLI_ANALYTICS' in process.env) {
229
- if (process.env['NG_CLI_ANALYTICS'] == 'false' || process.env['NG_CLI_ANALYTICS'] == '') {
230
- analyticsDebug('NG_CLI_ANALYTICS is false');
231
- return undefined;
232
- }
233
- if (process.env['NG_CLI_ANALYTICS'] === 'ci') {
234
- analyticsDebug('Running in CI mode');
235
- return new analytics_collector_1.AnalyticsCollector(propertyId, 'ci');
236
- }
237
- }
238
- // If anything happens we just keep the NOOP analytics.
239
- try {
240
- const globalWorkspace = await (0, config_1.getWorkspace)('global');
241
- const analyticsConfig = globalWorkspace && globalWorkspace.getCli() && globalWorkspace.getCli()['analytics'];
242
- analyticsDebug('Client Analytics config found: %j', analyticsConfig);
243
- if (analyticsConfig === false) {
244
- analyticsDebug('Analytics disabled. Ignoring all analytics.');
245
- return undefined;
246
- }
247
- else if (analyticsConfig === undefined || analyticsConfig === null) {
248
- analyticsDebug('Analytics settings not found. Ignoring all analytics.');
249
- // globalWorkspace can be null if there is no file. analyticsConfig would be null in this
250
- // case. Since there is no file, the user hasn't answered and the expected return value is
251
- // undefined.
252
- return undefined;
253
- }
254
- else {
255
- let uid = undefined;
256
- if (typeof analyticsConfig == 'string') {
257
- uid = analyticsConfig;
258
- }
259
- else if (typeof analyticsConfig == 'object' && typeof analyticsConfig['uid'] == 'string') {
260
- uid = analyticsConfig['uid'];
261
- }
262
- analyticsDebug('client id: %j', uid);
263
- if (uid == undefined) {
264
- return undefined;
265
- }
266
- return new analytics_collector_1.AnalyticsCollector(propertyId, uid);
267
- }
268
- }
269
- catch (err) {
270
- analyticsDebug('Error happened during reading of analytics config: %s', err.message);
271
- return undefined;
272
- }
273
- }
274
- exports.getGlobalAnalytics = getGlobalAnalytics;
275
- async function hasWorkspaceAnalyticsConfiguration() {
276
- try {
277
- const globalWorkspace = await (0, config_1.getWorkspace)('local');
278
- const analyticsConfig = globalWorkspace && globalWorkspace.getCli() && globalWorkspace.getCli()['analytics'];
279
- if (analyticsConfig !== undefined) {
280
- return true;
281
- }
171
+ async function getAnalytics(level) {
172
+ analyticsDebug('getAnalytics');
173
+ if (environment_options_1.analyticsDisabled) {
174
+ analyticsDebug('NG_CLI_ANALYTICS is false');
175
+ return new core_1.analytics.NoopAnalytics();
282
176
  }
283
- catch { }
284
- return false;
285
- }
286
- exports.hasWorkspaceAnalyticsConfiguration = hasWorkspaceAnalyticsConfiguration;
287
- /**
288
- * Get the workspace analytics object for the user. This returns an instance of AnalyticsCollector,
289
- * or undefined if analytics are disabled.
290
- *
291
- * If any problem happens, it is considered the user has been opting out of analytics.
292
- */
293
- async function getWorkspaceAnalytics() {
294
- analyticsDebug('getWorkspaceAnalytics');
295
177
  try {
296
- const globalWorkspace = await (0, config_1.getWorkspace)('local');
297
- const analyticsConfig = globalWorkspace === null || globalWorkspace === void 0 ? void 0 : globalWorkspace.getCli()['analytics'];
178
+ const workspace = await (0, config_1.getWorkspace)(level);
179
+ const analyticsConfig = workspace === null || workspace === void 0 ? void 0 : workspace.getCli()['analytics'];
298
180
  analyticsDebug('Workspace Analytics config found: %j', analyticsConfig);
299
181
  if (analyticsConfig === false) {
300
- analyticsDebug('Analytics disabled. Ignoring all analytics.');
301
- return undefined;
182
+ return new core_1.analytics.NoopAnalytics();
302
183
  }
303
184
  else if (analyticsConfig === undefined || analyticsConfig === null) {
304
- analyticsDebug('Analytics settings not found. Ignoring all analytics.');
305
185
  return undefined;
306
186
  }
307
187
  else {
@@ -324,19 +204,16 @@ async function getWorkspaceAnalytics() {
324
204
  return undefined;
325
205
  }
326
206
  }
327
- exports.getWorkspaceAnalytics = getWorkspaceAnalytics;
207
+ exports.getAnalytics = getAnalytics;
328
208
  /**
329
209
  * Return the usage analytics sharing setting, which is either a property string (GA-XXXXXXX-XX),
330
210
  * or undefined if no sharing.
331
211
  */
332
212
  async function getSharedAnalytics() {
333
213
  analyticsDebug('getSharedAnalytics');
334
- const envVarName = 'NG_CLI_ANALYTICS_SHARE';
335
- if (envVarName in process.env) {
336
- if (process.env[envVarName] == 'false' || process.env[envVarName] == '') {
337
- analyticsDebug('NG_CLI_ANALYTICS is false');
338
- return undefined;
339
- }
214
+ if (environment_options_1.analyticsShareDisabled) {
215
+ analyticsDebug('NG_CLI_ANALYTICS is false');
216
+ return undefined;
340
217
  }
341
218
  // If anything happens we just keep the NOOP analytics.
342
219
  try {
@@ -357,33 +234,71 @@ async function getSharedAnalytics() {
357
234
  }
358
235
  exports.getSharedAnalytics = getSharedAnalytics;
359
236
  async function createAnalytics(workspace, skipPrompt = false) {
360
- let config = await getGlobalAnalytics();
361
- // If in workspace and global analytics is enabled, defer to workspace level
362
- if (workspace && config) {
363
- const skipAnalytics = skipPrompt ||
364
- (process.env['NG_CLI_ANALYTICS'] &&
365
- (process.env['NG_CLI_ANALYTICS'].toLowerCase() === 'false' ||
366
- process.env['NG_CLI_ANALYTICS'] === '0'));
367
- // TODO: This should honor the `no-interactive` option.
368
- // It is currently not an `ng` option but rather only an option for specific commands.
369
- // The concept of `ng`-wide options are needed to cleanly handle this.
370
- if (!skipAnalytics && !(await hasWorkspaceAnalyticsConfiguration())) {
371
- await promptProjectAnalytics();
237
+ // Global config takes precedence over local config only for the disabled check.
238
+ // IE:
239
+ // global: disabled & local: enabled = disabled
240
+ // global: id: 123 & local: id: 456 = 456
241
+ var _a;
242
+ // check global
243
+ const globalConfig = await getAnalytics('global');
244
+ if (globalConfig instanceof core_1.analytics.NoopAnalytics) {
245
+ return globalConfig;
246
+ }
247
+ let config = globalConfig;
248
+ // Not disabled globally, check locally or not set globally and command is run outside of workspace example: `ng new`
249
+ if (workspace || globalConfig === undefined) {
250
+ const level = workspace ? 'local' : 'global';
251
+ let localOrGlobalConfig = await getAnalytics(level);
252
+ if (localOrGlobalConfig === undefined) {
253
+ if (!skipPrompt) {
254
+ // config is unset, prompt user.
255
+ // TODO: This should honor the `no-interactive` option.
256
+ // It is currently not an `ng` option but rather only an option for specific commands.
257
+ // The concept of `ng`-wide options are needed to cleanly handle this.
258
+ await promptAnalytics(!workspace /** global */);
259
+ localOrGlobalConfig = await getAnalytics(level);
260
+ }
261
+ }
262
+ if (localOrGlobalConfig instanceof core_1.analytics.NoopAnalytics) {
263
+ return localOrGlobalConfig;
264
+ }
265
+ else if (localOrGlobalConfig) {
266
+ // Favor local settings over global when defined.
267
+ config = localOrGlobalConfig;
372
268
  }
373
- config = await getWorkspaceAnalytics();
374
269
  }
270
+ // Get shared analytics
271
+ // TODO: evalute if this should be completly removed.
375
272
  const maybeSharedAnalytics = await getSharedAnalytics();
376
273
  if (config && maybeSharedAnalytics) {
377
274
  return new core_1.analytics.MultiAnalytics([config, maybeSharedAnalytics]);
378
275
  }
379
- else if (config) {
380
- return config;
276
+ return (_a = config !== null && config !== void 0 ? config : maybeSharedAnalytics) !== null && _a !== void 0 ? _a : new core_1.analytics.NoopAnalytics();
277
+ }
278
+ exports.createAnalytics = createAnalytics;
279
+ function analyticsConfigValueToHumanFormat(value) {
280
+ if (value === false) {
281
+ return 'disabled';
381
282
  }
382
- else if (maybeSharedAnalytics) {
383
- return maybeSharedAnalytics;
283
+ else if (typeof value === 'string' || value === true) {
284
+ return 'enabled';
384
285
  }
385
286
  else {
386
- return new core_1.analytics.NoopAnalytics();
287
+ return 'not set';
387
288
  }
388
289
  }
389
- exports.createAnalytics = createAnalytics;
290
+ async function getAnalyticsInfoString() {
291
+ const [globalWorkspace] = (0, config_1.getWorkspaceRaw)('global');
292
+ const [localWorkspace] = (0, config_1.getWorkspaceRaw)('local');
293
+ const globalSetting = globalWorkspace === null || globalWorkspace === void 0 ? void 0 : globalWorkspace.get(['cli', 'analytics']);
294
+ const localSetting = localWorkspace === null || localWorkspace === void 0 ? void 0 : localWorkspace.get(['cli', 'analytics']);
295
+ const analyticsInstance = await createAnalytics(!!localWorkspace /** workspace */, true /** skipPrompt */);
296
+ return (core_1.tags.stripIndents `
297
+ Global setting: ${analyticsConfigValueToHumanFormat(globalSetting)}
298
+ Local setting: ${localWorkspace
299
+ ? analyticsConfigValueToHumanFormat(localSetting)
300
+ : 'No local workspace configuration file.'}
301
+ Effective status: ${analyticsInstance instanceof core_1.analytics.NoopAnalytics ? 'disabled' : 'enabled'}
302
+ ` + '\n');
303
+ }
304
+ exports.getAnalyticsInfoString = getAnalyticsInfoString;
@@ -9,10 +9,14 @@ import { Architect, Target } from '@angular-devkit/architect';
9
9
  import { WorkspaceNodeModulesArchitectHost } from '@angular-devkit/architect/node';
10
10
  import { CommandModule, CommandModuleImplementation, CommandScope, OtherOptions } from './command-module';
11
11
  import { Option } from './utilities/json-schema';
12
+ export interface MissingTargetChoice {
13
+ name: string;
14
+ value: string;
15
+ }
12
16
  export declare abstract class ArchitectBaseCommandModule<T> extends CommandModule<T> implements CommandModuleImplementation<T> {
13
17
  static scope: CommandScope;
14
18
  protected shouldReportAnalytics: boolean;
15
- protected readonly missingErrorTarget: string | undefined;
19
+ protected readonly missingTargetChoices: MissingTargetChoice[] | undefined;
16
20
  protected runSingleTarget(target: Target, options: OtherOptions): Promise<number>;
17
21
  private _architectHost;
18
22
  protected getArchitectHost(): WorkspaceNodeModulesArchitectHost;
@@ -20,4 +24,7 @@ export declare abstract class ArchitectBaseCommandModule<T> extends CommandModul
20
24
  protected getArchitect(): Architect;
21
25
  protected getArchitectTargetOptions(target: Target): Promise<Option[]>;
22
26
  private warnOnMissingNodeModules;
27
+ protected getArchitectTarget(): string;
28
+ protected onMissingTarget(defaultMessage: string): Promise<1>;
29
+ private getMissingTargetPackageToInstall;
23
30
  }
@@ -11,10 +11,12 @@ exports.ArchitectBaseCommandModule = void 0;
11
11
  const architect_1 = require("@angular-devkit/architect");
12
12
  const node_1 = require("@angular-devkit/architect/node");
13
13
  const core_1 = require("@angular-devkit/core");
14
+ const child_process_1 = require("child_process");
14
15
  const fs_1 = require("fs");
15
16
  const path_1 = require("path");
16
17
  const analytics_1 = require("../analytics/analytics");
17
- const package_manager_1 = require("../utilities/package-manager");
18
+ const prompt_1 = require("../utilities/prompt");
19
+ const tty_1 = require("../utilities/tty");
18
20
  const command_module_1 = require("./command-module");
19
21
  const json_schema_1 = require("./utilities/json-schema");
20
22
  class ArchitectBaseCommandModule extends command_module_1.CommandModule {
@@ -23,14 +25,13 @@ class ArchitectBaseCommandModule extends command_module_1.CommandModule {
23
25
  this.shouldReportAnalytics = false;
24
26
  }
25
27
  async runSingleTarget(target, options) {
26
- var _a;
27
28
  const architectHost = await this.getArchitectHost();
28
29
  let builderName;
29
30
  try {
30
31
  builderName = await architectHost.getBuilderNameForTarget(target);
31
32
  }
32
33
  catch (e) {
33
- throw new command_module_1.CommandModuleError((_a = this.missingErrorTarget) !== null && _a !== void 0 ? _a : e.message);
34
+ return this.onMissingTarget(e.message);
34
35
  }
35
36
  await this.reportAnalytics({
36
37
  ...(await architectHost.getOptionsForTarget(target)),
@@ -74,14 +75,14 @@ class ArchitectBaseCommandModule extends command_module_1.CommandModule {
74
75
  }
75
76
  catch (e) {
76
77
  if (e.code === 'MODULE_NOT_FOUND') {
77
- await this.warnOnMissingNodeModules();
78
+ this.warnOnMissingNodeModules();
78
79
  throw new command_module_1.CommandModuleError(`Could not find the '${builderConf}' builder's node package.`);
79
80
  }
80
81
  throw e;
81
82
  }
82
83
  return (0, json_schema_1.parseJsonSchemaToOptions)(new core_1.json.schema.CoreSchemaRegistry(), builderDesc.optionSchema, true);
83
84
  }
84
- async warnOnMissingNodeModules() {
85
+ warnOnMissingNodeModules() {
85
86
  var _a;
86
87
  const basePath = (_a = this.context.workspace) === null || _a === void 0 ? void 0 : _a.basePath;
87
88
  if (!basePath) {
@@ -97,8 +98,61 @@ class ArchitectBaseCommandModule extends command_module_1.CommandModule {
97
98
  (0, fs_1.existsSync)((0, path_1.resolve)(basePath, '.pnp.mjs'))) {
98
99
  return;
99
100
  }
100
- const packageManager = await (0, package_manager_1.getPackageManager)(basePath);
101
- this.context.logger.warn(`Node packages may not be installed. Try installing with '${packageManager} install'.`);
101
+ this.context.logger.warn(`Node packages may not be installed. Try installing with '${this.context.packageManager} install'.`);
102
+ }
103
+ getArchitectTarget() {
104
+ return this.commandName;
105
+ }
106
+ async onMissingTarget(defaultMessage) {
107
+ const { logger } = this.context;
108
+ const choices = this.missingTargetChoices;
109
+ if (!(choices === null || choices === void 0 ? void 0 : choices.length)) {
110
+ logger.error(defaultMessage);
111
+ return 1;
112
+ }
113
+ const missingTargetMessage = `Cannot find "${this.getArchitectTarget()}" target for the specified project.\n` +
114
+ `You can add a package that implements these capabilities.\n\n` +
115
+ `For example:\n` +
116
+ choices.map(({ name, value }) => ` ${name}: ng add ${value}`).join('\n') +
117
+ '\n';
118
+ if ((0, tty_1.isTTY)()) {
119
+ // Use prompts to ask the user if they'd like to install a package.
120
+ logger.warn(missingTargetMessage);
121
+ const packageToInstall = await this.getMissingTargetPackageToInstall(choices);
122
+ if (packageToInstall) {
123
+ // Example run: `ng add @angular-eslint/schematics`.
124
+ const binPath = (0, path_1.resolve)(__dirname, '../../bin/ng.js');
125
+ const { error } = (0, child_process_1.spawnSync)(process.execPath, [binPath, 'add', packageToInstall], {
126
+ stdio: 'inherit',
127
+ });
128
+ if (error) {
129
+ throw error;
130
+ }
131
+ }
132
+ }
133
+ else {
134
+ // Non TTY display error message.
135
+ logger.error(missingTargetMessage);
136
+ }
137
+ return 1;
138
+ }
139
+ async getMissingTargetPackageToInstall(choices) {
140
+ if (choices.length === 1) {
141
+ // Single choice
142
+ const { name, value } = choices[0];
143
+ if (await (0, prompt_1.askConfirmation)(`Would you like to add ${name} now?`, true, false)) {
144
+ return value;
145
+ }
146
+ return null;
147
+ }
148
+ // Multiple choice
149
+ return (0, prompt_1.askQuestion)(`Would you like to add a package with "${this.getArchitectTarget()}" capabilities now?`, [
150
+ {
151
+ name: 'No',
152
+ value: null,
153
+ },
154
+ ...choices,
155
+ ], 0, null);
102
156
  }
103
157
  }
104
158
  exports.ArchitectBaseCommandModule = ArchitectBaseCommandModule;
@@ -17,6 +17,5 @@ export declare abstract class ArchitectCommandModule extends ArchitectBaseComman
17
17
  builder(argv: Argv): Promise<Argv<ArchitectCommandArgs>>;
18
18
  run(options: Options<ArchitectCommandArgs> & OtherOptions): Promise<number | void>;
19
19
  private getArchitectProject;
20
- private getArchitectTarget;
21
20
  private getProjectNamesByTarget;
22
21
  }
@@ -6,8 +6,16 @@
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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
10
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
11
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
12
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
13
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
14
+ };
9
15
  Object.defineProperty(exports, "__esModule", { value: true });
10
16
  exports.ArchitectCommandModule = void 0;
17
+ const config_1 = require("../utilities/config");
18
+ const memoize_1 = require("../utilities/memoize");
11
19
  const architect_base_command_module_1 = require("./architect-base-command-module");
12
20
  const command_module_1 = require("./command-module");
13
21
  class ArchitectCommandModule extends architect_base_command_module_1.ArchitectBaseCommandModule {
@@ -38,7 +46,6 @@ class ArchitectCommandModule extends architect_base_command_module_1.ArchitectBa
38
46
  return this.addSchemaOptionsToCommand(localYargs, schemaOptions);
39
47
  }
40
48
  async run(options) {
41
- var _a;
42
49
  const target = this.getArchitectTarget();
43
50
  const { configuration = '', project, ...architectOptions } = options;
44
51
  if (!project) {
@@ -47,7 +54,7 @@ class ArchitectCommandModule extends architect_base_command_module_1.ArchitectBa
47
54
  let result = 0;
48
55
  const projectNames = this.getProjectNamesByTarget(target);
49
56
  if (!projectNames) {
50
- throw new command_module_1.CommandModuleError((_a = this.missingErrorTarget) !== null && _a !== void 0 ? _a : 'Cannot determine project or target for command.');
57
+ return this.onMissingTarget('Cannot determine project or target for command.');
51
58
  }
52
59
  for (const project of projectNames) {
53
60
  result |= await this.runSingleTarget({ configuration, target, project }, architectOptions);
@@ -74,9 +81,6 @@ class ArchitectCommandModule extends architect_base_command_module_1.ArchitectBa
74
81
  const projectFromTarget = this.getProjectNamesByTarget(target);
75
82
  return (projectFromTarget === null || projectFromTarget === void 0 ? void 0 : projectFromTarget.length) ? projectFromTarget[0] : undefined;
76
83
  }
77
- getArchitectTarget() {
78
- return this.commandName;
79
- }
80
84
  getProjectNamesByTarget(target) {
81
85
  const workspace = this.getWorkspaceOrThrow();
82
86
  const allProjectsForTargetName = [];
@@ -93,18 +97,18 @@ class ArchitectCommandModule extends architect_base_command_module_1.ArchitectBa
93
97
  return allProjectsForTargetName;
94
98
  }
95
99
  else {
96
- // For single target commands, we try the default project first,
97
- // then the full list if it has a single project, then error out.
98
- const maybeDefaultProject = workspace.extensions['defaultProject'];
99
- if (typeof maybeDefaultProject === 'string' &&
100
- allProjectsForTargetName.includes(maybeDefaultProject)) {
101
- return [maybeDefaultProject];
102
- }
103
100
  if (allProjectsForTargetName.length === 1) {
104
101
  return allProjectsForTargetName;
105
102
  }
103
+ const maybeProject = (0, config_1.getProjectByCwd)(workspace);
104
+ if (maybeProject && allProjectsForTargetName.includes(maybeProject)) {
105
+ return [maybeProject];
106
+ }
106
107
  }
107
108
  return undefined;
108
109
  }
109
110
  }
111
+ __decorate([
112
+ memoize_1.memoize
113
+ ], ArchitectCommandModule.prototype, "getProjectNamesByTarget", null);
110
114
  exports.ArchitectCommandModule = ArchitectCommandModule;
@@ -8,6 +8,7 @@
8
8
  import { analytics, logging } from '@angular-devkit/core';
9
9
  import { ArgumentsCamelCase, Argv, CamelCaseKey, CommandModule as YargsCommandModule } from 'yargs';
10
10
  import { AngularWorkspace } from '../utilities/config';
11
+ import { PackageManagerUtils } from '../utilities/package-manager';
11
12
  import { Option } from './utilities/json-schema';
12
13
  export declare type Options<T> = {
13
14
  [key in keyof T as CamelCaseKey<key>]: T[key];
@@ -24,12 +25,15 @@ export interface CommandContext {
24
25
  currentDirectory: string;
25
26
  root: string;
26
27
  workspace?: AngularWorkspace;
28
+ globalConfiguration?: AngularWorkspace;
27
29
  logger: logging.Logger;
30
+ packageManager: PackageManagerUtils;
28
31
  /** Arguments parsed in free-from without parser configuration. */
29
32
  args: {
30
33
  positional: string[];
31
34
  options: {
32
35
  help: boolean;
36
+ jsonHelp: boolean;
33
37
  } & Record<string, unknown>;
34
38
  };
35
39
  }
@@ -52,7 +56,7 @@ export declare abstract class CommandModule<T extends {} = {}> implements Comman
52
56
  abstract readonly command: string;
53
57
  abstract readonly describe: string | false;
54
58
  abstract readonly longDescriptionPath?: string;
55
- protected shouldReportAnalytics: boolean;
59
+ protected readonly shouldReportAnalytics: boolean;
56
60
  static scope: CommandScope;
57
61
  private readonly optionsWithAnalytics;
58
62
  constructor(context: CommandContext);
@@ -68,7 +72,6 @@ export declare abstract class CommandModule<T extends {} = {}> implements Comman
68
72
  abstract run(options: Options<T> & OtherOptions): Promise<number | void> | number | void;
69
73
  handler(args: ArgumentsCamelCase<T> & OtherOptions): Promise<void>;
70
74
  reportAnalytics(options: (Options<T> & OtherOptions) | OtherOptions, paths?: string[], dimensions?: (boolean | number | string)[]): Promise<void>;
71
- private _analytics;
72
75
  protected getAnalytics(): Promise<analytics.Analytics>;
73
76
  /**
74
77
  * Adds schema options to a command also this keeps track of options that are required for analytics.