@angular/core 21.0.0-next.1 → 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 (107) hide show
  1. package/fesm2022/_attribute-chunk.mjs +12 -0
  2. package/fesm2022/_attribute-chunk.mjs.map +1 -0
  3. package/fesm2022/_debug_node-chunk.mjs +18469 -0
  4. package/fesm2022/_debug_node-chunk.mjs.map +1 -0
  5. package/fesm2022/_effect-chunk.mjs +423 -0
  6. package/fesm2022/_effect-chunk.mjs.map +1 -0
  7. package/fesm2022/_effect-chunk2.mjs +2951 -0
  8. package/fesm2022/_effect-chunk2.mjs.map +1 -0
  9. package/fesm2022/_not_found-chunk.mjs +39 -0
  10. package/fesm2022/_not_found-chunk.mjs.map +1 -0
  11. package/fesm2022/_resource-chunk.mjs +378 -0
  12. package/fesm2022/_resource-chunk.mjs.map +1 -0
  13. package/fesm2022/_untracked-chunk.mjs +96 -0
  14. package/fesm2022/_untracked-chunk.mjs.map +1 -0
  15. package/fesm2022/_weak_ref-chunk.mjs +10 -0
  16. package/fesm2022/_weak_ref-chunk.mjs.map +1 -0
  17. package/fesm2022/core.mjs +2499 -4185
  18. package/fesm2022/core.mjs.map +1 -1
  19. package/fesm2022/primitives-di.mjs +23 -0
  20. package/fesm2022/primitives-di.mjs.map +1 -0
  21. package/fesm2022/primitives-event-dispatch.mjs +788 -0
  22. package/fesm2022/primitives-event-dispatch.mjs.map +1 -0
  23. package/fesm2022/primitives-signals.mjs +187 -0
  24. package/fesm2022/primitives-signals.mjs.map +1 -0
  25. package/fesm2022/rxjs-interop.mjs +210 -308
  26. package/fesm2022/rxjs-interop.mjs.map +1 -1
  27. package/fesm2022/testing.mjs +2309 -3170
  28. package/fesm2022/testing.mjs.map +1 -1
  29. package/package.json +18 -12
  30. package/resources/best-practices.md +56 -0
  31. package/schematics/bundles/add-bootstrap-context-to-server-main.cjs +117 -0
  32. package/schematics/bundles/application-config-core.cjs +84 -0
  33. package/schematics/bundles/{apply_import_manager-yycO3l8f.cjs → apply_import_manager-1Zs_gpB6.cjs} +4 -5
  34. package/schematics/bundles/bootstrap-options-migration.cjs +598 -0
  35. package/schematics/bundles/cleanup-unused-imports.cjs +9 -13
  36. package/schematics/bundles/common-to-standalone-migration.cjs +381 -0
  37. package/schematics/bundles/{compiler_host-DrXTGf_7.cjs → compiler_host-DBwYMlTo.cjs} +10 -11
  38. package/schematics/bundles/control-flow-migration.cjs +113 -82
  39. package/schematics/bundles/{imports-26VeX8i-.cjs → imports-DP72APSx.cjs} +5 -1
  40. package/schematics/bundles/{index-BdH2rlWJ.cjs → index-B7I9sIUx.cjs} +36 -39
  41. package/schematics/bundles/inject-migration.cjs +148 -70
  42. package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
  43. package/schematics/bundles/{migrate_ts_type_references-BVSg43hf.cjs → migrate_ts_type_references-UGIUl7En.cjs} +500 -24
  44. package/schematics/bundles/{ng_component_template-DjLc4mdL.cjs → ng_component_template-Dsuq1Lw7.cjs} +4 -5
  45. package/schematics/bundles/{ng_decorators-CtYwz9Lw.cjs → ng_decorators-DSFlWYQY.cjs} +2 -2
  46. package/schematics/bundles/ngclass-to-class-migration.cjs +118 -109
  47. package/schematics/bundles/ngstyle-to-style-migration.cjs +487 -0
  48. package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
  49. package/schematics/bundles/output-migration.cjs +16 -19
  50. package/schematics/bundles/parse_html-8VLCL37B.cjs +132 -0
  51. package/schematics/bundles/{project_paths-T_M15e2g.cjs → project_paths-DvD50ouC.cjs} +14 -247
  52. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +90 -0
  53. package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
  54. package/schematics/bundles/route-lazy-loading.cjs +54 -26
  55. package/schematics/bundles/router-current-navigation.cjs +7 -18
  56. package/schematics/bundles/router-last-successful-navigation.cjs +7 -18
  57. package/schematics/bundles/router-testing-module-migration.cjs +502 -0
  58. package/schematics/bundles/self-closing-tags-migration.cjs +14 -17
  59. package/schematics/bundles/signal-input-migration.cjs +93 -29
  60. package/schematics/bundles/signal-queries-migration.cjs +22 -25
  61. package/schematics/bundles/signals.cjs +10 -13
  62. package/schematics/bundles/standalone-migration.cjs +135 -102
  63. package/schematics/bundles/{symbol-VPWguRxr.cjs → symbol-BObKoqes.cjs} +3 -2
  64. package/schematics/collection.json +17 -0
  65. package/schematics/migrations/common-to-standalone-migration/schema.json +14 -0
  66. package/schematics/migrations/ngclass-to-class-migration/schema.json +2 -2
  67. package/schematics/migrations/ngstyle-to-style-migration/schema.json +20 -0
  68. package/schematics/migrations/router-testing-module-migration/schema.json +14 -0
  69. package/schematics/migrations.json +16 -2
  70. package/{api.d.d.ts → types/_api-chunk.d.ts} +9 -6
  71. package/{chrome_dev_tools_performance.d.d.ts → types/_chrome_dev_tools_performance-chunk.d.ts} +25 -15
  72. package/{discovery.d.d.ts → types/_discovery-chunk.d.ts} +130 -75
  73. package/{effect.d.d.ts → types/_effect-chunk.d.ts} +3 -4
  74. package/{event_dispatcher.d.d.ts → types/_event_dispatcher-chunk.d.ts} +2 -2
  75. package/{graph.d.d.ts → types/_formatter-chunk.d.ts} +40 -7
  76. package/{weak_ref.d.d.ts → types/_weak_ref-chunk.d.ts} +2 -2
  77. package/{index.d.ts → types/core.d.ts} +233 -298
  78. package/{primitives/di/index.d.ts → types/primitives-di.d.ts} +2 -2
  79. package/{primitives/event-dispatch/index.d.ts → types/primitives-event-dispatch.d.ts} +4 -4
  80. package/{primitives/signals/index.d.ts → types/primitives-signals.d.ts} +7 -8
  81. package/{rxjs-interop/index.d.ts → types/rxjs-interop.d.ts} +8 -6
  82. package/{testing/index.d.ts → types/testing.d.ts} +7 -7
  83. package/fesm2022/attribute.mjs +0 -24
  84. package/fesm2022/attribute.mjs.map +0 -1
  85. package/fesm2022/debug_node.mjs +0 -31829
  86. package/fesm2022/debug_node.mjs.map +0 -1
  87. package/fesm2022/effect.mjs +0 -142
  88. package/fesm2022/effect.mjs.map +0 -1
  89. package/fesm2022/not_found.mjs +0 -56
  90. package/fesm2022/not_found.mjs.map +0 -1
  91. package/fesm2022/primitives/di.mjs +0 -23
  92. package/fesm2022/primitives/di.mjs.map +0 -1
  93. package/fesm2022/primitives/event-dispatch.mjs +0 -1622
  94. package/fesm2022/primitives/event-dispatch.mjs.map +0 -1
  95. package/fesm2022/primitives/signals.mjs +0 -89
  96. package/fesm2022/primitives/signals.mjs.map +0 -1
  97. package/fesm2022/resource.mjs +0 -624
  98. package/fesm2022/resource.mjs.map +0 -1
  99. package/fesm2022/root_effect_scheduler.mjs +0 -4001
  100. package/fesm2022/root_effect_scheduler.mjs.map +0 -1
  101. package/fesm2022/signal.mjs +0 -560
  102. package/fesm2022/signal.mjs.map +0 -1
  103. package/fesm2022/weak_ref.mjs +0 -12
  104. package/fesm2022/weak_ref.mjs.map +0 -1
  105. package/schematics/bundles/index-jjHOgYYs.cjs +0 -22074
  106. package/schematics/bundles/parse_html-CXR8hziE.cjs +0 -41
  107. package/schematics/bundles/project_tsconfig_paths-D7xzGqRi.cjs +0 -51085
@@ -1,29 +1,26 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v21.0.0-next.1
3
+ * @license Angular v21.0.0-next.10
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
7
7
  'use strict';
8
8
 
9
9
  var ts = require('typescript');
10
- require('os');
11
- var project_tsconfig_paths = require('./project_tsconfig_paths-D7xzGqRi.cjs');
12
- var index = require('./index-jjHOgYYs.cjs');
13
- require('path');
10
+ require('@angular/compiler-cli');
11
+ var migrations = require('@angular/compiler-cli/private/migrations');
14
12
  require('node:path');
15
- var project_paths = require('./project_paths-T_M15e2g.cjs');
16
- var apply_import_manager = require('./apply_import_manager-yycO3l8f.cjs');
17
- var imports = require('./imports-26VeX8i-.cjs');
18
- var parse_html = require('./parse_html-CXR8hziE.cjs');
19
- var ng_component_template = require('./ng_component_template-DjLc4mdL.cjs');
13
+ var project_paths = require('./project_paths-DvD50ouC.cjs');
14
+ var compiler = require('@angular/compiler');
15
+ var apply_import_manager = require('./apply_import_manager-1Zs_gpB6.cjs');
16
+ var imports = require('./imports-DP72APSx.cjs');
17
+ var parse_html = require('./parse_html-8VLCL37B.cjs');
18
+ var ng_component_template = require('./ng_component_template-Dsuq1Lw7.cjs');
20
19
  require('@angular-devkit/core');
21
20
  require('node:path/posix');
22
- require('fs');
23
- require('module');
24
- require('url');
25
21
  require('@angular-devkit/schematics');
26
- require('./ng_decorators-CtYwz9Lw.cjs');
22
+ require('./project_tsconfig_paths-CDVxT6Ov.cjs');
23
+ require('./ng_decorators-DSFlWYQY.cjs');
27
24
  require('./property_name-BBwFuqMe.cjs');
28
25
 
29
26
  const ngClassStr = 'NgClass';
@@ -32,10 +29,10 @@ const commonModuleImportsStr = 'CommonModule';
32
29
  function migrateNgClassBindings(template, config, componentNode, typeChecker) {
33
30
  const parsed = parse_html.parseTemplate(template);
34
31
  if (!parsed.tree || !parsed.tree.rootNodes.length) {
35
- return { migrated: template, changed: false, replacementCount: 0 };
32
+ return { migrated: template, changed: false, replacementCount: 0, canRemoveCommonModule: false };
36
33
  }
37
34
  const visitor = new NgClassCollector(template, componentNode, typeChecker);
38
- project_tsconfig_paths.visitAll$1(visitor, parsed.tree.rootNodes, config);
35
+ compiler.visitAll(visitor, parsed.tree.rootNodes, config);
39
36
  let newTemplate = template;
40
37
  let changedOffset = 0;
41
38
  let replacementCount = 0;
@@ -45,15 +42,21 @@ function migrateNgClassBindings(template, config, componentNode, typeChecker) {
45
42
  changedOffset += newTemplate.length - currentLength;
46
43
  replacementCount++;
47
44
  }
48
- return { migrated: newTemplate, changed: newTemplate !== template, replacementCount };
45
+ const changed = newTemplate !== template;
46
+ return {
47
+ migrated: newTemplate,
48
+ changed,
49
+ replacementCount,
50
+ canRemoveCommonModule: changed ? parse_html.canRemoveCommonModule(newTemplate) : false,
51
+ };
49
52
  }
50
53
  /**
51
54
  * Creates a Replacement to remove `NgClass` from a component's `imports` array.
52
55
  * Uses ReflectionHost + PartialEvaluator for robust AST analysis.
53
56
  */
54
- function createNgClassImportsArrayRemoval(classNode, file, typeChecker) {
55
- const reflector = new project_tsconfig_paths.TypeScriptReflectionHost(typeChecker);
56
- const evaluator = new index.PartialEvaluator(reflector, typeChecker, null);
57
+ function createNgClassImportsArrayRemoval(classNode, file, typeChecker, removeCommonModule) {
58
+ const reflector = new migrations.TypeScriptReflectionHost(typeChecker);
59
+ const evaluator = new migrations.PartialEvaluator(reflector, typeChecker, null);
57
60
  // Use ReflectionHost to get decorators instead of manual AST traversal
58
61
  const decorators = reflector.getDecoratorsOfDeclaration(classNode);
59
62
  if (!decorators) {
@@ -84,74 +87,66 @@ function createNgClassImportsArrayRemoval(classNode, file, typeChecker) {
84
87
  return null;
85
88
  }
86
89
  const importsArray = importsProperty.initializer;
87
- const ngClassIndex = importsArray.elements.findIndex((e) => ts.isIdentifier(e) && e.text === ngClassStr);
88
- if (ngClassIndex === -1) {
89
- return null;
90
- }
91
- const elements = importsArray.elements;
92
- const ngClassElement = elements[ngClassIndex];
93
- const range = getNgClassRemovalRange(importsProperty, importsArray, ngClassElement, classNode.getSourceFile());
94
- return new project_paths.Replacement(file, new project_paths.TextUpdate({ position: range.start, end: range.end, toInsert: '' }));
95
- }
96
- function getElementRemovalRange(elementNode, sourceFile) {
97
- const parent = elementNode.parent;
98
- // Check if in array context (imports: [..]) or object context (@Component({..}))
99
- const isArrayLiteralExpression = ts.isArrayLiteralExpression(parent);
100
- const isObjectLiteralExpression = ts.isObjectLiteralExpression(parent);
101
- let elements;
102
- if (isArrayLiteralExpression) {
103
- elements = parent.elements;
104
- }
105
- else if (isObjectLiteralExpression) {
106
- elements = parent.properties;
107
- }
108
- else {
109
- return { start: elementNode.getStart(sourceFile), end: elementNode.getEnd() };
110
- }
111
- const elementIndex = elements.indexOf(elementNode);
112
- const isLastElement = elementIndex === elements.length - 1;
113
- if (isLastElement) {
114
- // If this is the LAST element, the range is from the END of the previous element
115
- // to the END of this element. This captures the comma and space preceding it.
116
- // Ex: `[a, b]` -> remove `, b`
117
- const start = elementIndex > 0 ? elements[elementIndex - 1].getEnd() : elementNode.getStart(sourceFile); // If it is also the first (only) element, there is no comma before it.
118
- return { start: start, end: elementNode.getEnd() };
119
- }
120
- else {
121
- // If it's the FIRST or MIDDLE element, the range goes from the BEGINNING of this element
122
- // to the BEGINNING of the next one. This captures the element itself and the comma that FOLLOWS it.
123
- // Ex: `[a, b]` -> remove `a,`
124
- const nextElement = elements[elementIndex + 1];
125
- return {
126
- start: elementNode.getStart(sourceFile),
127
- end: nextElement.getStart(sourceFile),
128
- };
129
- }
90
+ const elementsToRemove = new Set([ngClassStr]);
91
+ if (removeCommonModule) {
92
+ elementsToRemove.add(commonModuleImportsStr);
93
+ }
94
+ const originalElements = importsArray.elements;
95
+ const filteredElements = originalElements.filter((el) => !ts.isIdentifier(el) || !elementsToRemove.has(el.text));
96
+ if (filteredElements.length === originalElements.length) {
97
+ return null; // No changes needed.
98
+ }
99
+ // If the array becomes empty, remove the entire `imports` property.
100
+ if (filteredElements.length === 0) {
101
+ const removalRange = getPropertyRemovalRange(importsProperty);
102
+ return new project_paths.Replacement(file, new project_paths.TextUpdate({
103
+ position: removalRange.start,
104
+ end: removalRange.end,
105
+ toInsert: '',
106
+ }));
107
+ }
108
+ const printer = ts.createPrinter();
109
+ const newArray = ts.factory.updateArrayLiteralExpression(importsArray, filteredElements);
110
+ const newText = printer.printNode(ts.EmitHint.Unspecified, newArray, classNode.getSourceFile());
111
+ return new project_paths.Replacement(file, new project_paths.TextUpdate({
112
+ position: importsArray.getStart(),
113
+ end: importsArray.getEnd(),
114
+ toInsert: newText,
115
+ }));
130
116
  }
131
- /**
132
- * If there is more than one import, it affects the NgClass element within the array.
133
- * Otherwise, `NgClass` is the only import. The removal affects the entire `imports: [...]` property.
134
- */
135
- function getNgClassRemovalRange(importsProperty, importsArray, ngClassElement, sourceFile) {
136
- if (importsArray.elements.length > 1) {
137
- return getElementRemovalRange(ngClassElement, sourceFile);
138
- }
139
- else {
140
- return getElementRemovalRange(importsProperty, sourceFile);
141
- }
117
+ function getPropertyRemovalRange(property) {
118
+ const parent = property.parent;
119
+ if (!ts.isObjectLiteralExpression(parent)) {
120
+ return { start: property.getStart(), end: property.getEnd() };
121
+ }
122
+ const properties = parent.properties;
123
+ const propertyIndex = properties.indexOf(property);
124
+ const end = property.getEnd();
125
+ if (propertyIndex < properties.length - 1) {
126
+ const nextProperty = properties[propertyIndex + 1];
127
+ return { start: property.getStart(), end: nextProperty.getStart() };
128
+ }
129
+ return { start: property.getStart(), end };
142
130
  }
143
- function calculateImportReplacements(info, sourceFiles) {
131
+ function calculateImportReplacements(info, sourceFiles, filesToRemoveCommonModule) {
144
132
  const importReplacements = {};
145
- const importManager = new project_tsconfig_paths.ImportManager();
133
+ const importManager = new migrations.ImportManager();
146
134
  for (const sf of sourceFiles) {
147
135
  const file = project_paths.projectFile(sf, info);
136
+ // Always remove NgClass if it's imported directly.
148
137
  importManager.removeImport(sf, ngClassStr, commonModuleStr);
138
+ // Conditionally remove CommonModule if it's no longer needed.
139
+ if (filesToRemoveCommonModule.has(file.id)) {
140
+ importManager.removeImport(sf, commonModuleImportsStr, commonModuleStr);
141
+ }
149
142
  const addRemove = [];
150
143
  apply_import_manager.applyImportManagerChanges(importManager, addRemove, [sf], info);
151
- importReplacements[file.id] = {
152
- add: [],
153
- addAndRemove: addRemove,
154
- };
144
+ if (addRemove.length > 0) {
145
+ importReplacements[file.id] = {
146
+ add: [],
147
+ addAndRemove: addRemove,
148
+ };
149
+ }
155
150
  }
156
151
  return importReplacements;
157
152
  }
@@ -162,7 +157,7 @@ function replaceTemplate(template, replaceValue, start, end, offset) {
162
157
  * Visitor class that scans Angular templates and collects replacements
163
158
  * for [ngClass] bindings that use static object literals.
164
159
  */
165
- class NgClassCollector extends project_tsconfig_paths.RecursiveVisitor$1 {
160
+ class NgClassCollector extends compiler.RecursiveVisitor {
166
161
  componentNode;
167
162
  typeChecker;
168
163
  replacements = [];
@@ -390,11 +385,27 @@ class NgClassMigration extends project_paths.TsurgeFunnelMigration {
390
385
  super();
391
386
  this.config = config;
392
387
  }
388
+ processTemplate(template, node, file, info, typeChecker) {
389
+ const { migrated, changed, replacementCount, canRemoveCommonModule } = migrateNgClassBindings(template.content, this.config, node, typeChecker);
390
+ if (!changed) {
391
+ return null;
392
+ }
393
+ const fileToMigrate = template.inline
394
+ ? file
395
+ : project_paths.projectFile(template.filePath, info);
396
+ const end = template.start + template.content.length;
397
+ return {
398
+ replacements: [prepareTextReplacement(fileToMigrate, migrated, template.start, end)],
399
+ replacementCount,
400
+ canRemoveCommonModule,
401
+ };
402
+ }
393
403
  async analyze(info) {
394
404
  const { sourceFiles, program } = info;
395
405
  const typeChecker = program.getTypeChecker();
396
406
  const ngClassReplacements = [];
397
407
  const filesWithNgClassDeclarations = new Set();
408
+ const filesToRemoveCommonModule = new Set();
398
409
  for (const sf of sourceFiles) {
399
410
  ts.forEachChild(sf, (node) => {
400
411
  if (!ts.isClassDeclaration(node)) {
@@ -408,42 +419,40 @@ class NgClassMigration extends project_paths.TsurgeFunnelMigration {
408
419
  templateVisitor.visitNode(node);
409
420
  const replacementsForClass = [];
410
421
  let replacementCountForClass = 0;
411
- templateVisitor.resolvedTemplates.forEach((template) => {
412
- const { migrated, changed, replacementCount } = migrateNgClassBindings(template.content, this.config, node, typeChecker);
413
- if (!changed) {
414
- return;
422
+ let canRemoveCommonModuleForFile = true;
423
+ for (const template of templateVisitor.resolvedTemplates) {
424
+ const result = this.processTemplate(template, node, file, info, typeChecker);
425
+ if (result) {
426
+ replacementsForClass.push(...result.replacements);
427
+ replacementCountForClass += result.replacementCount;
428
+ if (!result.canRemoveCommonModule) {
429
+ canRemoveCommonModuleForFile = false;
430
+ }
415
431
  }
416
- replacementCountForClass += replacementCount;
417
- const fileToMigrate = template.inline
418
- ? file
419
- : project_paths.projectFile(template.filePath, info);
420
- const end = template.start + template.content.length;
421
- replacementsForClass.push(prepareTextReplacement(fileToMigrate, migrated, template.start, end));
422
- });
423
- if (replacementCountForClass === 0) {
424
- return;
425
- }
426
- filesWithNgClassDeclarations.add(sf);
427
- const importArrayRemoval = createNgClassImportsArrayRemoval(node, file, typeChecker);
428
- if (importArrayRemoval) {
429
- replacementsForClass.push(importArrayRemoval);
430
- }
431
- const existing = ngClassReplacements.find((entry) => entry.file === file);
432
- if (existing) {
433
- existing.replacements.push(...replacementsForClass);
434
- existing.replacementCount += replacementCountForClass;
435
432
  }
436
- else {
433
+ if (replacementsForClass.length > 0) {
434
+ if (canRemoveCommonModuleForFile) {
435
+ filesToRemoveCommonModule.add(file.id);
436
+ }
437
+ // Handle the `@Component({ imports: [...] })` array.
438
+ const importsRemoval = createNgClassImportsArrayRemoval(node, file, typeChecker, canRemoveCommonModuleForFile);
439
+ if (importsRemoval) {
440
+ replacementsForClass.push(importsRemoval);
441
+ }
437
442
  ngClassReplacements.push({
438
443
  file,
439
- replacements: replacementsForClass,
440
444
  replacementCount: replacementCountForClass,
445
+ replacements: replacementsForClass,
441
446
  });
447
+ filesWithNgClassDeclarations.add(sf);
442
448
  }
443
449
  });
444
450
  }
445
- const importReplacements = calculateImportReplacements(info, filesWithNgClassDeclarations);
446
- return project_paths.confirmAsSerializable({ ngClassReplacements, importReplacements });
451
+ const importReplacements = calculateImportReplacements(info, filesWithNgClassDeclarations, filesToRemoveCommonModule);
452
+ return project_paths.confirmAsSerializable({
453
+ ngClassReplacements,
454
+ importReplacements,
455
+ });
447
456
  }
448
457
  async combine(unitA, unitB) {
449
458
  const importReplacements = {};
@@ -511,7 +520,7 @@ function migrate(options) {
511
520
  }
512
521
  },
513
522
  beforeUnitAnalysis: (tsconfigPath) => {
514
- context.logger.info(`Scanning for component tags: ${tsconfigPath}...`);
523
+ context.logger.info(`Scanning for ngClass bindings: ${tsconfigPath}...`);
515
524
  },
516
525
  afterAllAnalyzed: () => {
517
526
  context.logger.info(``);