@angular/core 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 (106) 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-DR9xXCle.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-BXBP7CE2.cjs → compiler_host-DBwYMlTo.cjs} +10 -11
  38. package/schematics/bundles/control-flow-migration.cjs +122 -119
  39. package/schematics/bundles/{imports-CIX-JgAN.cjs → imports-DP72APSx.cjs} +6 -1
  40. package/schematics/bundles/{index-CfTQUOiz.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-6NtAj-Wk.cjs → migrate_ts_type_references-UGIUl7En.cjs} +500 -24
  44. package/schematics/bundles/ng_component_template-Dsuq1Lw7.cjs +185 -0
  45. package/schematics/bundles/{ng_decorators-B5HCqr20.cjs → ng_decorators-DSFlWYQY.cjs} +2 -2
  46. package/schematics/bundles/ngclass-to-class-migration.cjs +542 -0
  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-DcaODbky.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 +17 -216
  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 +23 -0
  65. package/schematics/migrations/common-to-standalone-migration/schema.json +14 -0
  66. package/schematics/migrations/ngclass-to-class-migration/schema.json +20 -0
  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} +26 -31
  72. package/{discovery.d.d.ts → types/_discovery-chunk.d.ts} +135 -98
  73. package/{signal.d.d.ts → types/_effect-chunk.d.ts} +14 -5
  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 -305
  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 -31833
  86. package/fesm2022/debug_node.mjs.map +0 -1
  87. package/fesm2022/not_found.mjs +0 -56
  88. package/fesm2022/not_found.mjs.map +0 -1
  89. package/fesm2022/primitives/di.mjs +0 -23
  90. package/fesm2022/primitives/di.mjs.map +0 -1
  91. package/fesm2022/primitives/event-dispatch.mjs +0 -1622
  92. package/fesm2022/primitives/event-dispatch.mjs.map +0 -1
  93. package/fesm2022/primitives/signals.mjs +0 -89
  94. package/fesm2022/primitives/signals.mjs.map +0 -1
  95. package/fesm2022/resource.mjs +0 -633
  96. package/fesm2022/resource.mjs.map +0 -1
  97. package/fesm2022/root_effect_scheduler.mjs +0 -4007
  98. package/fesm2022/root_effect_scheduler.mjs.map +0 -1
  99. package/fesm2022/signal.mjs +0 -560
  100. package/fesm2022/signal.mjs.map +0 -1
  101. package/fesm2022/untracked.mjs +0 -117
  102. package/fesm2022/untracked.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-esqfDjNB.cjs +0 -22074
  106. package/schematics/bundles/project_tsconfig_paths-CS-eSeHC.cjs +0 -51062
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v21.0.0-next.0
3
+ * @license Angular v21.0.0-next.10
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -10,22 +10,19 @@ var schematics = require('@angular-devkit/schematics');
10
10
  var signalQueriesMigration = require('./signal-queries-migration.cjs');
11
11
  var signalInputMigration = require('./signal-input-migration.cjs');
12
12
  var outputMigration = require('./output-migration.cjs');
13
- require('./project_tsconfig_paths-CS-eSeHC.cjs');
13
+ require('@angular/compiler-cli/private/migrations');
14
14
  require('typescript');
15
- require('os');
16
- require('fs');
17
- require('module');
18
- require('path');
19
- require('url');
20
- require('@angular-devkit/core');
21
- require('./index-esqfDjNB.cjs');
15
+ require('@angular/compiler-cli');
22
16
  require('node:path');
23
- require('./project_paths-DcaODbky.cjs');
17
+ require('./project_paths-DvD50ouC.cjs');
18
+ require('@angular-devkit/core');
24
19
  require('node:path/posix');
25
- require('./apply_import_manager-DR9xXCle.cjs');
26
- require('./migrate_ts_type_references-6NtAj-Wk.cjs');
20
+ require('./project_tsconfig_paths-CDVxT6Ov.cjs');
21
+ require('./apply_import_manager-1Zs_gpB6.cjs');
22
+ require('./migrate_ts_type_references-UGIUl7En.cjs');
27
23
  require('assert');
28
- require('./index-CfTQUOiz.cjs');
24
+ require('./index-B7I9sIUx.cjs');
25
+ require('@angular/compiler');
29
26
  require('./leading_space-D9nQ8UQC.cjs');
30
27
 
31
28
  function migrate(options) {
@@ -1,38 +1,25 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v21.0.0-next.0
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 schematics = require('@angular-devkit/schematics');
10
- var index = require('./index-esqfDjNB.cjs');
10
+ var compilerCli = require('@angular/compiler-cli');
11
11
  var fs = require('fs');
12
- var p = require('path');
12
+ var path = require('path');
13
13
  var ts = require('typescript');
14
- var compiler_host = require('./compiler_host-BXBP7CE2.cjs');
15
- var project_tsconfig_paths = require('./project_tsconfig_paths-CS-eSeHC.cjs');
16
- var ng_decorators = require('./ng_decorators-B5HCqr20.cjs');
14
+ var compiler_host = require('./compiler_host-DBwYMlTo.cjs');
15
+ var project_tsconfig_paths = require('./project_tsconfig_paths-CDVxT6Ov.cjs');
16
+ var ng_decorators = require('./ng_decorators-DSFlWYQY.cjs');
17
17
  var nodes = require('./nodes-B16H9JUd.cjs');
18
- var symbol = require('./symbol-VPWguRxr.cjs');
19
- var imports = require('./imports-CIX-JgAN.cjs');
20
- require('os');
21
- require('module');
22
- require('url');
18
+ var symbol = require('./symbol-BObKoqes.cjs');
19
+ var imports = require('./imports-DP72APSx.cjs');
20
+ var migrations = require('@angular/compiler-cli/private/migrations');
23
21
  require('@angular-devkit/core');
24
22
 
25
- function createProgram({ rootNames, options, host, oldProgram, }) {
26
- return new index.NgtscProgram(rootNames, options, host, oldProgram);
27
- }
28
-
29
- /*!
30
- * @license
31
- * Copyright Google LLC All Rights Reserved.
32
- *
33
- * Use of this source code is governed by an MIT-style license that can be
34
- * found in the LICENSE file at https://angular.dev/license
35
- */
36
23
  /** Utility class used to track a one-to-many relationship where all the items are unique. */
37
24
  class UniqueItemTracker {
38
25
  _nodes = new Map();
@@ -227,13 +214,13 @@ function findLiteralProperty(literal, name) {
227
214
  }
228
215
  /** Gets a relative path between two files that can be used inside a TypeScript import. */
229
216
  function getRelativeImportPath(fromFile, toFile) {
230
- let path = p.relative(p.dirname(fromFile), toFile).replace(/\.ts$/, '');
217
+ let path$1 = path.relative(path.dirname(fromFile), toFile).replace(/\.ts$/, '');
231
218
  // `relative` returns paths inside the same directory without `./`
232
- if (!path.startsWith('.')) {
233
- path = './' + path;
219
+ if (!path$1.startsWith('.')) {
220
+ path$1 = './' + path$1;
234
221
  }
235
222
  // Using the Node utilities can yield paths with forward slashes on Windows.
236
- return compiler_host.normalizePath(path);
223
+ return compiler_host.normalizePath(path$1);
237
224
  }
238
225
  /** Function used to remap the generated `imports` for a component to known shorter aliases. */
239
226
  function knownInternalAliasRemapper(imports) {
@@ -308,13 +295,6 @@ function isTestCall(typeChecker, node, testBedImport, catalystImport) {
308
295
  return !!(isTestBedCall || isCatalystCall);
309
296
  }
310
297
 
311
- /*!
312
- * @license
313
- * Copyright Google LLC All Rights Reserved.
314
- *
315
- * Use of this source code is governed by an MIT-style license that can be
316
- * found in the LICENSE file at https://angular.dev/license
317
- */
318
298
  /**
319
299
  * Converts all declarations in the specified files to standalone.
320
300
  * @param sourceFiles Files that should be migrated.
@@ -400,11 +380,18 @@ function getComponentImportExpressions(decl, allDeclarations, tracker, typeCheck
400
380
  const resolvedDependencies = [];
401
381
  for (const dep of templateDependencies) {
402
382
  const importLocation = findImportLocation(dep, decl, usedDependenciesInMigration.has(dep)
403
- ? project_tsconfig_paths.PotentialImportMode.ForceDirect
404
- : project_tsconfig_paths.PotentialImportMode.Normal, typeChecker);
405
- if (importLocation && !seenImports.has(importLocation.symbolName)) {
406
- seenImports.add(importLocation.symbolName);
407
- resolvedDependencies.push(importLocation);
383
+ ? migrations.PotentialImportMode.ForceDirect
384
+ : migrations.PotentialImportMode.Normal, typeChecker);
385
+ if (importLocation) {
386
+ // Create a unique key that includes both the symbol name and module specifier
387
+ // to handle cases where the same symbol name is imported from different modules
388
+ const importKey = importLocation.moduleSpecifier
389
+ ? `${importLocation.symbolName}::${importLocation.moduleSpecifier}`
390
+ : importLocation.symbolName;
391
+ if (!seenImports.has(importKey)) {
392
+ seenImports.add(importKey);
393
+ resolvedDependencies.push(importLocation);
394
+ }
408
395
  }
409
396
  }
410
397
  return potentialImportsToExpressions(resolvedDependencies, decl.getSourceFile(), tracker, importRemapper);
@@ -470,33 +457,42 @@ function moveDeclarationsToImports(literal, allDeclarations, typeChecker, templa
470
457
  ts.isArrayLiteralExpression(prop.initializer) &&
471
458
  prop.initializer.elements.hasTrailingComma);
472
459
  // Separate the declarations that we want to keep and ones we need to copy into the `imports`.
473
- if (ts.isPropertyAssignment(declarationsProp)) {
474
- // If the declarations are an array, we can analyze it to
475
- // find any classes from the current migration.
476
- if (ts.isArrayLiteralExpression(declarationsProp.initializer)) {
477
- for (const el of declarationsProp.initializer.elements) {
478
- if (ts.isIdentifier(el)) {
479
- const correspondingClass = findClassDeclaration(el, typeChecker);
480
- if (!correspondingClass ||
481
- // Check whether the declaration is either standalone already or is being converted
482
- // in this migration. We need to check if it's standalone already, in order to correct
483
- // some cases where the main app and the test files are being migrated in separate
484
- // programs.
485
- isStandaloneDeclaration(correspondingClass, allDeclarations, templateTypeChecker)) {
486
- declarationsToCopy.push(el);
460
+ if (ts.isPropertyAssignment(declarationsProp) ||
461
+ ts.isShorthandPropertyAssignment(declarationsProp)) {
462
+ // Handle both regular and shorthand property assignments
463
+ if (ts.isPropertyAssignment(declarationsProp)) {
464
+ // If the declarations are an array, we can analyze it to
465
+ // find any classes from the current migration.
466
+ if (ts.isArrayLiteralExpression(declarationsProp.initializer)) {
467
+ for (const el of declarationsProp.initializer.elements) {
468
+ if (ts.isIdentifier(el)) {
469
+ const correspondingClass = findClassDeclaration(el, typeChecker);
470
+ if (!correspondingClass ||
471
+ // Check whether the declaration is either standalone already or is being converted
472
+ // in this migration. We need to check if it's standalone already, in order to correct
473
+ // some cases where the main app and the test files are being migrated in separate
474
+ // programs.
475
+ isStandaloneDeclaration(correspondingClass, allDeclarations, templateTypeChecker)) {
476
+ declarationsToCopy.push(el);
477
+ }
478
+ else {
479
+ declarationsToPreserve.push(el);
480
+ }
487
481
  }
488
482
  else {
489
- declarationsToPreserve.push(el);
483
+ declarationsToCopy.push(el);
490
484
  }
491
485
  }
492
- else {
493
- declarationsToCopy.push(el);
494
- }
486
+ }
487
+ else {
488
+ // Otherwise create a spread that will be copied into the `imports`.
489
+ declarationsToCopy.push(ts.factory.createSpreadElement(declarationsProp.initializer));
495
490
  }
496
491
  }
497
492
  else {
498
- // Otherwise create a spread that will be copied into the `imports`.
499
- declarationsToCopy.push(ts.factory.createSpreadElement(declarationsProp.initializer));
493
+ // For shorthand properties, treat them as unanalyzable and use spread syntax
494
+ // shorthand properties were being ignored, now they're detected and treated as spreads
495
+ declarationsToCopy.push(ts.factory.createSpreadElement(declarationsProp.name));
500
496
  }
501
497
  }
502
498
  // If there are no `imports`, create them with the declarations we want to copy.
@@ -504,35 +500,38 @@ function moveDeclarationsToImports(literal, allDeclarations, typeChecker, templa
504
500
  properties.push(ts.factory.createPropertyAssignment('imports', ts.factory.createArrayLiteralExpression(ts.factory.createNodeArray(declarationsToCopy, hasAnyArrayTrailingComma && declarationsToCopy.length > 2))));
505
501
  }
506
502
  for (const prop of literal.properties) {
507
- if (!isNamedPropertyAssignment(prop)) {
503
+ if (!isNamedPropertyAssignment(prop) && !ts.isShorthandPropertyAssignment(prop)) {
508
504
  properties.push(prop);
509
505
  continue;
510
506
  }
511
507
  // If we have declarations to preserve, update the existing property, otherwise drop it.
512
508
  if (prop === declarationsProp) {
513
509
  if (declarationsToPreserve.length > 0) {
514
- const hasTrailingComma = ts.isArrayLiteralExpression(prop.initializer)
510
+ const hasTrailingComma = ts.isPropertyAssignment(prop) && ts.isArrayLiteralExpression(prop.initializer)
515
511
  ? prop.initializer.elements.hasTrailingComma
516
512
  : hasAnyArrayTrailingComma;
517
- properties.push(ts.factory.updatePropertyAssignment(prop, prop.name, ts.factory.createArrayLiteralExpression(ts.factory.createNodeArray(declarationsToPreserve, hasTrailingComma && declarationsToPreserve.length > 2))));
513
+ properties.push(ts.factory.createPropertyAssignment(prop.name, ts.factory.createArrayLiteralExpression(ts.factory.createNodeArray(declarationsToPreserve, hasTrailingComma && declarationsToPreserve.length > 2))));
518
514
  }
519
515
  continue;
520
516
  }
521
517
  // If we have an `imports` array and declarations
522
518
  // that should be copied, we merge the two arrays.
523
519
  if (prop === importsProp && declarationsToCopy.length > 0) {
524
- let initializer;
525
- if (ts.isArrayLiteralExpression(prop.initializer)) {
526
- initializer = ts.factory.updateArrayLiteralExpression(prop.initializer, ts.factory.createNodeArray([...prop.initializer.elements, ...declarationsToCopy], prop.initializer.elements.hasTrailingComma));
527
- }
528
- else {
529
- initializer = ts.factory.createArrayLiteralExpression(ts.factory.createNodeArray([ts.factory.createSpreadElement(prop.initializer), ...declarationsToCopy],
530
- // Expect the declarations to be greater than 1 since
531
- // we have the pre-existing initializer already.
532
- hasAnyArrayTrailingComma && declarationsToCopy.length > 1));
520
+ // Only regular property assignments have initializers that we can merge
521
+ if (ts.isPropertyAssignment(prop)) {
522
+ let initializer;
523
+ if (ts.isArrayLiteralExpression(prop.initializer)) {
524
+ initializer = ts.factory.updateArrayLiteralExpression(prop.initializer, ts.factory.createNodeArray([...prop.initializer.elements, ...declarationsToCopy], prop.initializer.elements.hasTrailingComma));
525
+ }
526
+ else {
527
+ initializer = ts.factory.createArrayLiteralExpression(ts.factory.createNodeArray([ts.factory.createSpreadElement(prop.initializer), ...declarationsToCopy],
528
+ // Expect the declarations to be greater than 1 since
529
+ // we have the pre-existing initializer already.
530
+ hasAnyArrayTrailingComma && declarationsToCopy.length > 1));
531
+ }
532
+ properties.push(ts.factory.updatePropertyAssignment(prop, prop.name, initializer));
533
+ continue;
533
534
  }
534
- properties.push(ts.factory.updatePropertyAssignment(prop, prop.name, initializer));
535
- continue;
536
535
  }
537
536
  // Retain any remaining properties.
538
537
  properties.push(prop);
@@ -621,13 +620,13 @@ function findImportLocation(target, inContext, importMode, typeChecker) {
621
620
  for (const location of importLocations) {
622
621
  // Prefer a standalone import, if we can find one.
623
622
  // Otherwise fall back to the first module-based import.
624
- if (location.kind === project_tsconfig_paths.PotentialImportKind.Standalone) {
623
+ if (location.kind === migrations.PotentialImportKind.Standalone) {
625
624
  return location;
626
625
  }
627
626
  if (!location.moduleSpecifier && !firstSameFileImport) {
628
627
  firstSameFileImport = location;
629
628
  }
630
- if (location.kind === project_tsconfig_paths.PotentialImportKind.NgModule &&
629
+ if (location.kind === migrations.PotentialImportKind.NgModule &&
631
630
  !firstModuleImport &&
632
631
  // ɵ is used for some internal Angular modules that we want to skip over.
633
632
  !location.symbolName.startsWith('ɵ')) {
@@ -642,8 +641,14 @@ function findImportLocation(target, inContext, importMode, typeChecker) {
642
641
  * but not `declarations: []`.
643
642
  */
644
643
  function hasNgModuleMetadataElements(node) {
645
- return (ts.isPropertyAssignment(node) &&
646
- (!ts.isArrayLiteralExpression(node.initializer) || node.initializer.elements.length > 0));
644
+ if (ts.isPropertyAssignment(node)) {
645
+ return !ts.isArrayLiteralExpression(node.initializer) || node.initializer.elements.length > 0;
646
+ }
647
+ if (ts.isShorthandPropertyAssignment(node)) {
648
+ // For shorthand properties, we assume they have elements since they reference a variable
649
+ return true;
650
+ }
651
+ return false;
647
652
  }
648
653
  /** Finds all modules whose declarations can be migrated. */
649
654
  function findNgModuleClassesToMigrate(sourceFile, typeChecker) {
@@ -820,6 +825,7 @@ function analyzeTestingModules(testObjects, typeChecker) {
820
825
  const importsProp = findLiteralProperty(obj, 'imports');
821
826
  const importElements = importsProp &&
822
827
  hasNgModuleMetadataElements(importsProp) &&
828
+ ts.isPropertyAssignment(importsProp) &&
823
829
  ts.isArrayLiteralExpression(importsProp.initializer)
824
830
  ? importsProp.initializer.elements.filter((el) => {
825
831
  // Filter out calls since they may be a `ModuleWithProviders`.
@@ -864,6 +870,7 @@ function extractDeclarationsFromTestObject(obj, typeChecker) {
864
870
  const declarations = findLiteralProperty(obj, 'declarations');
865
871
  if (declarations &&
866
872
  hasNgModuleMetadataElements(declarations) &&
873
+ ts.isPropertyAssignment(declarations) &&
867
874
  ts.isArrayLiteralExpression(declarations.initializer)) {
868
875
  for (const element of declarations.initializer.elements) {
869
876
  const declaration = findClassDeclaration(element, typeChecker);
@@ -900,13 +907,6 @@ function isStandaloneDeclaration(node, declarationsInMigration, templateTypeChec
900
907
  return metadata != null && metadata.isStandalone;
901
908
  }
902
909
 
903
- /*!
904
- * @license
905
- * Copyright Google LLC All Rights Reserved.
906
- *
907
- * Use of this source code is governed by an MIT-style license that can be
908
- * found in the LICENSE file at https://angular.dev/license
909
- */
910
910
  function pruneNgModules(program, host, basePath, rootFileNames, sourceFiles, printer, importRemapper, referenceLookupExcludedFiles, declarationImportRemapper) {
911
911
  const filesToRemove = new Set();
912
912
  const tracker = new compiler_host.ChangeTracker(printer, importRemapper);
@@ -944,7 +944,7 @@ function pruneNgModules(program, host, basePath, rootFileNames, sourceFiles, pri
944
944
  }
945
945
  node.forEachChild(walk);
946
946
  });
947
- replaceInComponentImportsArray(componentImportArrays, classesToRemove, tracker, typeChecker, templateTypeChecker, declarationImportRemapper);
947
+ replaceInComponentImportsArray(componentImportArrays, classesToRemove, removalLocations, tracker, typeChecker, templateTypeChecker, declarationImportRemapper);
948
948
  replaceInTestImportsArray(testArrays, removalLocations, classesToRemove, tracker, typeChecker, templateTypeChecker, declarationImportRemapper);
949
949
  // We collect all the places where we need to remove references first before generating the
950
950
  // removal instructions since we may have to remove multiple references from one node.
@@ -1050,12 +1050,13 @@ function collectChangeLocations(ngModule, removalLocations, componentImportArray
1050
1050
  * Replaces all the leftover modules in component `imports` arrays with their exports.
1051
1051
  * @param componentImportArrays All the imports arrays and their nodes that represent NgModules.
1052
1052
  * @param classesToRemove Set of classes that were marked for removal.
1053
+ * @param removalLocations Tracks the different places from which imports should be removed.
1053
1054
  * @param tracker
1054
1055
  * @param typeChecker
1055
1056
  * @param templateTypeChecker
1056
1057
  * @param importRemapper
1057
1058
  */
1058
- function replaceInComponentImportsArray(componentImportArrays, classesToRemove, tracker, typeChecker, templateTypeChecker, importRemapper) {
1059
+ function replaceInComponentImportsArray(componentImportArrays, classesToRemove, removalLocations, tracker, typeChecker, templateTypeChecker, importRemapper) {
1059
1060
  for (const [array, toReplace] of componentImportArrays.getEntries()) {
1060
1061
  const closestClass = nodes.closestNode(array, ts.isClassDeclaration);
1061
1062
  if (!closestClass) {
@@ -1063,16 +1064,35 @@ function replaceInComponentImportsArray(componentImportArrays, classesToRemove,
1063
1064
  }
1064
1065
  const replacements = new UniqueItemTracker();
1065
1066
  const usedImports = new Set(findTemplateDependencies(closestClass, templateTypeChecker).map((ref) => ref.node));
1067
+ const nodesToRemove = new Set();
1066
1068
  for (const node of toReplace) {
1067
1069
  const moduleDecl = findClassDeclaration(node, typeChecker);
1068
1070
  if (moduleDecl) {
1069
1071
  const moduleMeta = templateTypeChecker.getNgModuleMetadata(moduleDecl);
1070
1072
  if (moduleMeta) {
1073
+ let hasUsedExports = false;
1071
1074
  moduleMeta.exports.forEach((exp) => {
1072
1075
  if (usedImports.has(exp.node)) {
1073
1076
  replacements.track(node, exp);
1077
+ hasUsedExports = true;
1074
1078
  }
1075
1079
  });
1080
+ // If none of the module's exports are used, track the node for removal
1081
+ if (!hasUsedExports) {
1082
+ nodesToRemove.add(node);
1083
+ }
1084
+ else if (ts.isIdentifier(node)) {
1085
+ // Track the import statement for removal when replacing with exports
1086
+ const symbol = typeChecker.getSymbolAtLocation(node);
1087
+ const declarations = symbol?.declarations;
1088
+ if (declarations) {
1089
+ for (const declaration of declarations) {
1090
+ if (ts.isImportSpecifier(declaration)) {
1091
+ removalLocations.imports.track(declaration.parent, declaration);
1092
+ }
1093
+ }
1094
+ }
1095
+ }
1076
1096
  }
1077
1097
  else {
1078
1098
  // It's unlikely not to have module metadata at this point, but just in
@@ -1081,12 +1101,13 @@ function replaceInComponentImportsArray(componentImportArrays, classesToRemove,
1081
1101
  }
1082
1102
  }
1083
1103
  }
1084
- replaceModulesInImportsArray(array, replacements, tracker, templateTypeChecker, importRemapper);
1104
+ replaceModulesInImportsArray(array, replacements, nodesToRemove, tracker, templateTypeChecker, importRemapper);
1085
1105
  }
1086
1106
  }
1087
1107
  /**
1088
1108
  * Replaces all the leftover modules in testing `imports` arrays with their exports.
1089
1109
  * @param testImportArrays All test `imports` arrays and their nodes that represent modules.
1110
+ * @param removalLocations Tracks the different places from which imports should be removed.
1090
1111
  * @param classesToRemove Classes marked for removal by the migration.
1091
1112
  * @param tracker
1092
1113
  * @param typeChecker
@@ -1096,6 +1117,7 @@ function replaceInComponentImportsArray(componentImportArrays, classesToRemove,
1096
1117
  function replaceInTestImportsArray(testImportArrays, removalLocations, classesToRemove, tracker, typeChecker, templateTypeChecker, importRemapper) {
1097
1118
  for (const [array, toReplace] of testImportArrays.getEntries()) {
1098
1119
  const replacements = new UniqueItemTracker();
1120
+ const nodesToRemove = new Set();
1099
1121
  for (const node of toReplace) {
1100
1122
  const moduleDecl = findClassDeclaration(node, typeChecker);
1101
1123
  if (moduleDecl) {
@@ -1106,6 +1128,18 @@ function replaceInTestImportsArray(testImportArrays, removalLocations, classesTo
1106
1128
  const exports = moduleMeta.exports.filter((exp) => !classesToRemove.has(exp.node));
1107
1129
  if (exports.length > 0) {
1108
1130
  exports.forEach((exp) => replacements.track(node, exp));
1131
+ // Track the import statement for removal when replacing with exports
1132
+ if (ts.isIdentifier(node)) {
1133
+ const symbol = typeChecker.getSymbolAtLocation(node);
1134
+ const declarations = symbol?.declarations;
1135
+ if (declarations) {
1136
+ for (const declaration of declarations) {
1137
+ if (ts.isImportSpecifier(declaration)) {
1138
+ removalLocations.imports.track(declaration.parent, declaration);
1139
+ }
1140
+ }
1141
+ }
1142
+ }
1109
1143
  }
1110
1144
  else {
1111
1145
  removalLocations.arrays.track(array, node);
@@ -1118,19 +1152,21 @@ function replaceInTestImportsArray(testImportArrays, removalLocations, classesTo
1118
1152
  }
1119
1153
  }
1120
1154
  }
1121
- replaceModulesInImportsArray(array, replacements, tracker, templateTypeChecker, importRemapper);
1155
+ replaceModulesInImportsArray(array, replacements, nodesToRemove, tracker, templateTypeChecker, importRemapper);
1122
1156
  }
1123
1157
  }
1124
1158
  /**
1125
1159
  * Replaces any leftover modules in an `imports` arrays with a set of specified exports
1126
1160
  * @param array Imports array which is being migrated.
1127
1161
  * @param replacements Map of NgModule references to their exports.
1162
+ * @param nodesToRemove Set of nodes that should be removed without replacement (unused modules).
1128
1163
  * @param tracker
1164
+ * @param typeChecker
1129
1165
  * @param templateTypeChecker
1130
1166
  * @param importRemapper
1131
1167
  */
1132
- function replaceModulesInImportsArray(array, replacements, tracker, templateTypeChecker, importRemapper) {
1133
- if (replacements.isEmpty()) {
1168
+ function replaceModulesInImportsArray(array, replacements, nodesToRemove, tracker, templateTypeChecker, importRemapper) {
1169
+ if (replacements.isEmpty() && nodesToRemove.size === 0) {
1134
1170
  return;
1135
1171
  }
1136
1172
  const newElements = [];
@@ -1141,6 +1177,10 @@ function replaceModulesInImportsArray(array, replacements, tracker, templateType
1141
1177
  }
1142
1178
  }
1143
1179
  for (const element of array.elements) {
1180
+ // Check if this element should be removed entirely (unused module)
1181
+ if (nodesToRemove.has(element)) {
1182
+ continue;
1183
+ }
1144
1184
  const replacementRefs = replacements.get(element);
1145
1185
  if (!replacementRefs) {
1146
1186
  newElements.push(element);
@@ -1148,7 +1188,7 @@ function replaceModulesInImportsArray(array, replacements, tracker, templateType
1148
1188
  }
1149
1189
  const potentialImports = [];
1150
1190
  for (const ref of replacementRefs) {
1151
- const importLocation = findImportLocation(ref, array, project_tsconfig_paths.PotentialImportMode.Normal, templateTypeChecker);
1191
+ const importLocation = findImportLocation(ref, array, migrations.PotentialImportMode.Normal, templateTypeChecker);
1152
1192
  if (importLocation) {
1153
1193
  potentialImports.push(importLocation);
1154
1194
  }
@@ -1385,13 +1425,6 @@ function isInImportsArray(closestAssignment, closestArray) {
1385
1425
  closestAssignment.name.text === 'imports');
1386
1426
  }
1387
1427
 
1388
- /*!
1389
- * @license
1390
- * Copyright Google LLC All Rights Reserved.
1391
- *
1392
- * Use of this source code is governed by an MIT-style license that can be
1393
- * found in the LICENSE file at https://angular.dev/license
1394
- */
1395
1428
  function toStandaloneBootstrap(program, host, basePath, rootFileNames, sourceFiles, printer, importRemapper, referenceLookupExcludedFiles, declarationImportRemapper) {
1396
1429
  const tracker = new compiler_host.ChangeTracker(printer, importRemapper);
1397
1430
  const typeChecker = program.getTsProgram().getTypeChecker();
@@ -1913,7 +1946,7 @@ function isOutsideRange(excludeStart, excludeEnd, start, end) {
1913
1946
  * @param specifier Specifier whose path is being remapped.
1914
1947
  */
1915
1948
  function remapRelativeImport(targetFileName, specifier) {
1916
- return getRelativeImportPath(targetFileName, p.join(p.dirname(specifier.getSourceFile().fileName), specifier.text));
1949
+ return getRelativeImportPath(targetFileName, path.join(path.dirname(specifier.getSourceFile().fileName), specifier.text));
1917
1950
  }
1918
1951
  /**
1919
1952
  * Whether a node is exported.
@@ -1986,7 +2019,7 @@ function migrate(options) {
1986
2019
  const allPaths = [...buildPaths, ...testPaths];
1987
2020
  // TS and Schematic use paths in POSIX format even on Windows. This is needed as otherwise
1988
2021
  // string matching such as `sourceFile.fileName.startsWith(pathToMigrate)` might not work.
1989
- const pathToMigrate = compiler_host.normalizePath(p.join(basePath, options.path));
2022
+ const pathToMigrate = compiler_host.normalizePath(path.join(basePath, options.path));
1990
2023
  let migratedFiles = 0;
1991
2024
  if (!allPaths.length) {
1992
2025
  throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run the standalone migration.');
@@ -2014,7 +2047,7 @@ function standaloneMigration(tree, tsconfigPath, basePath, pathToMigrate, schema
2014
2047
  skipDefaultLibCheck: true,
2015
2048
  });
2016
2049
  const referenceLookupExcludedFiles = /node_modules|\.ngtypecheck\.ts/;
2017
- const program = createProgram({ rootNames, host, options, oldProgram });
2050
+ const program = compilerCli.createProgram({ rootNames, host, options, oldProgram });
2018
2051
  const printer = ts.createPrinter();
2019
2052
  if (fs.existsSync(pathToMigrate) && !fs.statSync(pathToMigrate).isDirectory()) {
2020
2053
  throw new schematics.SchematicsException(`Migration path ${pathToMigrate} has to be a directory. Cannot run the standalone migration.`);
@@ -2046,7 +2079,7 @@ function standaloneMigration(tree, tsconfigPath, basePath, pathToMigrate, schema
2046
2079
  if (filesToRemove?.has(file)) {
2047
2080
  continue;
2048
2081
  }
2049
- const update = tree.beginUpdate(p.relative(basePath, file.fileName));
2082
+ const update = tree.beginUpdate(path.relative(basePath, file.fileName));
2050
2083
  changes.forEach((change) => {
2051
2084
  if (change.removeLength != null) {
2052
2085
  update.remove(change.start, change.removeLength);
@@ -2057,7 +2090,7 @@ function standaloneMigration(tree, tsconfigPath, basePath, pathToMigrate, schema
2057
2090
  }
2058
2091
  if (filesToRemove) {
2059
2092
  for (const file of filesToRemove) {
2060
- tree.delete(p.relative(basePath, file.fileName));
2093
+ tree.delete(path.relative(basePath, file.fileName));
2061
2094
  }
2062
2095
  }
2063
2096
  // Run the module pruning after the standalone bootstrap to automatically remove the root module.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v21.0.0-next.0
3
+ * @license Angular v21.0.0-next.10
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -13,7 +13,8 @@ function isReferenceToImport(typeChecker, node, importSpecifier) {
13
13
  // If this function is called on an identifier (should be most cases), we can quickly rule out
14
14
  // non-matches by comparing the identifier's string and the local name of the import specifier
15
15
  // which saves us some calls to the type checker.
16
- if (ts.isIdentifier(node) && node.text !== importSpecifier.name.text) {
16
+ if (importSpecifier === null ||
17
+ (ts.isIdentifier(node) && node.text !== importSpecifier.name.text)) {
17
18
  return false;
18
19
  }
19
20
  const nodeSymbol = typeChecker.getTypeAtLocation(node).getSymbol();
@@ -52,11 +52,34 @@
52
52
  "schema": "./ng-generate/self-closing-tags-migration/schema.json",
53
53
  "aliases": ["self-closing-tag"]
54
54
  },
55
+ "common-to-standalone-migration": {
56
+ "description": "Replaces CommonModule with individual imports from @angular/common",
57
+ "factory": "./bundles/common-to-standalone-migration.cjs#migrate",
58
+ "schema": "./migrations/common-to-standalone-migration/schema.json",
59
+ "aliases": ["common-to-standalone"]
60
+ },
55
61
  "control-flow-migration": {
56
62
  "description": "Converts the entire application to block control flow syntax",
57
63
  "factory": "./bundles/control-flow-migration.cjs#migrate",
58
64
  "schema": "./migrations/control-flow-migration/schema.json",
59
65
  "aliases": ["control-flow"]
66
+ },
67
+ "ngclass-to-class-migration": {
68
+ "description": "Updates usages of `ngClass` directives to the `class` bindings where possible",
69
+ "factory": "./bundles/ngclass-to-class-migration.cjs#migrate",
70
+ "schema": "./migrations/ngclass-to-class-migration/schema.json",
71
+ "aliases": ["ngclass-to-class"]
72
+ },
73
+ "ngstyle-to-style-migration": {
74
+ "description": "Updates usages of `ngStyle` directives to the `style` bindings where possible",
75
+ "factory": "./bundles/ngstyle-to-style-migration.cjs#migrate",
76
+ "schema": "./migrations/ngstyle-to-style-migration/schema.json",
77
+ "aliases": ["ngstyle-to-style"]
78
+ },
79
+ "router-testing-module-migration": {
80
+ "description": "Replaces deprecated RouterTestingModule with provideRouter() as recommended in the deprecation note",
81
+ "factory": "./bundles/router-testing-module-migration.cjs#migrate",
82
+ "schema": "./migrations/router-testing-module-migration/schema.json"
60
83
  }
61
84
  }
62
85
  }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "AngularCommonToStandaloneMigration",
4
+ "title": "Angular Common to Standalone Migration Schema",
5
+ "type": "object",
6
+ "properties": {
7
+ "path": {
8
+ "type": "string",
9
+ "description": "Path to the directory where all components and modules should be migrated.",
10
+ "x-prompt": "Which directory do you want to migrate?",
11
+ "default": "./"
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "AngularNgclassToClassMigration",
4
+ "title": "Angular ngClass to class Migration Schema",
5
+ "type": "object",
6
+ "properties": {
7
+ "path": {
8
+ "type": "string",
9
+ "description": "Path to the directory where all templates should be migrated.",
10
+ "x-prompt": "Which directory do you want to migrate?",
11
+ "default": "./"
12
+ },
13
+ "migrateSpaceSeparatedKey": {
14
+ "type": "boolean",
15
+ "description": "Enables the migration of object literals with space-separated keys",
16
+ "x-prompt": "Should the migration also migrate space-separated keys?",
17
+ "default": false
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "AngularNgStyleToStyleMigration",
4
+ "title": "Angular ngStyle to style Migration Schema",
5
+ "type": "object",
6
+ "properties": {
7
+ "path": {
8
+ "type": "string",
9
+ "description": "Path to the directory where all templates should be migrated.",
10
+ "x-prompt": "Which directory do you want to migrate?",
11
+ "default": "./"
12
+ },
13
+ "bestEffortMode": {
14
+ "type": "boolean",
15
+ "description": "Enables the migration of object references",
16
+ "x-prompt": "Should the migration also migrate object references?",
17
+ "default": false
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "AngularRouterTestingToProvideRouterMigration",
4
+ "title": "Angular RouterTestingModule to provideRouter Migration Schema",
5
+ "type": "object",
6
+ "properties": {
7
+ "path": {
8
+ "type": "string",
9
+ "description": "Path to the directory where all tests should be migrated.",
10
+ "x-prompt": "Which directory do you want to migrate?",
11
+ "default": "./"
12
+ }
13
+ }
14
+ }