@angular/cli 14.0.0-rc.0 → 14.0.0-rc.1

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.
package/lib/cli/index.js CHANGED
@@ -73,7 +73,7 @@ async function default_1(options) {
73
73
  // Log nothing.
74
74
  }
75
75
  else {
76
- logger.fatal('An unexpected error occurred: ' + JSON.stringify(err));
76
+ logger.fatal(`An unexpected error occurred: ${'toString' in err ? err.toString() : JSON.stringify(err)}`);
77
77
  }
78
78
  return 1;
79
79
  }
package/lib/init.js CHANGED
@@ -120,7 +120,7 @@ const version_1 = require("../src/utilities/version");
120
120
  });
121
121
  })
122
122
  .then((exitCode) => {
123
- process.exit(exitCode);
123
+ process.exitCode = exitCode;
124
124
  })
125
125
  .catch((err) => {
126
126
  // eslint-disable-next-line no-console
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angular/cli",
3
- "version": "14.0.0-rc.0",
3
+ "version": "14.0.0-rc.1",
4
4
  "description": "CLI tool for Angular",
5
5
  "main": "lib/cli/index.js",
6
6
  "bin": {
@@ -25,10 +25,10 @@
25
25
  },
26
26
  "homepage": "https://github.com/angular/angular-cli",
27
27
  "dependencies": {
28
- "@angular-devkit/architect": "0.1400.0-rc.0",
29
- "@angular-devkit/core": "14.0.0-rc.0",
30
- "@angular-devkit/schematics": "14.0.0-rc.0",
31
- "@schematics/angular": "14.0.0-rc.0",
28
+ "@angular-devkit/architect": "0.1400.0-rc.1",
29
+ "@angular-devkit/core": "14.0.0-rc.1",
30
+ "@angular-devkit/schematics": "14.0.0-rc.1",
31
+ "@schematics/angular": "14.0.0-rc.1",
32
32
  "@yarnpkg/lockfile": "1.1.0",
33
33
  "ansi-colors": "4.1.1",
34
34
  "debug": "4.3.4",
@@ -49,12 +49,12 @@
49
49
  "ng-update": {
50
50
  "migrations": "@schematics/angular/migrations/migration-collection.json",
51
51
  "packageGroup": {
52
- "@angular/cli": "14.0.0-rc.0",
53
- "@angular-devkit/architect": "0.1400.0-rc.0",
54
- "@angular-devkit/build-angular": "14.0.0-rc.0",
55
- "@angular-devkit/build-webpack": "0.1400.0-rc.0",
56
- "@angular-devkit/core": "14.0.0-rc.0",
57
- "@angular-devkit/schematics": "14.0.0-rc.0"
52
+ "@angular/cli": "14.0.0-rc.1",
53
+ "@angular-devkit/architect": "0.1400.0-rc.1",
54
+ "@angular-devkit/build-angular": "14.0.0-rc.1",
55
+ "@angular-devkit/build-webpack": "0.1400.0-rc.1",
56
+ "@angular-devkit/core": "14.0.0-rc.1",
57
+ "@angular-devkit/schematics": "14.0.0-rc.1"
58
58
  }
59
59
  },
60
60
  "engines": {
@@ -40,6 +40,7 @@ exports.SchematicsCommandModule = exports.DEFAULT_SCHEMATICS_COLLECTION = void 0
40
40
  const core_1 = require("@angular-devkit/core");
41
41
  const schematics_1 = require("@angular-devkit/schematics");
42
42
  const tools_1 = require("@angular-devkit/schematics/tools");
43
+ const path_1 = require("path");
43
44
  const config_1 = require("../utilities/config");
44
45
  const memoize_1 = require("../utilities/memoize");
45
46
  const tty_1 = require("../utilities/tty");
@@ -209,16 +210,20 @@ class SchematicsCommandModule extends command_module_1.CommandModule {
209
210
  }
210
211
  async getSchematicCollections() {
211
212
  var _a;
213
+ // Resolve relative collections from the location of `angular.json`
214
+ const resolveRelativeCollection = (collectionName) => collectionName.charAt(0) === '.'
215
+ ? (0, path_1.resolve)(this.context.root, collectionName)
216
+ : collectionName;
212
217
  const getSchematicCollections = (configSection) => {
213
218
  if (!configSection) {
214
219
  return undefined;
215
220
  }
216
221
  const { schematicCollections, defaultCollection } = configSection;
217
222
  if (Array.isArray(schematicCollections)) {
218
- return new Set(schematicCollections);
223
+ return new Set(schematicCollections.map((c) => resolveRelativeCollection(c)));
219
224
  }
220
225
  else if (typeof defaultCollection === 'string') {
221
- return new Set([defaultCollection]);
226
+ return new Set([resolveRelativeCollection(defaultCollection)]);
222
227
  }
223
228
  return undefined;
224
229
  };
@@ -275,11 +280,11 @@ class SchematicsCommandModule extends command_module_1.CommandModule {
275
280
  if (err instanceof schematics_1.UnsuccessfulWorkflowExecution) {
276
281
  // "See above" because we already printed the error.
277
282
  logger.fatal('The Schematic workflow failed. See above.');
278
- return 1;
279
283
  }
280
284
  else {
281
- throw err;
285
+ logger.fatal(err.message);
282
286
  }
287
+ return 1;
283
288
  }
284
289
  finally {
285
290
  unsubscribe();
@@ -41,6 +41,13 @@ Appended \`source <(ng completion script)\` to \`${rcFile}\`. Restart your termi
41
41
 
42
42
  ${color_1.colors.yellow('source <(ng completion script)')}
43
43
  `.trim());
44
+ if ((await (0, completion_1.hasGlobalCliInstall)()) === false) {
45
+ this.context.logger.warn('Setup completed successfully, but there does not seem to be a global install of the' +
46
+ ' Angular CLI. For autocompletion to work, the CLI will need to be on your `$PATH`, which' +
47
+ ' is typically done with the `-g` flag in `npm install -g @angular/cli`.' +
48
+ '\n\n' +
49
+ 'For more information, see https://angular.io/cli/completion#global-install');
50
+ }
44
51
  return 0;
45
52
  }
46
53
  }
@@ -1,5 +1,73 @@
1
- To enable Bash and Zsh real-time type-ahead autocompletion, run
2
- `ng completion` and restart your terminal.
1
+ Setting up autocompletion configures your terminal, so pressing the `<TAB>` key while in the middle
2
+ of typing will display various commands and options available to you. This makes it very easy to
3
+ discover and use CLI commands without lots of memorization.
3
4
 
4
- Alternatively, append `source <(ng completion script)` to the appropriate `.bashrc`,
5
- `.bash_profile`, `.zshrc`, `.zsh_profile`, or `.profile` file.
5
+ ![A demo of Angular CLI autocompletion in a terminal. The user types several partial `ng` commands,
6
+ using autocompletion to finish several arguments and list contextual options.
7
+ ](/generated/images/guide/cli/completion.gif)
8
+
9
+ ## Automated setup
10
+
11
+ The CLI should prompt and ask to set up autocompletion for you the first time you use it (v14+).
12
+ Simply answer "Yes" and the CLI will take care of the rest.
13
+
14
+ ```
15
+ $ ng serve
16
+ ? Would you like to enable autocompletion? This will set up your terminal so pressing TAB while
17
+ typing Angular CLI commands will show possible options and autocomplete arguments. (Enabling
18
+ autocompletion will modify configuration files in your home directory.) Yes
19
+ Appended `source <(ng completion script)` to `/home/my-username/.bashrc`. Restart your terminal or
20
+ run:
21
+
22
+ source <(ng completion script)
23
+
24
+ to autocomplete `ng` commands.
25
+
26
+ # Serve output...
27
+ ```
28
+
29
+ If you already refused the prompt, it won't ask again. But you can run `ng completion` to
30
+ do the same thing automatically.
31
+
32
+ This modifies your terminal environment to load Angular CLI autocompletion, but can't update your
33
+ current terminal session. Either restart it or run `source <(ng completion script)` directly to
34
+ enable autocompletion in your current session.
35
+
36
+ Test it out by typing `ng ser<TAB>` and it should autocomplete to `ng serve`. Ambiguous arguments
37
+ will show all possible options and their documentation, such as `ng generate <TAB>`.
38
+
39
+ ## Manual setup
40
+
41
+ Some users may have highly customized terminal setups, possibly with configuration files checked
42
+ into source control with an opinionated structure. `ng completion` only ever appends Angular's setup
43
+ to an existing configuration file for your current shell, or creates one if none exists. If you want
44
+ more control over exactly where this configuration lives, you can manually set it up by having your
45
+ shell run at startup:
46
+
47
+ ```bash
48
+ source <(ng completion script)
49
+ ```
50
+
51
+ This is equivalent to what `ng completion` will automatically set up, and gives power users more
52
+ flexibility in their environments when desired.
53
+
54
+ ## Platform support
55
+
56
+ Angular CLI supports autocompletion for the Bash and Zsh shells on MacOS and Linux operating
57
+ systems.
58
+
59
+ Windows does not support autocompletion in native shells, such as Cmd and Powershell. However,
60
+ the Angular CLI supports Git Bash and
61
+ [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/) using Bash or Zsh.
62
+
63
+ ## Global install
64
+
65
+ Autocompletion works by configuring your terminal to invoke the Angular CLI on startup to load the
66
+ setup script. This means the terminal must be able to find and execute the Angular CLI, typically
67
+ through a global install that places the binary on the user's `$PATH`. If you get
68
+ `command not found: ng`, make sure the CLI is installed globally which you can do with the `-g`
69
+ flag:
70
+
71
+ ```bash
72
+ npm install -g @angular/cli
73
+ ```
@@ -93,8 +93,8 @@ class DocCommandModule extends command_module_1.CommandModule {
93
93
  catch { }
94
94
  }
95
95
  await (0, open_1.default)(options.search
96
- ? `https://${domain}/api?query=${options.keyword}`
97
- : `https://${domain}/docs?search=${options.keyword}`);
96
+ ? `https://${domain}/docs?search=${options.keyword}`
97
+ : `https://${domain}/api?query=${options.keyword}`);
98
98
  }
99
99
  }
100
100
  exports.DocCommandModule = DocCommandModule;
@@ -584,8 +584,9 @@ class UpdateCommandModule extends command_module_1.CommandModule {
584
584
  }
585
585
  }
586
586
  const result = await this.executeMigrations(workflow, migration.package, migrations, migration.from, migration.to, options.createCommits);
587
- if (!result) {
588
- return 0;
587
+ // A non-zero value is a failure for the package's migrations
588
+ if (result !== 0) {
589
+ return result;
589
590
  }
590
591
  }
591
592
  }
@@ -20,3 +20,11 @@ export declare function considerSettingUpAutocompletion(command: string, logger:
20
20
  * @return The full path of the configuration file modified.
21
21
  */
22
22
  export declare function initializeAutocomplete(): Promise<string>;
23
+ /**
24
+ * Returns whether the user has a global CLI install or `undefined` if this can't be determined.
25
+ * Execution from `npx` is *not* considered a global CLI install.
26
+ *
27
+ * This does *not* mean the current execution is from a global CLI install, only that a global
28
+ * install exists on the system.
29
+ */
30
+ export declare function hasGlobalCliInstall(): Promise<boolean | undefined>;
@@ -30,8 +30,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
30
30
  return result;
31
31
  };
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.initializeAutocomplete = exports.considerSettingUpAutocompletion = void 0;
33
+ exports.hasGlobalCliInstall = exports.initializeAutocomplete = exports.considerSettingUpAutocompletion = void 0;
34
34
  const core_1 = require("@angular-devkit/core");
35
+ const child_process_1 = require("child_process");
35
36
  const fs_1 = require("fs");
36
37
  const path = __importStar(require("path"));
37
38
  const process_1 = require("process");
@@ -80,6 +81,13 @@ Appended \`source <(ng completion script)\` to \`${rcFile}\`. Restart your termi
80
81
 
81
82
  ${color_1.colors.yellow(`source <(ng completion script)`)}
82
83
  `.trim());
84
+ if ((await hasGlobalCliInstall()) === false) {
85
+ logger.warn('Setup completed successfully, but there does not seem to be a global install of the' +
86
+ ' Angular CLI. For autocompletion to work, the CLI will need to be on your `$PATH`, which' +
87
+ ' is typically done with the `-g` flag in `npm install -g @angular/cli`.' +
88
+ '\n\n' +
89
+ 'For more information, see https://angular.io/cli/completion#global-install');
90
+ }
83
91
  // Save configuration to remember that the user was prompted.
84
92
  await setCompletionConfig({ ...completionConfig, prompted: true });
85
93
  return undefined;
@@ -136,6 +144,11 @@ async function shouldPromptForAutocompletionSetup(command, config) {
136
144
  if (!rcFiles) {
137
145
  return false; // Unknown shell.
138
146
  }
147
+ // Don't prompt if the user is missing a global CLI install. Autocompletion won't work after setup
148
+ // anyway and could be annoying for users running one-off commands via `npx` or using `npm start`.
149
+ if ((await hasGlobalCliInstall()) === false) {
150
+ return false;
151
+ }
139
152
  // Check each RC file if they already use `ng completion script` in any capacity and don't prompt.
140
153
  for (const rcFile of rcFiles) {
141
154
  const contents = await fs_1.promises.readFile(rcFile, 'utf-8').catch(() => undefined);
@@ -217,3 +230,53 @@ function getShellRunCommandCandidates(shell, home) {
217
230
  return undefined;
218
231
  }
219
232
  }
233
+ /**
234
+ * Returns whether the user has a global CLI install or `undefined` if this can't be determined.
235
+ * Execution from `npx` is *not* considered a global CLI install.
236
+ *
237
+ * This does *not* mean the current execution is from a global CLI install, only that a global
238
+ * install exists on the system.
239
+ */
240
+ async function hasGlobalCliInstall() {
241
+ var _a;
242
+ // List all binaries with the `ng` name on the user's `$PATH`.
243
+ const proc = (0, child_process_1.execFile)('which', ['-a', 'ng']);
244
+ let stdout = '';
245
+ (_a = proc.stdout) === null || _a === void 0 ? void 0 : _a.addListener('data', (content) => {
246
+ stdout += content;
247
+ });
248
+ const exitCode = await new Promise((resolve) => {
249
+ proc.addListener('exit', (exitCode) => {
250
+ resolve(exitCode);
251
+ });
252
+ });
253
+ switch (exitCode) {
254
+ case 0:
255
+ // Successfully listed all `ng` binaries on the `$PATH`. Look for at least one line which is a
256
+ // global install. We can't easily identify global installs, but local installs are typically
257
+ // placed in `node_modules/.bin` by NPM / Yarn. `npx` also currently caches files at
258
+ // `~/.npm/_npx/*/node_modules/.bin/`, so the same logic applies.
259
+ const lines = stdout.split('\n').filter((line) => line !== '');
260
+ const hasGlobalInstall = lines.some((line) => {
261
+ // A binary is a local install if it is a direct child of a `node_modules/.bin/` directory.
262
+ const parent = path.parse(path.parse(line).dir);
263
+ const grandparent = path.parse(parent.dir);
264
+ const localInstall = grandparent.base === 'node_modules' && parent.base === '.bin';
265
+ return !localInstall;
266
+ });
267
+ return hasGlobalInstall;
268
+ case 1:
269
+ // No instances of `ng` on the user's `$PATH`.
270
+ return false;
271
+ case null:
272
+ // `which` was killed by a signal and did not exit gracefully. Maybe it hung or something else
273
+ // went very wrong, so treat this as inconclusive.
274
+ return undefined;
275
+ default:
276
+ // `which` returns exit code 2 if an invalid option is specified and `-a` doesn't appear to be
277
+ // supported on all systems. Other exit codes mean unknown errors occurred. Can't tell whether
278
+ // CLI is globally installed, so treat this as inconclusive.
279
+ return undefined;
280
+ }
281
+ }
282
+ exports.hasGlobalCliInstall = hasGlobalCliInstall;