@angular/cli 20.2.0-next.3 → 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.
Files changed (32) hide show
  1. package/lib/code-examples.db +0 -0
  2. package/lib/config/schema.json +18 -2
  3. package/lib/config/workspace-schema.d.ts +14 -0
  4. package/lib/config/workspace-schema.js +11 -1
  5. package/package.json +16 -16
  6. package/src/commands/mcp/cli.d.ts +5 -1
  7. package/src/commands/mcp/cli.js +24 -3
  8. package/src/commands/mcp/mcp-server.d.ts +13 -1
  9. package/src/commands/mcp/mcp-server.js +47 -26
  10. package/src/commands/mcp/{instructions → resources}/best-practices.md +0 -5
  11. package/src/commands/mcp/resources/instructions.d.ts +9 -0
  12. package/src/commands/mcp/resources/instructions.js +28 -0
  13. package/src/commands/mcp/tools/best-practices.d.ts +1 -2
  14. package/src/commands/mcp/tools/best-practices.js +29 -28
  15. package/src/commands/mcp/tools/doc-search.d.ts +5 -9
  16. package/src/commands/mcp/tools/doc-search.js +34 -37
  17. package/src/commands/mcp/tools/examples.d.ts +4 -11
  18. package/src/commands/mcp/tools/examples.js +44 -37
  19. package/src/commands/mcp/tools/modernize.d.ts +31 -0
  20. package/src/commands/mcp/tools/modernize.js +135 -0
  21. package/src/commands/mcp/tools/projects.d.ts +22 -5
  22. package/src/commands/mcp/tools/projects.js +37 -35
  23. package/src/commands/mcp/tools/tool-registry.d.ts +35 -0
  24. package/src/commands/mcp/tools/tool-registry.js +33 -0
  25. package/src/utilities/config.js +3 -0
  26. package/src/utilities/eol.d.ts +12 -0
  27. package/src/utilities/eol.js +12 -0
  28. package/src/utilities/error.d.ts +8 -0
  29. package/src/utilities/error.js +24 -4
  30. package/src/utilities/json-file.d.ts +15 -2
  31. package/src/utilities/json-file.js +100 -27
  32. package/src/utilities/version.js +1 -1
@@ -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
- /** @internal */
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
- path;
19
- content;
20
- eol;
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.path = path;
23
- const buffer = (0, node_fs_1.readFileSync)(this.path);
24
- if (buffer) {
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
- else {
28
- throw new Error(`Could not read '${path}'.`);
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.eol = (0, eol_1.getEOL)(this.content);
57
+ this.#eol = (0, eol_1.getEOL)(this.#content);
58
+ this.#detectIndentation();
31
59
  }
32
- _jsonAst;
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._jsonAst) {
35
- return this._jsonAst;
65
+ if (this.#jsonAst) {
66
+ return this.#jsonAst;
36
67
  }
37
68
  const errors = [];
38
- this._jsonAst = (0, jsonc_parser_1.parseTree)(this.content, errors, { allowTrailingComma: true });
69
+ this.#jsonAst = (0, jsonc_parser_1.parseTree)(this.#content, errors, { allowTrailingComma: true });
39
70
  if (errors.length) {
40
- formatError(this.path, errors);
71
+ formatError(this.#path, errors);
41
72
  }
42
- return this._jsonAst;
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.content, jsonPath, value, {
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: true,
73
- tabSize: 2,
74
- eol: this.eol,
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.content = (0, jsonc_parser_1.applyEdits)(this.content, edits);
81
- this._jsonAst = undefined;
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.path, this.content);
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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
  }
@@ -22,4 +22,4 @@ class Version {
22
22
  this.patch = patch;
23
23
  }
24
24
  }
25
- exports.VERSION = new Version('20.2.0-next.3');
25
+ exports.VERSION = new Version('20.2.0-rc.0');