@angular/cli 20.2.0-next.2 → 20.2.0-rc.0
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/code-examples.db +0 -0
- package/lib/config/schema.json +18 -2
- package/lib/config/workspace-schema.d.ts +14 -0
- package/lib/config/workspace-schema.js +11 -1
- package/package.json +17 -17
- package/src/commands/mcp/cli.d.ts +5 -1
- package/src/commands/mcp/cli.js +25 -4
- package/src/commands/mcp/mcp-server.d.ts +13 -1
- package/src/commands/mcp/mcp-server.js +51 -27
- package/src/commands/mcp/{instructions → resources}/best-practices.md +0 -5
- package/src/commands/mcp/resources/instructions.d.ts +9 -0
- package/src/commands/mcp/resources/instructions.js +28 -0
- package/src/commands/mcp/tools/best-practices.d.ts +1 -2
- package/src/commands/mcp/tools/best-practices.js +30 -24
- package/src/commands/mcp/tools/doc-search.d.ts +5 -9
- package/src/commands/mcp/tools/doc-search.js +34 -37
- package/src/commands/mcp/tools/examples.d.ts +4 -11
- package/src/commands/mcp/tools/examples.js +68 -34
- package/src/commands/mcp/tools/modernize.d.ts +31 -0
- package/src/commands/mcp/tools/modernize.js +135 -0
- package/src/commands/mcp/tools/projects.d.ts +22 -5
- package/src/commands/mcp/tools/projects.js +37 -35
- package/src/commands/mcp/tools/tool-registry.d.ts +35 -0
- package/src/commands/mcp/tools/tool-registry.js +33 -0
- package/src/commands/version/cli.d.ts +24 -2
- package/src/commands/version/cli.js +74 -115
- package/src/commands/version/version-info.d.ts +33 -0
- package/src/commands/version/version-info.js +122 -0
- package/src/utilities/config.js +3 -0
- package/src/utilities/environment-options.d.ts +13 -0
- package/src/utilities/environment-options.js +43 -14
- package/src/utilities/eol.d.ts +12 -0
- package/src/utilities/eol.js +12 -0
- package/src/utilities/error.d.ts +8 -0
- package/src/utilities/error.js +24 -4
- package/src/utilities/json-file.d.ts +15 -2
- package/src/utilities/json-file.js +100 -27
- package/src/utilities/tty.d.ts +8 -0
- package/src/utilities/tty.js +10 -10
- package/src/utilities/version.js +1 -1
- package/src/utilities/load-esm.d.ts +0 -20
- package/src/utilities/load-esm.js +0 -30
|
@@ -13,34 +13,70 @@ exports.parseJson = parseJson;
|
|
|
13
13
|
const jsonc_parser_1 = require("jsonc-parser");
|
|
14
14
|
const node_fs_1 = require("node:fs");
|
|
15
15
|
const eol_1 = require("./eol");
|
|
16
|
-
|
|
16
|
+
const error_1 = require("./error");
|
|
17
|
+
/**
|
|
18
|
+
* Represents a JSON file, allowing for reading, modifying, and saving.
|
|
19
|
+
* This class uses `jsonc-parser` to preserve comments and formatting, including
|
|
20
|
+
* indentation and end-of-line sequences.
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
17
23
|
class JSONFile {
|
|
18
|
-
|
|
19
|
-
content;
|
|
20
|
-
|
|
24
|
+
/** The raw content of the JSON file. */
|
|
25
|
+
#content;
|
|
26
|
+
/** The end-of-line sequence used in the file. */
|
|
27
|
+
#eol;
|
|
28
|
+
/** Whether the file uses spaces for indentation. */
|
|
29
|
+
#insertSpaces = true;
|
|
30
|
+
/** The number of spaces or tabs used for indentation. */
|
|
31
|
+
#tabSize = 2;
|
|
32
|
+
/** The path to the JSON file. */
|
|
33
|
+
#path;
|
|
34
|
+
/** The parsed JSON abstract syntax tree. */
|
|
35
|
+
#jsonAst;
|
|
36
|
+
/** The raw content of the JSON file. */
|
|
37
|
+
get content() {
|
|
38
|
+
return this.#content;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Creates an instance of JSONFile.
|
|
42
|
+
* @param path The path to the JSON file.
|
|
43
|
+
*/
|
|
21
44
|
constructor(path) {
|
|
22
|
-
this
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.content = buffer.toString();
|
|
45
|
+
this.#path = path;
|
|
46
|
+
try {
|
|
47
|
+
this.#content = (0, node_fs_1.readFileSync)(this.#path, 'utf-8');
|
|
26
48
|
}
|
|
27
|
-
|
|
28
|
-
|
|
49
|
+
catch (e) {
|
|
50
|
+
(0, error_1.assertIsError)(e);
|
|
51
|
+
// We don't have to worry about ENOENT, since we'll be creating the file.
|
|
52
|
+
if (e.code !== 'ENOENT') {
|
|
53
|
+
throw e;
|
|
54
|
+
}
|
|
55
|
+
this.#content = '';
|
|
29
56
|
}
|
|
30
|
-
this
|
|
57
|
+
this.#eol = (0, eol_1.getEOL)(this.#content);
|
|
58
|
+
this.#detectIndentation();
|
|
31
59
|
}
|
|
32
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Gets the parsed JSON abstract syntax tree.
|
|
62
|
+
* The AST is lazily parsed and cached.
|
|
63
|
+
*/
|
|
33
64
|
get JsonAst() {
|
|
34
|
-
if (this
|
|
35
|
-
return this
|
|
65
|
+
if (this.#jsonAst) {
|
|
66
|
+
return this.#jsonAst;
|
|
36
67
|
}
|
|
37
68
|
const errors = [];
|
|
38
|
-
this
|
|
69
|
+
this.#jsonAst = (0, jsonc_parser_1.parseTree)(this.#content, errors, { allowTrailingComma: true });
|
|
39
70
|
if (errors.length) {
|
|
40
|
-
formatError(this
|
|
71
|
+
formatError(this.#path, errors);
|
|
41
72
|
}
|
|
42
|
-
return this
|
|
73
|
+
return this.#jsonAst;
|
|
43
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Gets a value from the JSON file at a specific path.
|
|
77
|
+
* @param jsonPath The path to the value.
|
|
78
|
+
* @returns The value at the given path, or `undefined` if not found.
|
|
79
|
+
*/
|
|
44
80
|
get(jsonPath) {
|
|
45
81
|
const jsonAstNode = this.JsonAst;
|
|
46
82
|
if (!jsonAstNode) {
|
|
@@ -52,6 +88,13 @@ class JSONFile {
|
|
|
52
88
|
const node = (0, jsonc_parser_1.findNodeAtLocation)(jsonAstNode, jsonPath);
|
|
53
89
|
return node === undefined ? undefined : (0, jsonc_parser_1.getNodeValue)(node);
|
|
54
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Modifies a value in the JSON file.
|
|
93
|
+
* @param jsonPath The path to the value to modify.
|
|
94
|
+
* @param value The new value to insert.
|
|
95
|
+
* @param insertInOrder A function to determine the insertion index, or `false` to insert at the end.
|
|
96
|
+
* @returns `true` if the modification was successful, `false` otherwise.
|
|
97
|
+
*/
|
|
55
98
|
modify(jsonPath, value, insertInOrder) {
|
|
56
99
|
if (value === undefined && this.get(jsonPath) === undefined) {
|
|
57
100
|
// Cannot remove a value which doesn't exist.
|
|
@@ -65,28 +108,49 @@ class JSONFile {
|
|
|
65
108
|
else if (insertInOrder !== false) {
|
|
66
109
|
getInsertionIndex = insertInOrder;
|
|
67
110
|
}
|
|
68
|
-
const edits = (0, jsonc_parser_1.modify)(this
|
|
111
|
+
const edits = (0, jsonc_parser_1.modify)(this.#content, jsonPath, value, {
|
|
69
112
|
getInsertionIndex,
|
|
70
|
-
// TODO: use indentation from original file.
|
|
71
113
|
formattingOptions: {
|
|
72
|
-
insertSpaces:
|
|
73
|
-
tabSize:
|
|
74
|
-
eol: this
|
|
114
|
+
insertSpaces: this.#insertSpaces,
|
|
115
|
+
tabSize: this.#tabSize,
|
|
116
|
+
eol: this.#eol,
|
|
75
117
|
},
|
|
76
118
|
});
|
|
77
119
|
if (edits.length === 0) {
|
|
78
120
|
return false;
|
|
79
121
|
}
|
|
80
|
-
this
|
|
81
|
-
this
|
|
122
|
+
this.#content = (0, jsonc_parser_1.applyEdits)(this.#content, edits);
|
|
123
|
+
this.#jsonAst = undefined;
|
|
82
124
|
return true;
|
|
83
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Deletes a value from the JSON file at a specific path.
|
|
128
|
+
* @param jsonPath The path to the value to delete.
|
|
129
|
+
* @returns `true` if the deletion was successful, `false` otherwise.
|
|
130
|
+
*/
|
|
131
|
+
delete(jsonPath) {
|
|
132
|
+
return this.modify(jsonPath, undefined);
|
|
133
|
+
}
|
|
134
|
+
/** Saves the modified content back to the file. */
|
|
84
135
|
save() {
|
|
85
|
-
(0, node_fs_1.writeFileSync)(this
|
|
136
|
+
(0, node_fs_1.writeFileSync)(this.#path, this.#content);
|
|
137
|
+
}
|
|
138
|
+
/** Detects the indentation of the file. */
|
|
139
|
+
#detectIndentation() {
|
|
140
|
+
// Find the first line that has indentation.
|
|
141
|
+
const match = this.#content.match(/^(?:( )+|\t+)\S/m);
|
|
142
|
+
if (match) {
|
|
143
|
+
this.#insertSpaces = !!match[1];
|
|
144
|
+
this.#tabSize = match[0].length - 1;
|
|
145
|
+
}
|
|
86
146
|
}
|
|
87
147
|
}
|
|
88
148
|
exports.JSONFile = JSONFile;
|
|
89
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Reads and parses a JSON file, supporting comments and trailing commas.
|
|
151
|
+
* @param path The path to the JSON file.
|
|
152
|
+
* @returns The parsed JSON object.
|
|
153
|
+
*/
|
|
90
154
|
function readAndParseJson(path) {
|
|
91
155
|
const errors = [];
|
|
92
156
|
const content = (0, jsonc_parser_1.parse)((0, node_fs_1.readFileSync)(path, 'utf-8'), errors, { allowTrailingComma: true });
|
|
@@ -95,11 +159,20 @@ function readAndParseJson(path) {
|
|
|
95
159
|
}
|
|
96
160
|
return content;
|
|
97
161
|
}
|
|
162
|
+
/**
|
|
163
|
+
* Formats a JSON parsing error and throws an exception.
|
|
164
|
+
* @param path The path to the file that failed to parse.
|
|
165
|
+
* @param errors The list of parsing errors.
|
|
166
|
+
*/
|
|
98
167
|
function formatError(path, errors) {
|
|
99
168
|
const { error, offset } = errors[0];
|
|
100
169
|
throw new Error(`Failed to parse "${path}" as JSON AST Object. ${(0, jsonc_parser_1.printParseErrorCode)(error)} at location: ${offset}.`);
|
|
101
170
|
}
|
|
102
|
-
|
|
171
|
+
/**
|
|
172
|
+
* Parses a JSON string, supporting comments and trailing commas.
|
|
173
|
+
* @param content The JSON string to parse.
|
|
174
|
+
* @returns The parsed JSON object.
|
|
175
|
+
*/
|
|
103
176
|
function parseJson(content) {
|
|
104
177
|
return (0, jsonc_parser_1.parse)(content, undefined, { allowTrailingComma: true });
|
|
105
178
|
}
|
package/src/utilities/tty.d.ts
CHANGED
|
@@ -5,4 +5,12 @@
|
|
|
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.dev/license
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* Determines if the `stream` is a TTY.
|
|
10
|
+
*
|
|
11
|
+
* @param stream A NodeJS stream to check. Defaults to `process.stdout`.
|
|
12
|
+
* @returns `true` if the `stream` is a TTY, `false` otherwise. This detection is overridden
|
|
13
|
+
* by the `NG_FORCE_TTY` environment variable. In a CI environment, this will also be `false`
|
|
14
|
+
* unless `NG_FORCE_TTY` is set.
|
|
15
|
+
*/
|
|
8
16
|
export declare function isTTY(stream?: NodeJS.WriteStream): boolean;
|
package/src/utilities/tty.js
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.isTTY = isTTY;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const environment_options_1 = require("./environment-options");
|
|
12
|
+
/**
|
|
13
|
+
* Determines if the `stream` is a TTY.
|
|
14
|
+
*
|
|
15
|
+
* @param stream A NodeJS stream to check. Defaults to `process.stdout`.
|
|
16
|
+
* @returns `true` if the `stream` is a TTY, `false` otherwise. This detection is overridden
|
|
17
|
+
* by the `NG_FORCE_TTY` environment variable. In a CI environment, this will also be `false`
|
|
18
|
+
* unless `NG_FORCE_TTY` is set.
|
|
19
|
+
*/
|
|
15
20
|
function isTTY(stream = process.stdout) {
|
|
16
|
-
|
|
17
|
-
const force = process.env['NG_FORCE_TTY'];
|
|
18
|
-
if (force !== undefined) {
|
|
19
|
-
return _isTruthy(force);
|
|
20
|
-
}
|
|
21
|
-
return !!stream.isTTY && !_isTruthy(process.env['CI']);
|
|
21
|
+
return environment_options_1.forceTty ?? (!!stream.isTTY && !environment_options_1.isCI);
|
|
22
22
|
}
|
package/src/utilities/version.js
CHANGED
|
@@ -1,20 +0,0 @@
|
|
|
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.dev/license
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* This uses a dynamic import to load a module which may be ESM.
|
|
10
|
-
* CommonJS code can load ESM code via a dynamic import. Unfortunately, TypeScript
|
|
11
|
-
* will currently, unconditionally downlevel dynamic import into a require call.
|
|
12
|
-
* require calls cannot load ESM code and will result in a runtime error. To workaround
|
|
13
|
-
* this, a Function constructor is used to prevent TypeScript from changing the dynamic import.
|
|
14
|
-
* Once TypeScript provides support for keeping the dynamic import this workaround can
|
|
15
|
-
* be dropped.
|
|
16
|
-
*
|
|
17
|
-
* @param modulePath The path of the module to load.
|
|
18
|
-
* @returns A Promise that resolves to the dynamically imported module.
|
|
19
|
-
*/
|
|
20
|
-
export declare function loadEsmModule<T>(modulePath: string | URL): Promise<T>;
|
|
@@ -1,30 +0,0 @@
|
|
|
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.dev/license
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.loadEsmModule = loadEsmModule;
|
|
11
|
-
/**
|
|
12
|
-
* Lazily compiled dynamic import loader function.
|
|
13
|
-
*/
|
|
14
|
-
let load;
|
|
15
|
-
/**
|
|
16
|
-
* This uses a dynamic import to load a module which may be ESM.
|
|
17
|
-
* CommonJS code can load ESM code via a dynamic import. Unfortunately, TypeScript
|
|
18
|
-
* will currently, unconditionally downlevel dynamic import into a require call.
|
|
19
|
-
* require calls cannot load ESM code and will result in a runtime error. To workaround
|
|
20
|
-
* this, a Function constructor is used to prevent TypeScript from changing the dynamic import.
|
|
21
|
-
* Once TypeScript provides support for keeping the dynamic import this workaround can
|
|
22
|
-
* be dropped.
|
|
23
|
-
*
|
|
24
|
-
* @param modulePath The path of the module to load.
|
|
25
|
-
* @returns A Promise that resolves to the dynamically imported module.
|
|
26
|
-
*/
|
|
27
|
-
function loadEsmModule(modulePath) {
|
|
28
|
-
load ??= new Function('modulePath', `return import(modulePath);`);
|
|
29
|
-
return load(modulePath);
|
|
30
|
-
}
|