@angular/cli 21.0.0-next.0 → 21.0.0-next.10

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 (226) hide show
  1. package/lib/cli/index.js +1 -0
  2. package/lib/cli/index.js.map +1 -0
  3. package/lib/code-examples.db +0 -0
  4. package/lib/config/schema.json +276 -51
  5. package/lib/config/workspace-schema.d.ts +57 -2
  6. package/lib/config/workspace-schema.js +23 -2
  7. package/lib/config/workspace-schema.js.map +1 -0
  8. package/lib/init.js +1 -0
  9. package/lib/init.js.map +1 -0
  10. package/package.json +24 -23
  11. package/src/analytics/analytics-collector.js +1 -0
  12. package/src/analytics/analytics-collector.js.map +1 -0
  13. package/src/analytics/analytics-parameters.js +1 -0
  14. package/src/analytics/analytics-parameters.js.map +1 -0
  15. package/src/analytics/analytics.js +1 -0
  16. package/src/analytics/analytics.js.map +1 -0
  17. package/src/command-builder/architect-base-command-module.js +1 -0
  18. package/src/command-builder/architect-base-command-module.js.map +1 -0
  19. package/src/command-builder/architect-command-module.js +21 -7
  20. package/src/command-builder/architect-command-module.js.map +1 -0
  21. package/src/command-builder/command-module.js +1 -0
  22. package/src/command-builder/command-module.js.map +1 -0
  23. package/src/command-builder/command-runner.js +2 -2
  24. package/src/command-builder/command-runner.js.map +1 -0
  25. package/src/command-builder/schematics-command-module.js +8 -2
  26. package/src/command-builder/schematics-command-module.js.map +1 -0
  27. package/src/command-builder/utilities/command.js +1 -0
  28. package/src/command-builder/utilities/command.js.map +1 -0
  29. package/src/command-builder/utilities/json-help.js +1 -0
  30. package/src/command-builder/utilities/json-help.js.map +1 -0
  31. package/src/command-builder/utilities/json-schema.d.ts +13 -1
  32. package/src/command-builder/utilities/json-schema.js +180 -96
  33. package/src/command-builder/utilities/json-schema.js.map +1 -0
  34. package/src/command-builder/utilities/normalize-options-middleware.js +1 -0
  35. package/src/command-builder/utilities/normalize-options-middleware.js.map +1 -0
  36. package/src/command-builder/utilities/schematic-engine-host.js +5 -6
  37. package/src/command-builder/utilities/schematic-engine-host.js.map +1 -0
  38. package/src/command-builder/utilities/schematic-workflow.js +1 -0
  39. package/src/command-builder/utilities/schematic-workflow.js.map +1 -0
  40. package/src/commands/add/cli.d.ts +2 -1
  41. package/src/commands/add/cli.js +179 -94
  42. package/src/commands/add/cli.js.map +1 -0
  43. package/src/commands/analytics/cli.js +1 -0
  44. package/src/commands/analytics/cli.js.map +1 -0
  45. package/src/commands/analytics/info/cli.js +1 -0
  46. package/src/commands/analytics/info/cli.js.map +1 -0
  47. package/src/commands/analytics/settings/cli.js +1 -0
  48. package/src/commands/analytics/settings/cli.js.map +1 -0
  49. package/src/commands/build/cli.js +1 -0
  50. package/src/commands/build/cli.js.map +1 -0
  51. package/src/commands/cache/clean/cli.js +1 -0
  52. package/src/commands/cache/clean/cli.js.map +1 -0
  53. package/src/commands/cache/cli.js +1 -0
  54. package/src/commands/cache/cli.js.map +1 -0
  55. package/src/commands/cache/info/cli.js +36 -11
  56. package/src/commands/cache/info/cli.js.map +1 -0
  57. package/src/commands/cache/settings/cli.js +1 -0
  58. package/src/commands/cache/settings/cli.js.map +1 -0
  59. package/src/commands/cache/utilities.js +1 -0
  60. package/src/commands/cache/utilities.js.map +1 -0
  61. package/src/commands/command-config.js +1 -0
  62. package/src/commands/command-config.js.map +1 -0
  63. package/src/commands/completion/cli.js +1 -0
  64. package/src/commands/completion/cli.js.map +1 -0
  65. package/src/commands/config/cli.js +1 -0
  66. package/src/commands/config/cli.js.map +1 -0
  67. package/src/commands/deploy/cli.js +1 -0
  68. package/src/commands/deploy/cli.js.map +1 -0
  69. package/src/commands/e2e/cli.js +1 -0
  70. package/src/commands/e2e/cli.js.map +1 -0
  71. package/src/commands/extract-i18n/cli.js +1 -0
  72. package/src/commands/extract-i18n/cli.js.map +1 -0
  73. package/src/commands/generate/cli.js +1 -0
  74. package/src/commands/generate/cli.js.map +1 -0
  75. package/src/commands/lint/cli.js +1 -0
  76. package/src/commands/lint/cli.js.map +1 -0
  77. package/src/commands/make-this-awesome/cli.js +1 -0
  78. package/src/commands/make-this-awesome/cli.js.map +1 -0
  79. package/src/commands/mcp/cli.js +1 -0
  80. package/src/commands/mcp/cli.js.map +1 -0
  81. package/src/commands/mcp/constants.d.ts +1 -1
  82. package/src/commands/mcp/constants.js +2 -1
  83. package/src/commands/mcp/constants.js.map +1 -0
  84. package/src/commands/mcp/mcp-server.d.ts +3 -3
  85. package/src/commands/mcp/mcp-server.js +40 -4
  86. package/src/commands/mcp/mcp-server.js.map +1 -0
  87. package/src/commands/mcp/resources/ai-tutor.md +627 -0
  88. package/src/commands/mcp/resources/instructions.js +1 -0
  89. package/src/commands/mcp/resources/instructions.js.map +1 -0
  90. package/src/commands/mcp/tools/ai-tutor.d.ts +8 -0
  91. package/src/commands/mcp/tools/ai-tutor.js +62 -0
  92. package/src/commands/mcp/tools/ai-tutor.js.map +1 -0
  93. package/src/commands/mcp/tools/best-practices.d.ts +4 -1
  94. package/src/commands/mcp/tools/best-practices.js +167 -22
  95. package/src/commands/mcp/tools/best-practices.js.map +1 -0
  96. package/src/commands/mcp/tools/doc-search.d.ts +20 -1
  97. package/src/commands/mcp/tools/doc-search.js +186 -67
  98. package/src/commands/mcp/tools/doc-search.js.map +1 -0
  99. package/src/commands/mcp/tools/examples.d.ts +35 -1
  100. package/src/commands/mcp/tools/examples.js +414 -56
  101. package/src/commands/mcp/tools/examples.js.map +1 -0
  102. package/src/commands/mcp/tools/modernize.js +29 -27
  103. package/src/commands/mcp/tools/modernize.js.map +1 -0
  104. package/src/commands/mcp/tools/onpush-zoneless-migration/analyze_for_unsupported_zone_uses.d.ts +17 -0
  105. package/src/commands/mcp/tools/onpush-zoneless-migration/analyze_for_unsupported_zone_uses.js +62 -0
  106. package/src/commands/mcp/tools/onpush-zoneless-migration/analyze_for_unsupported_zone_uses.js.map +1 -0
  107. package/src/commands/mcp/tools/onpush-zoneless-migration/migrate_single_file.d.ts +12 -0
  108. package/src/commands/mcp/tools/onpush-zoneless-migration/migrate_single_file.js +73 -0
  109. package/src/commands/mcp/tools/onpush-zoneless-migration/migrate_single_file.js.map +1 -0
  110. package/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file.d.ts +11 -0
  111. package/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file.js +106 -0
  112. package/src/commands/mcp/tools/onpush-zoneless-migration/migrate_test_file.js.map +1 -0
  113. package/src/commands/mcp/tools/onpush-zoneless-migration/prompts.d.ts +15 -0
  114. package/src/commands/mcp/tools/onpush-zoneless-migration/prompts.js +238 -0
  115. package/src/commands/mcp/tools/onpush-zoneless-migration/prompts.js.map +1 -0
  116. package/src/commands/mcp/tools/onpush-zoneless-migration/send_debug_message.d.ts +10 -0
  117. package/src/commands/mcp/tools/onpush-zoneless-migration/send_debug_message.js +20 -0
  118. package/src/commands/mcp/tools/onpush-zoneless-migration/send_debug_message.js.map +1 -0
  119. package/src/commands/mcp/tools/onpush-zoneless-migration/ts_utils.d.ts +36 -0
  120. package/src/commands/mcp/tools/onpush-zoneless-migration/ts_utils.js +136 -0
  121. package/src/commands/mcp/tools/onpush-zoneless-migration/ts_utils.js.map +1 -0
  122. package/src/commands/mcp/tools/onpush-zoneless-migration/types.d.ts +13 -0
  123. package/src/commands/mcp/tools/onpush-zoneless-migration/types.js +10 -0
  124. package/src/commands/mcp/tools/onpush-zoneless-migration/types.js.map +1 -0
  125. package/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.d.ts +14 -0
  126. package/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.js +228 -0
  127. package/src/commands/mcp/tools/onpush-zoneless-migration/zoneless-migration.js.map +1 -0
  128. package/src/commands/mcp/tools/projects.d.ts +75 -16
  129. package/src/commands/mcp/tools/projects.js +427 -30
  130. package/src/commands/mcp/tools/projects.js.map +1 -0
  131. package/src/commands/mcp/tools/tool-registry.d.ts +2 -1
  132. package/src/commands/mcp/tools/tool-registry.js +4 -2
  133. package/src/commands/mcp/tools/tool-registry.js.map +1 -0
  134. package/src/commands/new/cli.js +2 -0
  135. package/src/commands/new/cli.js.map +1 -0
  136. package/src/commands/run/cli.js +1 -0
  137. package/src/commands/run/cli.js.map +1 -0
  138. package/src/commands/serve/cli.js +1 -0
  139. package/src/commands/serve/cli.js.map +1 -0
  140. package/src/commands/test/cli.js +1 -0
  141. package/src/commands/test/cli.js.map +1 -0
  142. package/src/commands/update/cli.js +1 -0
  143. package/src/commands/update/cli.js.map +1 -0
  144. package/src/commands/update/schematic/index.js +1 -0
  145. package/src/commands/update/schematic/index.js.map +1 -0
  146. package/src/commands/update/schematic/schema.d.ts +0 -1
  147. package/src/commands/update/schematic/schema.js +1 -1
  148. package/src/commands/update/schematic/schema.js.map +1 -0
  149. package/src/commands/update/schematic/schema.json +1 -1
  150. package/src/commands/version/cli.d.ts +3 -7
  151. package/src/commands/version/cli.js +50 -49
  152. package/src/commands/version/cli.js.map +1 -0
  153. package/src/commands/version/version-info.d.ts +28 -10
  154. package/src/commands/version/version-info.js +34 -50
  155. package/src/commands/version/version-info.js.map +1 -0
  156. package/src/package-managers/discovery.d.ts +23 -0
  157. package/src/package-managers/discovery.js +110 -0
  158. package/src/package-managers/discovery.js.map +1 -0
  159. package/src/package-managers/error.d.ts +31 -0
  160. package/src/package-managers/error.js +41 -0
  161. package/src/package-managers/error.js.map +1 -0
  162. package/src/package-managers/factory.d.ts +25 -0
  163. package/src/package-managers/factory.js +123 -0
  164. package/src/package-managers/factory.js.map +1 -0
  165. package/src/package-managers/host.d.ts +64 -0
  166. package/src/package-managers/host.js +69 -0
  167. package/src/package-managers/host.js.map +1 -0
  168. package/src/package-managers/index.d.ts +12 -0
  169. package/src/package-managers/index.js +15 -0
  170. package/src/package-managers/index.js.map +1 -0
  171. package/src/package-managers/logger.d.ts +27 -0
  172. package/src/package-managers/logger.js +10 -0
  173. package/src/package-managers/logger.js.map +1 -0
  174. package/src/package-managers/package-manager-descriptor.d.ts +204 -0
  175. package/src/package-managers/package-manager-descriptor.js +147 -0
  176. package/src/package-managers/package-manager-descriptor.js.map +1 -0
  177. package/src/package-managers/package-manager.d.ts +144 -0
  178. package/src/package-managers/package-manager.js +304 -0
  179. package/src/package-managers/package-manager.js.map +1 -0
  180. package/src/package-managers/package-metadata.d.ts +87 -0
  181. package/src/package-managers/package-metadata.js +10 -0
  182. package/src/package-managers/package-metadata.js.map +1 -0
  183. package/src/package-managers/package-tree.d.ts +23 -0
  184. package/src/package-managers/package-tree.js +10 -0
  185. package/src/package-managers/package-tree.js.map +1 -0
  186. package/src/package-managers/parsers.d.ts +92 -0
  187. package/src/package-managers/parsers.js +234 -0
  188. package/src/package-managers/parsers.js.map +1 -0
  189. package/src/package-managers/testing/mock-host.d.ts +26 -0
  190. package/src/package-managers/testing/mock-host.js +53 -0
  191. package/src/package-managers/testing/mock-host.js.map +1 -0
  192. package/src/utilities/color.js +1 -0
  193. package/src/utilities/color.js.map +1 -0
  194. package/src/utilities/completion.js +1 -0
  195. package/src/utilities/completion.js.map +1 -0
  196. package/src/utilities/config.js +1 -0
  197. package/src/utilities/config.js.map +1 -0
  198. package/src/utilities/environment-options.js +1 -0
  199. package/src/utilities/environment-options.js.map +1 -0
  200. package/src/utilities/eol.js +1 -0
  201. package/src/utilities/eol.js.map +1 -0
  202. package/src/utilities/error.js +1 -0
  203. package/src/utilities/error.js.map +1 -0
  204. package/src/utilities/find-up.js +1 -0
  205. package/src/utilities/find-up.js.map +1 -0
  206. package/src/utilities/json-file.js +1 -0
  207. package/src/utilities/json-file.js.map +1 -0
  208. package/src/utilities/log-file.js +1 -0
  209. package/src/utilities/log-file.js.map +1 -0
  210. package/src/utilities/memoize.js +1 -0
  211. package/src/utilities/memoize.js.map +1 -0
  212. package/src/utilities/package-manager.d.ts +12 -0
  213. package/src/utilities/package-manager.js +52 -35
  214. package/src/utilities/package-manager.js.map +1 -0
  215. package/src/utilities/package-metadata.js +1 -0
  216. package/src/utilities/package-metadata.js.map +1 -0
  217. package/src/utilities/package-tree.js +1 -0
  218. package/src/utilities/package-tree.js.map +1 -0
  219. package/src/utilities/project.js +1 -0
  220. package/src/utilities/project.js.map +1 -0
  221. package/src/utilities/prompt.js +1 -0
  222. package/src/utilities/prompt.js.map +1 -0
  223. package/src/utilities/tty.js +1 -0
  224. package/src/utilities/tty.js.map +1 -0
  225. package/src/utilities/version.js +2 -1
  226. package/src/utilities/version.js.map +1 -0
@@ -0,0 +1,17 @@
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
+ import type { ImportSpecifier, Node, SourceFile } from 'typescript';
9
+ import { MigrationResponse } from './types';
10
+ export declare function analyzeForUnsupportedZoneUses(sourceFile: SourceFile): Promise<MigrationResponse | null>;
11
+ /**
12
+ * Finds usages of `NgZone` that are not supported in zoneless applications.
13
+ * @param sourceFile The source file to check.
14
+ * @param ngZoneImport The import specifier for `NgZone`.
15
+ * @returns A list of nodes that are unsupported `NgZone` usages.
16
+ */
17
+ export declare function findUnsupportedZoneUsages(sourceFile: SourceFile, ngZoneImport: ImportSpecifier): Promise<Node[]>;
@@ -0,0 +1,62 @@
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.analyzeForUnsupportedZoneUses = analyzeForUnsupportedZoneUses;
11
+ exports.findUnsupportedZoneUsages = findUnsupportedZoneUsages;
12
+ const prompts_1 = require("./prompts");
13
+ const ts_utils_1 = require("./ts_utils");
14
+ async function analyzeForUnsupportedZoneUses(sourceFile) {
15
+ const ngZoneImport = await (0, ts_utils_1.getImportSpecifier)(sourceFile, '@angular/core', 'NgZone');
16
+ if (!ngZoneImport) {
17
+ return null;
18
+ }
19
+ const unsupportedUsages = await findUnsupportedZoneUsages(sourceFile, ngZoneImport);
20
+ if (unsupportedUsages.length === 0) {
21
+ return null;
22
+ }
23
+ const locations = unsupportedUsages.map((node) => {
24
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
25
+ return `line ${line + 1}, character ${character + 1}: ${node.getText()}`;
26
+ });
27
+ return (0, prompts_1.createUnsupportedZoneUsagesMessage)(locations, sourceFile.fileName);
28
+ }
29
+ /**
30
+ * Finds usages of `NgZone` that are not supported in zoneless applications.
31
+ * @param sourceFile The source file to check.
32
+ * @param ngZoneImport The import specifier for `NgZone`.
33
+ * @returns A list of nodes that are unsupported `NgZone` usages.
34
+ */
35
+ async function findUnsupportedZoneUsages(sourceFile, ngZoneImport) {
36
+ const unsupportedUsages = [];
37
+ const ngZoneClassName = ngZoneImport.name.text;
38
+ const staticMethods = new Set([
39
+ 'isInAngularZone',
40
+ 'assertInAngularZone',
41
+ 'assertNotInAngularZone',
42
+ ]);
43
+ const instanceMethods = new Set(['onMicrotaskEmpty', 'onStable']);
44
+ const ts = await (0, ts_utils_1.loadTypescript)();
45
+ ts.forEachChild(sourceFile, function visit(node) {
46
+ if (ts.isPropertyAccessExpression(node)) {
47
+ const propertyName = node.name.text;
48
+ const expressionText = node.expression.getText(sourceFile);
49
+ // Static: NgZone.method()
50
+ if (expressionText === ngZoneClassName && staticMethods.has(propertyName)) {
51
+ unsupportedUsages.push(node);
52
+ }
53
+ // Instance: zone.method() or this.zone.method()
54
+ if (instanceMethods.has(propertyName)) {
55
+ unsupportedUsages.push(node);
56
+ }
57
+ }
58
+ ts.forEachChild(node, visit);
59
+ });
60
+ return unsupportedUsages;
61
+ }
62
+ //# sourceMappingURL=analyze_for_unsupported_zone_uses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze_for_unsupported_zone_uses.js","sourceRoot":"","sources":["analyze_for_unsupported_zone_uses.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAOH,sEAoBC;AAQD,8DAkCC;AAlED,uCAA+D;AAC/D,yCAAgE;AAGzD,KAAK,UAAU,6BAA6B,CACjD,UAAsB;IAEtB,MAAM,YAAY,GAAG,MAAM,IAAA,6BAAkB,EAAC,UAAU,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;IACrF,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,iBAAiB,GAAG,MAAM,yBAAyB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;IAEpF,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,SAAS,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC,IAAU,EAAE,EAAE;QACrD,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,UAAU,CAAC,6BAA6B,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;QAEtF,OAAO,QAAQ,IAAI,GAAG,CAAC,eAAe,SAAS,GAAG,CAAC,KAAK,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,OAAO,IAAA,4CAAkC,EAAC,SAAS,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;AAC5E,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,yBAAyB,CAC7C,UAAsB,EACtB,YAA6B;IAE7B,MAAM,iBAAiB,GAAW,EAAE,CAAC;IACrC,MAAM,eAAe,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC;IAE/C,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;QAC5B,iBAAiB;QACjB,qBAAqB;QACrB,wBAAwB;KACzB,CAAC,CAAC;IACH,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAC,CAAC;IAElE,MAAM,EAAE,GAAG,MAAM,IAAA,yBAAc,GAAE,CAAC;IAClC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,SAAS,KAAK,CAAC,IAAI;QAC7C,IAAI,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;YACpC,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAE3D,0BAA0B;YAC1B,IAAI,cAAc,KAAK,eAAe,IAAI,aAAa,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC1E,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;YAED,gDAAgD;YAChD,IAAI,eAAe,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;gBACtC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,OAAO,iBAAiB,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,12 @@
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
+ import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol';
9
+ import { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types';
10
+ import type { SourceFile } from 'typescript';
11
+ import { MigrationResponse } from './types';
12
+ export declare function migrateSingleFile(sourceFile: SourceFile, extras: RequestHandlerExtra<ServerRequest, ServerNotification>): Promise<MigrationResponse | null>;
@@ -0,0 +1,73 @@
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.migrateSingleFile = migrateSingleFile;
11
+ const analyze_for_unsupported_zone_uses_1 = require("./analyze_for_unsupported_zone_uses");
12
+ const migrate_test_file_1 = require("./migrate_test_file");
13
+ const prompts_1 = require("./prompts");
14
+ const send_debug_message_1 = require("./send_debug_message");
15
+ const ts_utils_1 = require("./ts_utils");
16
+ async function migrateSingleFile(sourceFile, extras) {
17
+ const testBedSpecifier = await (0, ts_utils_1.getImportSpecifier)(sourceFile, '@angular/core/testing', 'TestBed');
18
+ const isTestFile = sourceFile.fileName.endsWith('.spec.ts') || !!testBedSpecifier;
19
+ if (isTestFile) {
20
+ return (0, migrate_test_file_1.migrateTestFile)(sourceFile);
21
+ }
22
+ const unsupportedZoneUseResponse = await (0, analyze_for_unsupported_zone_uses_1.analyzeForUnsupportedZoneUses)(sourceFile);
23
+ if (unsupportedZoneUseResponse) {
24
+ return unsupportedZoneUseResponse;
25
+ }
26
+ let detectedStrategy;
27
+ let hasComponentDecorator = false;
28
+ const componentSpecifier = await (0, ts_utils_1.getImportSpecifier)(sourceFile, '@angular/core', 'Component');
29
+ if (!componentSpecifier) {
30
+ (0, send_debug_message_1.sendDebugMessage)(`No component decorator found in file: ${sourceFile.fileName}`, extras);
31
+ return null;
32
+ }
33
+ const ts = await (0, ts_utils_1.loadTypescript)();
34
+ ts.forEachChild(sourceFile, function visit(node) {
35
+ if (detectedStrategy) {
36
+ return; // Already found, no need to traverse further
37
+ }
38
+ if (ts.isDecorator(node) && ts.isCallExpression(node.expression)) {
39
+ const callExpr = node.expression;
40
+ if (callExpr.expression.getText(sourceFile) === 'Component') {
41
+ hasComponentDecorator = true;
42
+ if (callExpr.arguments.length > 0 && ts.isObjectLiteralExpression(callExpr.arguments[0])) {
43
+ const componentMetadata = callExpr.arguments[0];
44
+ for (const prop of componentMetadata.properties) {
45
+ if (ts.isPropertyAssignment(prop) &&
46
+ prop.name.getText(sourceFile) === 'changeDetection') {
47
+ if (ts.isPropertyAccessExpression(prop.initializer) &&
48
+ prop.initializer.expression.getText(sourceFile) === 'ChangeDetectionStrategy') {
49
+ const strategy = prop.initializer.name.text;
50
+ if (strategy === 'OnPush' || strategy === 'Default') {
51
+ detectedStrategy = strategy;
52
+ return;
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
60
+ ts.forEachChild(node, visit);
61
+ });
62
+ if (!hasComponentDecorator ||
63
+ // component uses OnPush. We don't have anything more to do here.
64
+ detectedStrategy === 'OnPush' ||
65
+ // Explicit default strategy, assume there's a reason for it (already migrated, or is a library that hosts Default components) and skip.
66
+ detectedStrategy === 'Default') {
67
+ (0, send_debug_message_1.sendDebugMessage)(`Component decorator found with strategy: ${detectedStrategy} in file: ${sourceFile.fileName}. Skipping migration for file.`, extras);
68
+ return null;
69
+ }
70
+ // Component decorator found, but no change detection strategy.
71
+ return (0, prompts_1.generateZonelessMigrationInstructionsForComponent)(sourceFile.fileName);
72
+ }
73
+ //# sourceMappingURL=migrate_single_file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate_single_file.js","sourceRoot":"","sources":["migrate_single_file.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAYH,8CA8EC;AArFD,2FAAoF;AACpF,2DAAsD;AACtD,uCAA8E;AAC9E,6DAAwD;AACxD,yCAAgE;AAGzD,KAAK,UAAU,iBAAiB,CACrC,UAAsB,EACtB,MAA8D;IAE9D,MAAM,gBAAgB,GAAG,MAAM,IAAA,6BAAkB,EAAC,UAAU,EAAE,uBAAuB,EAAE,SAAS,CAAC,CAAC;IAClG,MAAM,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC;IAClF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,IAAA,mCAAe,EAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAED,MAAM,0BAA0B,GAAG,MAAM,IAAA,iEAA6B,EAAC,UAAU,CAAC,CAAC;IACnF,IAAI,0BAA0B,EAAE,CAAC;QAC/B,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED,IAAI,gBAAkD,CAAC;IACvD,IAAI,qBAAqB,GAAG,KAAK,CAAC;IAElC,MAAM,kBAAkB,GAAG,MAAM,IAAA,6BAAkB,EAAC,UAAU,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;IAC9F,IAAI,CAAC,kBAAkB,EAAE,CAAC;QACxB,IAAA,qCAAgB,EAAC,yCAAyC,UAAU,CAAC,QAAQ,EAAE,EAAE,MAAM,CAAC,CAAC;QAEzF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,IAAA,yBAAc,GAAE,CAAC;IAClC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,SAAS,KAAK,CAAC,IAAI;QAC7C,IAAI,gBAAgB,EAAE,CAAC;YACrB,OAAO,CAAC,6CAA6C;QACvD,CAAC;QAED,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC;YACjC,IAAI,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,WAAW,EAAE,CAAC;gBAC5D,qBAAqB,GAAG,IAAI,CAAC;gBAC7B,IAAI,QAAQ,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,yBAAyB,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACzF,MAAM,iBAAiB,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;oBAChD,KAAK,MAAM,IAAI,IAAI,iBAAiB,CAAC,UAAU,EAAE,CAAC;wBAChD,IACE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC;4BAC7B,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,iBAAiB,EACnD,CAAC;4BACD,IACE,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,WAAW,CAAC;gCAC/C,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,yBAAyB,EAC7E,CAAC;gCACD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gCAC5C,IAAI,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oCACpD,gBAAgB,GAAG,QAAQ,CAAC;oCAE5B,OAAO;gCACT,CAAC;4BACH,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,IACE,CAAC,qBAAqB;QACtB,iEAAiE;QACjE,gBAAgB,KAAK,QAAQ;QAC7B,wIAAwI;QACxI,gBAAgB,KAAK,SAAS,EAC9B,CAAC;QACD,IAAA,qCAAgB,EACd,4CAA4C,gBAAgB,aAAa,UAAU,CAAC,QAAQ,gCAAgC,EAC5H,MAAM,CACP,CAAC;QAEF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,+DAA+D;IAC/D,OAAO,IAAA,2DAAiD,EAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AAChF,CAAC"}
@@ -0,0 +1,11 @@
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
+ import type { SourceFile } from 'typescript';
9
+ import { MigrationResponse } from './types';
10
+ export declare function migrateTestFile(sourceFile: SourceFile): Promise<MigrationResponse | null>;
11
+ export declare function searchForGlobalZoneless(startPath: string): Promise<boolean>;
@@ -0,0 +1,106 @@
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
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = 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);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ exports.migrateTestFile = migrateTestFile;
44
+ exports.searchForGlobalZoneless = searchForGlobalZoneless;
45
+ const fs = __importStar(require("node:fs"));
46
+ const promises_1 = require("node:fs/promises");
47
+ const node_path_1 = require("node:path");
48
+ const prompts_1 = require("./prompts");
49
+ const ts_utils_1 = require("./ts_utils");
50
+ async function migrateTestFile(sourceFile) {
51
+ const ts = await (0, ts_utils_1.loadTypescript)();
52
+ // Check if tests use zoneless either by default through `initTestEnvironment` or by explicitly calling `provideZonelessChangeDetection`.
53
+ let testsUseZonelessChangeDetection = await searchForGlobalZoneless(sourceFile.fileName);
54
+ if (!testsUseZonelessChangeDetection) {
55
+ ts.forEachChild(sourceFile, function visit(node) {
56
+ if (ts.isCallExpression(node) &&
57
+ node.expression.getText(sourceFile) === 'provideZonelessChangeDetection') {
58
+ testsUseZonelessChangeDetection = true;
59
+ return;
60
+ }
61
+ ts.forEachChild(node, visit);
62
+ });
63
+ }
64
+ if (!testsUseZonelessChangeDetection) {
65
+ // Tests do not use zoneless, so we provide instructions to set it up.
66
+ return (0, prompts_1.createProvideZonelessForTestsSetupPrompt)(sourceFile.fileName);
67
+ }
68
+ // At this point, tests are using zoneless, so we look for any explicit uses of `provideZoneChangeDetection` that need to be fixed.
69
+ return (0, prompts_1.createFixResponseForZoneTests)(sourceFile);
70
+ }
71
+ async function searchForGlobalZoneless(startPath) {
72
+ const angularJsonDir = findAngularJsonDir(startPath);
73
+ if (!angularJsonDir) {
74
+ // Cannot determine project root, fallback to original behavior or assume false.
75
+ // For now, let's assume no global setup if angular.json is not found.
76
+ return false;
77
+ }
78
+ try {
79
+ const files = (0, promises_1.glob)(`${angularJsonDir}/**/*.ts`);
80
+ for await (const file of files) {
81
+ const content = fs.readFileSync(file, 'utf-8');
82
+ if (content.includes('initTestEnvironment') &&
83
+ content.includes('provideZonelessChangeDetection')) {
84
+ return true;
85
+ }
86
+ }
87
+ }
88
+ catch (e) {
89
+ return false;
90
+ }
91
+ return false;
92
+ }
93
+ function findAngularJsonDir(startDir) {
94
+ let currentDir = startDir;
95
+ while (true) {
96
+ if (fs.existsSync((0, node_path_1.join)(currentDir, 'angular.json'))) {
97
+ return currentDir;
98
+ }
99
+ const parentDir = (0, node_path_1.dirname)(currentDir);
100
+ if (parentDir === currentDir) {
101
+ return null;
102
+ }
103
+ currentDir = parentDir;
104
+ }
105
+ }
106
+ //# sourceMappingURL=migrate_test_file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate_test_file.js","sourceRoot":"","sources":["migrate_test_file.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUH,0CAyBC;AAED,0DAwBC;AA3DD,4CAA8B;AAC9B,+CAAwC;AACxC,yCAA0C;AAE1C,uCAAoG;AACpG,yCAA4C;AAGrC,KAAK,UAAU,eAAe,CAAC,UAAsB;IAC1D,MAAM,EAAE,GAAG,MAAM,IAAA,yBAAc,GAAE,CAAC;IAClC,yIAAyI;IACzI,IAAI,+BAA+B,GAAG,MAAM,uBAAuB,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzF,IAAI,CAAC,+BAA+B,EAAE,CAAC;QACrC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,SAAS,KAAK,CAAC,IAAI;YAC7C,IACE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC;gBACzB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,gCAAgC,EACxE,CAAC;gBACD,+BAA+B,GAAG,IAAI,CAAC;gBAEvC,OAAO;YACT,CAAC;YACD,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,+BAA+B,EAAE,CAAC;QACrC,sEAAsE;QACtE,OAAO,IAAA,kDAAwC,EAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvE,CAAC;IAED,mIAAmI;IACnI,OAAO,IAAA,uCAA6B,EAAC,UAAU,CAAC,CAAC;AACnD,CAAC;AAEM,KAAK,UAAU,uBAAuB,CAAC,SAAiB;IAC7D,MAAM,cAAc,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACrD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,gFAAgF;QAChF,sEAAsE;QACtE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAA,eAAI,EAAC,GAAG,cAAc,UAAU,CAAC,CAAC;QAChD,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC/C,IACE,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAC;gBACvC,OAAO,CAAC,QAAQ,CAAC,gCAAgC,CAAC,EAClD,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,IAAI,UAAU,GAAG,QAAQ,CAAC;IAC1B,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,EAAE,CAAC,UAAU,CAAC,IAAA,gBAAI,EAAC,UAAU,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;YACpD,OAAO,UAAU,CAAC;QACpB,CAAC;QACD,MAAM,SAAS,GAAG,IAAA,mBAAO,EAAC,UAAU,CAAC,CAAC;QACtC,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,UAAU,GAAG,SAAS,CAAC;IACzB,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
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
+ import type { SourceFile } from 'typescript';
9
+ import { MigrationResponse } from './types';
10
+ export declare function createProvideZonelessForTestsSetupPrompt(testFilePath: string): MigrationResponse;
11
+ export declare function createUnsupportedZoneUsagesMessage(usages: string[], filePath: string): MigrationResponse;
12
+ export declare function generateZonelessMigrationInstructionsForComponent(filePath: string): MigrationResponse;
13
+ export declare function createTestDebuggingGuideForNonActionableInput(fileOrDirPath: string): MigrationResponse;
14
+ export declare function createFixResponseForZoneTests(sourceFile: SourceFile): Promise<MigrationResponse | null>;
15
+ export declare function createResponse(text: string): MigrationResponse;
@@ -0,0 +1,238 @@
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.createProvideZonelessForTestsSetupPrompt = createProvideZonelessForTestsSetupPrompt;
11
+ exports.createUnsupportedZoneUsagesMessage = createUnsupportedZoneUsagesMessage;
12
+ exports.generateZonelessMigrationInstructionsForComponent = generateZonelessMigrationInstructionsForComponent;
13
+ exports.createTestDebuggingGuideForNonActionableInput = createTestDebuggingGuideForNonActionableInput;
14
+ exports.createFixResponseForZoneTests = createFixResponseForZoneTests;
15
+ exports.createResponse = createResponse;
16
+ const ts_utils_1 = require("./ts_utils");
17
+ /* eslint-disable max-len */
18
+ function createProvideZonelessForTestsSetupPrompt(testFilePath) {
19
+ const text = `You are an expert Angular developer assisting with a migration to zoneless. Your task is to update the test file at \`${testFilePath}\` to enable zoneless change detection and identify tests that are not yet compatible.
20
+
21
+ Follow these instructions precisely.
22
+
23
+ ### Refactoring Guide
24
+
25
+ The test file \`${testFilePath}\` is not yet configured for zoneless change detection. You need to enable it for the entire test suite and then identify which specific tests fail.
26
+
27
+ #### Step 1: Enable Zoneless Change Detection for the Suite
28
+
29
+ In the main \`beforeEach\` block for the test suite (the one inside the top-level \`describe\`), add \`provideZonelessChangeDetection()\` to the providers array in \`TestBed.configureTestingModule\`.
30
+
31
+ * If there is already an import from \`@angular/core\`, add \`provideZonelessChangeDetection\` to the existing import.
32
+ * Otherwise, add a new import statement for \`provideZonelessChangeDetection\` from \`@angular/core\`.
33
+
34
+ \`\`\`diff
35
+ - import {{ SomeImport }} from '@angular/core';
36
+ + import {{ SomeImport, provideZonelessChangeDetection }} from '@angular/core';
37
+
38
+ describe('MyComponent', () => {
39
+ + beforeEach(() => {
40
+ + TestBed.configureTestingModule({providers: [provideZonelessChangeDetection()]});
41
+ + });
42
+ });
43
+ \`\`\`
44
+
45
+ #### Step 2: Identify and fix Failing Tests
46
+
47
+ After enabling zoneless detection for the suite, some tests will likely fail. Your next task is to identify these failing tests and fix them.
48
+
49
+ ${testDebuggingGuideText(testFilePath)}
50
+ 8. **DO** add \`provideZonelessChangeDetection()\` _once_ to the top-most \`describe\` in a \`beforeEach\` block as instructed in Step 1.
51
+ 9. **DO** run the tests after adding \`provideZonelessChangeDetection\` to see which ones fail. **DO NOT** make assumptions about which tests will might fail.
52
+
53
+ ### Final Step
54
+ After you have applied all the required changes and followed all the rules, consult this tool again for the next steps in the migration process.`;
55
+ return createResponse(text);
56
+ }
57
+ function createUnsupportedZoneUsagesMessage(usages, filePath) {
58
+ const text = `You are an expert Angular developer assisting with a migration to zoneless. Your task is to refactor the component in ${filePath} to remove unsupported NgZone APIs.
59
+
60
+ The component uses NgZone APIs that are incompatible with zoneless applications. The only permitted NgZone APIs are \`NgZone.run\` and \`NgZone.runOutsideAngular\`.
61
+
62
+ The following usages are unsupported and must be fixed:
63
+ ${usages.map((usage) => `- ${usage}`).join('\n')}
64
+
65
+ Follow these instructions precisely to refactor the code.
66
+
67
+ ### Refactoring Guide
68
+
69
+ #### 1. APIs to Remove (No Replacement)
70
+ The following methods have no replacement in a zoneless context and must be removed entirely:
71
+ - \`NgZone.assertInAngularZone\`
72
+ - \`NgZone.assertNotInAngularZone\`
73
+ - \`NgZone.isInAngularZone\`
74
+
75
+ #### 2. APIs to Replace
76
+ The \`onMicrotaskEmpty\` and \`onStable\` observables must be replaced with modern Angular APIs.
77
+
78
+ - **For single-event subscriptions** (e.g., using \`.pipe(take(1))\` or \`.pipe(first())\`), use \`afterNextRender\` from \`@angular/core\`.
79
+
80
+ \`\`\`diff
81
+ - this.zone.onMicrotaskEmpty.pipe(take(1)).subscribe(() => {});
82
+ - this.zone.onStable.pipe(take(1)).subscribe(() => {});
83
+ + import { afterNextRender, Injector } from '@angular/core';
84
+ + afterNextRender(() => {}, {injector: this.injector});
85
+ \`\`\`
86
+
87
+ - **For continuous subscriptions**, use \`afterEveryRender\` from \`@angular/core\`.
88
+
89
+ \`\`\`diff
90
+ - this.zone.onMicrotaskEmpty.subscribe(() => {});
91
+ - this.zone.onStable.subscribe(() => {});
92
+ + import { afterEveryRender, Injector } from '@angular/core';
93
+ + afterEveryRender(() => {}, {injector: this.injector});
94
+ \`\`\`
95
+
96
+ - If the code checks \`this.zone.isStable\` before subscribing, you can remove the \`isStable\` check. \`afterNextRender\` handles this case correctly.
97
+
98
+ ### IMPORTANT: Rules and Constraints
99
+ You must follow these rules without exception:
100
+ 1. **DO NOT** make any changes to the component that are unrelated to removing the unsupported NgZone APIs listed above.
101
+ 2. **DO NOT** remove or modify usages of \`NgZone.run\` or \`NgZone.runOutsideAngular\`. These are still required.
102
+ 3. **DO** ensure that you replace \`onMicrotaskEmpty\` and \`onStable\` with the correct replacements (\`afterNextRender\` or \`afterEveryRender\`) as described in the guide.
103
+ 4. **DO** add the necessary imports for \`afterNextRender\`, \`afterEveryRender\`, and \`Injector\` when you use them.
104
+
105
+ ### Final Step
106
+ After you have applied all the required changes and followed all the rules, consult this tool again for the next steps in the migration process.
107
+ `;
108
+ return createResponse(text);
109
+ }
110
+ function generateZonelessMigrationInstructionsForComponent(filePath) {
111
+ const text = `You are an expert Angular developer assisting with a migration to zoneless. Your task is to refactor the component in \`${filePath}\` to be compatible with zoneless change detection by ensuring Angular is notified of all state changes that affect the view.
112
+
113
+ The component does not currently use a change detection strategy, which means it may rely on Zone.js. To prepare it for zoneless, you must manually trigger change detection when its state changes.
114
+
115
+ Follow these instructions precisely.
116
+
117
+ ### Refactoring Guide
118
+
119
+ #### Step 1: Identify and Refactor State
120
+ Your primary goal is to ensure that every time a component property used in the template is updated, Angular knows it needs to run change detection.
121
+
122
+ 1. **Identify Properties**: Find all component properties that are read by the template.
123
+ 2. **Choose a Strategy**: For each property identified, choose one of the following refactoring strategies:
124
+ * **(Preferred) Convert to Signal**: The best approach is to convert the property to an Angular Signal. This is the most idiomatic and future-proof way to handle state in zoneless applications.
125
+ * **(Alternative) Use \`markForCheck()\`**: If converting to a signal is too complex or would require extensive refactoring, you can instead inject \`ChangeDetectorRef\` and call \`this.cdr.markForCheck()\` immediately after the property is updated.
126
+
127
+ #### Step 2: Add \`ChangeDetectionStrategy.Default\`
128
+ After you have refactored all necessary properties, you must update the component's decorator to explicitly set the change detection strategy.
129
+
130
+ 1. Add \`ChangeDetectionStrategy\` to the import from \`@angular/core\`.
131
+ 2. In the \`@Component\` decorator, add the property \`changeDetection: ChangeDetectionStrategy.Default\`.
132
+ 3. Add a \`// TODO\` comment above this line explaining that the component should be fully migrated to \`OnPush\` after the application has been tested with these changes.
133
+
134
+ Example:
135
+ \`\`\`typescript
136
+ @Component({
137
+ ...
138
+ // TODO: This component has been partially migrated to be zoneless-compatible.
139
+ // After testing, this should be updated to ChangeDetectionStrategy.OnPush.
140
+ changeDetection: ChangeDetectionStrategy.Default,
141
+ })
142
+ \`\`\`
143
+
144
+ ### IMPORTANT: Rules and Constraints
145
+ You must follow these rules without exception:
146
+ 1. **DO** apply one of the two refactoring strategies (signals or \`markForCheck()\`) for all relevant component properties.
147
+ 2. **DO** add \`changeDetection: ChangeDetectionStrategy.Default\` with the specified TODO comment as the final code change.
148
+ 3. **DO NOT** use \`ChangeDetectionStrategy.OnPush\`. This will be the next step in the migration, but it is not part of this task.
149
+ 4. **DO NOT** modify properties that are already signals or are used with the \`async\` pipe in the template, as they are already zoneless-compatible.
150
+ 5. **DO NOT** make any changes to files other than the component file at \`${filePath}\` and its direct template/style files if necessary.
151
+ 6. **DO NOT** remove or modify usages of \`NgZone.run\` or \`NgZone.runOutsideAngular\`. These are still required.
152
+
153
+ ### Final Step
154
+ After you have applied all the required changes and followed all the rules, consult this tool again for the next steps in the migration process.`;
155
+ return createResponse(text);
156
+ }
157
+ function createTestDebuggingGuideForNonActionableInput(fileOrDirPath) {
158
+ const text = `You are an expert Angular developer assisting with a migration to zoneless.
159
+
160
+ No actionable migration steps were found in the application code for \`${fileOrDirPath}\`. However, if the tests for this code are failing with zoneless enabled, the tests themselves likely need to be updated.
161
+
162
+ Your task is to investigate and fix any failing tests related to the code in \`${fileOrDirPath}\`.
163
+
164
+ ${testDebuggingGuideText(fileOrDirPath)}
165
+ `;
166
+ return createResponse(text);
167
+ }
168
+ async function createFixResponseForZoneTests(sourceFile) {
169
+ const ts = await (0, ts_utils_1.loadTypescript)();
170
+ const usages = [];
171
+ ts.forEachChild(sourceFile, function visit(node) {
172
+ if (ts.isCallExpression(node) &&
173
+ node.expression.getText(sourceFile) === 'provideZoneChangeDetection') {
174
+ usages.push(node);
175
+ }
176
+ ts.forEachChild(node, visit);
177
+ });
178
+ if (usages.length === 0) {
179
+ // No usages of provideZoneChangeDetection found, so no fix needed.
180
+ return null;
181
+ }
182
+ const locations = usages.map((node) => {
183
+ const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
184
+ return `line ${line + 1}, character ${character + 1}`;
185
+ });
186
+ const text = `You are an expert Angular developer assisting with a migration to zoneless. Your task is to update the test file at \`${sourceFile.fileName}\` to be fully zoneless-compatible.
187
+
188
+ The test suite has been partially migrated, but some tests were incompatible and are still using Zone.js-based change detection via \`provideZoneChangeDetection\`. You must refactor these tests to work in a zoneless environment and remove the \`provideZoneChangeDetection\` calls.
189
+
190
+ The following usages of \`provideZoneChangeDetection\` must be removed:
191
+ ${locations.map((loc) => `- ${loc}`).join('\n')}
192
+
193
+ After removing \`provideZoneChangeDetection\`, the tests will likely fail. Use this guide to diagnose and fix the failures.
194
+
195
+ ${testDebuggingGuideText(sourceFile.fileName)}
196
+
197
+ ### Final Step
198
+ After you have applied all the required changes and followed all the rules, consult this tool again for the next steps in the migration process.`;
199
+ return createResponse(text);
200
+ }
201
+ function testDebuggingGuideText(fileName) {
202
+ return `
203
+ ### Test Debugging Guide
204
+
205
+ 1. **\`ExpressionChangedAfterItHasBeenCheckedError\`**:
206
+ * **Cause**: This error indicates that a value in a component's template was updated, but Angular was not notified to run change detection.
207
+ * **Solution**:
208
+ * If the value is in a test-only wrapper component, update the property to be a signal.
209
+ * For application components, either convert the property to a signal or call \`ChangeDetectorRef.markForCheck()\` immediately after the property is updated.
210
+
211
+ 2. **Asynchronous Operations and Timing**:
212
+ * **Cause**: Without Zone.js, change detection is always scheduled asynchronously. Tests that previously relied on synchronous updates might now fail. The \`fixture.whenStable()\` utility also no longer waits for timers (like \`setTimeout\` or \`setInterval\`).
213
+ * **Solution**:
214
+ * Avoid relying on synchronous change detection.
215
+ * To wait for asynchronous operations to complete, you may need to poll for an expected state, use \`fakeAsync\` with \`tick()\`, or use a mock clock to flush timers.
216
+
217
+ 3. **Indirect Dependencies**:
218
+ * **Cause**: The component itself might be zoneless-compatible, but it could be using a service or another dependency that is not.
219
+ * **Solution**: Investigate the services and dependencies used by the component and its tests. Run this tool on those dependencies to identify and fix any issues.
220
+
221
+ ### IMPORTANT: Rules and Constraints
222
+
223
+ You must follow these rules without exception:
224
+ 1. **DO** focus only on fixing the tests for the code in \`${fileName}\`.
225
+ 2. **DO** remove all usages of \`provideZoneChangeDetection\` from the test file.
226
+ 3. **DO** apply the solutions described in the debugging guide to fix any resulting test failures.
227
+ 4. **DO** update properties of test components and directives to use signals. Tests often use plain objects and values and update the component state directly before calling \`fixture.detectChanges\`. This will not work and will result in \`ExpressionChangedAfterItHasBeenCheckedError\` because Angular was not notifed of the change.
228
+ 5. **DO NOT** make changes to application code unless it is to fix a bug revealed by the zoneless migration (e.g., converting a property to a signal to fix an \`ExpressionChangedAfterItHasBeenCheckedError\`).
229
+ 6. **DO NOT** make any changes unrelated to fixing the failing tests in \`${fileName}\`.
230
+ 7. **DO NOT** re-introduce \`provideZoneChangeDetection()\` into tests that are already using \`provideZonelessChangeDetection()\`.`;
231
+ }
232
+ /* eslint-enable max-len */
233
+ function createResponse(text) {
234
+ return {
235
+ content: [{ type: 'text', text }],
236
+ };
237
+ }
238
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
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
+ import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol';
9
+ import { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types';
10
+ export declare function sendDebugMessage(message: string, { sendNotification }: RequestHandlerExtra<ServerRequest, ServerNotification>): void;
@@ -0,0 +1,20 @@
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.sendDebugMessage = sendDebugMessage;
11
+ function sendDebugMessage(message, { sendNotification }) {
12
+ void sendNotification({
13
+ method: 'notifications/message',
14
+ params: {
15
+ level: 'debug',
16
+ data: message,
17
+ },
18
+ });
19
+ }
20
+ //# sourceMappingURL=send_debug_message.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send_debug_message.js","sourceRoot":"","sources":["send_debug_message.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;AAKH,4CAWC;AAXD,SAAgB,gBAAgB,CAC9B,OAAe,EACf,EAAE,gBAAgB,EAA0D;IAE5E,KAAK,gBAAgB,CAAC;QACpB,MAAM,EAAE,uBAAuB;QAC/B,MAAM,EAAE;YACN,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,OAAO;SACd;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,36 @@
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
+ import type { ImportSpecifier, NodeArray, SourceFile } from 'typescript';
9
+ import type ts from 'typescript';
10
+ export declare function loadTypescript(): Promise<typeof ts>;
11
+ /**
12
+ * Gets a top-level import specifier with a specific name that is imported from a particular module.
13
+ * E.g. given a file that looks like:
14
+ *
15
+ * ```ts
16
+ * import { Component, Directive } from '@angular/core';
17
+ * import { Foo } from './foo';
18
+ * ```
19
+ *
20
+ * Calling `getImportSpecifier(sourceFile, '@angular/core', 'Directive')` will yield the node
21
+ * referring to `Directive` in the top import.
22
+ *
23
+ * @param sourceFile File in which to look for imports.
24
+ * @param moduleName Name of the import's module.
25
+ * @param specifierName Original name of the specifier to look for. Aliases will be resolved to
26
+ * their original name.
27
+ */
28
+ export declare function getImportSpecifier(sourceFile: SourceFile, moduleName: string | RegExp, specifierName: string): Promise<ImportSpecifier | null>;
29
+ /**
30
+ * Finds an import specifier with a particular name.
31
+ * @param nodes Array of import specifiers to search through.
32
+ * @param specifierName Name of the specifier to look for.
33
+ */
34
+ export declare function findImportSpecifier(nodes: NodeArray<ImportSpecifier>, specifierName: string): ImportSpecifier | undefined;
35
+ /** Creates a TypeScript source file from a file path. */
36
+ export declare function createSourceFile(file: string): Promise<SourceFile>;