@angular/core 20.0.0-next.4 → 20.0.0-next.6

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 (76) hide show
  1. package/api.d-DQLNOR5l.d.ts +297 -0
  2. package/discovery.d-CFs2MaLO.d.ts +7383 -0
  3. package/{event_dispatcher.d-pVP0-wST.d.ts → event_dispatcher.d-DlbccpYq.d.ts} +3 -2
  4. package/fesm2022/attribute-BWp59EjE.mjs +24 -0
  5. package/fesm2022/attribute-BWp59EjE.mjs.map +1 -0
  6. package/fesm2022/core.mjs +586 -36873
  7. package/fesm2022/core.mjs.map +1 -1
  8. package/fesm2022/debug_node-z_3NG8qT.mjs +32079 -0
  9. package/fesm2022/debug_node-z_3NG8qT.mjs.map +1 -0
  10. package/fesm2022/primitives/di.mjs +18 -4
  11. package/fesm2022/primitives/di.mjs.map +1 -1
  12. package/fesm2022/primitives/event-dispatch.mjs +2 -16
  13. package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
  14. package/fesm2022/primitives/signals.mjs +5 -3
  15. package/fesm2022/primitives/signals.mjs.map +1 -1
  16. package/fesm2022/resource-CPPwEcg7.mjs +619 -0
  17. package/fesm2022/resource-CPPwEcg7.mjs.map +1 -0
  18. package/fesm2022/root_effect_scheduler-VSXfCzDX.mjs +3847 -0
  19. package/fesm2022/root_effect_scheduler-VSXfCzDX.mjs.map +1 -0
  20. package/fesm2022/rxjs-interop.mjs +16 -9
  21. package/fesm2022/rxjs-interop.mjs.map +1 -1
  22. package/fesm2022/{untracked-DkcXpNb_.mjs → signal-B6pMq7KS.mjs} +16 -114
  23. package/fesm2022/signal-B6pMq7KS.mjs.map +1 -0
  24. package/fesm2022/testing.mjs +265 -201
  25. package/fesm2022/testing.mjs.map +1 -1
  26. package/fesm2022/untracked-Bz5WMeU1.mjs +117 -0
  27. package/fesm2022/untracked-Bz5WMeU1.mjs.map +1 -0
  28. package/fesm2022/weak_ref-BaIq-pgY.mjs +12 -0
  29. package/fesm2022/weak_ref-BaIq-pgY.mjs.map +1 -0
  30. package/{weak_ref.d-BZ7gyRag.d.ts → graph.d-BcIOep_B.d.ts} +3 -24
  31. package/index.d.ts +2624 -10909
  32. package/ng_i18n_closure_mode.d-C9d2CaSt.d.ts +832 -0
  33. package/package.json +3 -3
  34. package/primitives/di/index.d.ts +3 -2
  35. package/primitives/event-dispatch/index.d.ts +3 -3
  36. package/primitives/signals/index.d.ts +8 -4
  37. package/rxjs-interop/index.d.ts +10 -7
  38. package/schematics/bundles/{apply_import_manager-CeNv8GIG.js → apply_import_manager-DnMqg1pY.js} +6 -6
  39. package/schematics/bundles/{compiler_host-DwM3ugW3.js → change_tracker-UMPkv-eH.js} +3 -121
  40. package/schematics/bundles/checker-BFBQyesT.js +17719 -0
  41. package/schematics/bundles/cleanup-unused-imports.js +25 -19
  42. package/schematics/bundles/{checker-k591b6WQ.js → compiler-BQ7R7w2v.js} +1325 -18286
  43. package/schematics/bundles/compiler_host-CAfDJO3W.js +129 -0
  44. package/schematics/bundles/control-flow-migration.js +28 -40
  45. package/schematics/bundles/document-core.js +96 -0
  46. package/schematics/bundles/imports-CIX-JgAN.js +1 -1
  47. package/schematics/bundles/{index-B4OAlHh8.js → index-Cv4Q415G.js} +641 -547
  48. package/schematics/bundles/{index-BhELUmYx.js → index-D8tMJPKa.js} +35 -34
  49. package/schematics/bundles/inject-flags.js +14 -13
  50. package/schematics/bundles/inject-migration.js +29 -10
  51. package/schematics/bundles/leading_space-D9nQ8UQC.js +1 -1
  52. package/schematics/bundles/{migrate_ts_type_references-Be0TNYen.js → migrate_ts_type_references-Cq_ZBuT4.js} +21 -20
  53. package/schematics/bundles/ng_decorators-DznZ5jMl.js +1 -1
  54. package/schematics/bundles/nodes-B16H9JUd.js +1 -1
  55. package/schematics/bundles/output-migration.js +88 -25
  56. package/schematics/bundles/{run_in_devkit-CkvEksWP.js → project_paths-ql6qcf_c.js} +254 -243
  57. package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.js +1 -1
  58. package/schematics/bundles/property_name-BBwFuqMe.js +1 -1
  59. package/schematics/bundles/route-lazy-loading.js +7 -5
  60. package/schematics/bundles/self-closing-tags-migration.js +25 -19
  61. package/schematics/bundles/signal-input-migration.js +26 -20
  62. package/schematics/bundles/signal-queries-migration.js +51 -33
  63. package/schematics/bundles/signals.js +8 -7
  64. package/schematics/bundles/standalone-migration.js +11 -9
  65. package/schematics/bundles/symbol-VPWguRxr.js +1 -1
  66. package/schematics/bundles/test-bed-get.js +13 -12
  67. package/schematics/collection.json +0 -6
  68. package/schematics/migrations.json +11 -0
  69. package/signal.d-E0e5nW1p.d.ts +31 -0
  70. package/testing/index.d.ts +16 -28
  71. package/weak_ref.d-eGOEP9S1.d.ts +9 -0
  72. package/fesm2022/injector-BlLwZ2sr.mjs +0 -24
  73. package/fesm2022/injector-BlLwZ2sr.mjs.map +0 -1
  74. package/fesm2022/untracked-DkcXpNb_.mjs.map +0 -1
  75. package/navigation_types.d-DgDrF5rp.d.ts +0 -121
  76. package/schematics/ng-generate/control-flow-migration/schema.json +0 -20
@@ -1,18 +1,19 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v20.0.0-next.4
3
+ * @license Angular v20.0.0-next.6
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
7
7
  'use strict';
8
8
 
9
- var os = require('os');
10
- var ts = require('typescript');
11
- var checker = require('./checker-k591b6WQ.js');
12
- var index = require('./index-B4OAlHh8.js');
9
+ var index = require('./index-Cv4Q415G.js');
13
10
  var schematics = require('@angular-devkit/schematics');
14
11
  var core = require('@angular-devkit/core');
15
12
  var posixPath = require('node:path/posix');
13
+ var os = require('os');
14
+ var ts = require('typescript');
15
+ var checker = require('./checker-BFBQyesT.js');
16
+ require('./compiler-BQ7R7w2v.js');
16
17
  require('path');
17
18
  var project_tsconfig_paths = require('./project_tsconfig_paths-CDVxT6Ov.js');
18
19
 
@@ -33,8 +34,8 @@ function _interopNamespaceDefault(e) {
33
34
  return Object.freeze(n);
34
35
  }
35
36
 
36
- var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
37
37
  var posixPath__namespace = /*#__PURE__*/_interopNamespaceDefault(posixPath);
38
+ var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
38
39
 
39
40
  /// <reference types="node" />
40
41
  class NgtscCompilerHost {
@@ -260,235 +261,6 @@ function getExtendedConfigPathWorker(configFile, extendsValue, host, fs) {
260
261
  return null;
261
262
  }
262
263
 
263
- /**
264
- * By default, Tsurge will always create an Angular compiler program
265
- * for projects analyzed and migrated. This works perfectly fine in
266
- * third-party where Tsurge migrations run in Angular CLI projects.
267
- *
268
- * In first party, when running against full Google3, creating an Angular
269
- * program for e.g. plain `ts_library` targets is overly expensive and
270
- * can result in out of memory issues for large TS targets. In 1P we can
271
- * reliably distinguish between TS and Angular targets via the `angularCompilerOptions`.
272
- */
273
- function google3UsePlainTsProgramIfNoKnownAngularOption() {
274
- return process.env['GOOGLE3_TSURGE'] === '1';
275
- }
276
-
277
- /** Options that are good defaults for Tsurge migrations. */
278
- const defaultMigrationTsOptions = {
279
- // Avoid checking libraries to speed up migrations.
280
- skipLibCheck: true,
281
- skipDefaultLibCheck: true,
282
- noEmit: true,
283
- // Does not apply to g3 and externally is enforced when the app is built by the compiler.
284
- disableTypeScriptVersionCheck: true,
285
- };
286
- /**
287
- * Creates an instance of a TypeScript program for the given project.
288
- */
289
- function createPlainTsProgram(tsHost, tsconfig, optionOverrides) {
290
- const program = ts.createProgram({
291
- rootNames: tsconfig.rootNames,
292
- options: {
293
- ...tsconfig.options,
294
- ...defaultMigrationTsOptions,
295
- ...optionOverrides,
296
- },
297
- });
298
- return {
299
- ngCompiler: null,
300
- program,
301
- userOptions: tsconfig.options,
302
- programAbsoluteRootFileNames: tsconfig.rootNames,
303
- host: tsHost,
304
- };
305
- }
306
-
307
- /**
308
- * Parses the configuration of the given TypeScript project and creates
309
- * an instance of the Angular compiler for the project.
310
- */
311
- function createNgtscProgram(tsHost, tsconfig, optionOverrides) {
312
- const ngtscProgram = new index.NgtscProgram(tsconfig.rootNames, {
313
- ...tsconfig.options,
314
- ...defaultMigrationTsOptions,
315
- ...optionOverrides,
316
- }, tsHost);
317
- // Expose an easy way to debug-print ng semantic diagnostics.
318
- if (process.env['DEBUG_NG_SEMANTIC_DIAGNOSTICS'] === '1') {
319
- console.error(ts.formatDiagnosticsWithColorAndContext(ngtscProgram.getNgSemanticDiagnostics(), tsHost));
320
- }
321
- return {
322
- ngCompiler: ngtscProgram.compiler,
323
- program: ngtscProgram.getTsProgram(),
324
- userOptions: tsconfig.options,
325
- programAbsoluteRootFileNames: tsconfig.rootNames,
326
- host: tsHost,
327
- };
328
- }
329
-
330
- /** Code of the error raised by TypeScript when a tsconfig doesn't match any files. */
331
- const NO_INPUTS_ERROR_CODE = 18003;
332
- /** Parses the given tsconfig file, supporting Angular compiler options. */
333
- function parseTsconfigOrDie(absoluteTsconfigPath, fs) {
334
- const tsconfig = readConfiguration(absoluteTsconfigPath, {}, fs);
335
- // Skip the "No inputs found..." error since we don't want to interrupt the migration if a
336
- // tsconfig doesn't match a file. This will result in an empty `Program` which is still valid.
337
- const errors = tsconfig.errors.filter((diag) => diag.code !== NO_INPUTS_ERROR_CODE);
338
- if (errors.length) {
339
- throw new Error(`Tsconfig could not be parsed or is invalid:\n\n` + `${errors.map((e) => e.messageText)}`);
340
- }
341
- return tsconfig;
342
- }
343
-
344
- /** Creates the base program info for the given tsconfig path. */
345
- function createBaseProgramInfo(absoluteTsconfigPath, fs, optionOverrides = {}) {
346
- if (fs === undefined) {
347
- fs = new checker.NodeJSFileSystem();
348
- checker.setFileSystem(fs);
349
- }
350
- const tsconfig = parseTsconfigOrDie(absoluteTsconfigPath, fs);
351
- const tsHost = new NgtscCompilerHost(fs, tsconfig.options);
352
- // When enabled, use a plain TS program if we are sure it's not
353
- // an Angular project based on the `tsconfig.json`.
354
- if (google3UsePlainTsProgramIfNoKnownAngularOption() &&
355
- tsconfig.options['_useHostForImportGeneration'] === undefined) {
356
- return createPlainTsProgram(tsHost, tsconfig, optionOverrides);
357
- }
358
- return createNgtscProgram(tsHost, tsconfig, optionOverrides);
359
- }
360
-
361
- /**
362
- * @private
363
- *
364
- * Base class for the possible Tsurge migration variants.
365
- *
366
- * For example, this class exposes methods to conveniently create
367
- * TypeScript programs, while also allowing migration authors to override.
368
- */
369
- class TsurgeBaseMigration {
370
- /**
371
- * Advanced Tsurge users can override this method, but most of the time,
372
- * overriding {@link prepareProgram} is more desirable.
373
- *
374
- * By default:
375
- * - In 3P: Ngtsc programs are being created.
376
- * - In 1P: Ngtsc or TS programs are created based on the Blaze target.
377
- */
378
- createProgram(tsconfigAbsPath, fs, optionOverrides) {
379
- return createBaseProgramInfo(tsconfigAbsPath, fs, optionOverrides);
380
- }
381
- // Optional function to prepare the base `ProgramInfo` even further,
382
- // for the analyze and migrate phases. E.g. determining source files.
383
- prepareProgram(info) {
384
- const fullProgramSourceFiles = [...info.program.getSourceFiles()];
385
- const sourceFiles = fullProgramSourceFiles.filter((f) => !f.isDeclarationFile &&
386
- // Note `isShim` will work for the initial program, but for TCB programs, the shims are no longer annotated.
387
- !checker.isShim(f) &&
388
- !f.fileName.endsWith('.ngtypecheck.ts'));
389
- // Sort it by length in reverse order (longest first). This speeds up lookups,
390
- // since there's no need to keep going through the array once a match is found.
391
- const sortedRootDirs = checker.getRootDirs(info.host, info.userOptions).sort((a, b) => b.length - a.length);
392
- // TODO: Consider also following TS's logic here, finding the common source root.
393
- // See: Program#getCommonSourceDirectory.
394
- const primaryRoot = checker.absoluteFrom(info.userOptions.rootDir ?? sortedRootDirs.at(-1) ?? info.program.getCurrentDirectory());
395
- return {
396
- ...info,
397
- sourceFiles,
398
- fullProgramSourceFiles,
399
- sortedRootDirs,
400
- projectRoot: primaryRoot,
401
- };
402
- }
403
- }
404
-
405
- /**
406
- * A simpler variant of a {@link TsurgeComplexMigration} that does not
407
- * fan-out into multiple workers per compilation unit to compute
408
- * the final migration replacements.
409
- *
410
- * This is faster and less resource intensive as workers and TS programs
411
- * are only ever created once.
412
- *
413
- * This is commonly the case when migrations are refactored to eagerly
414
- * compute replacements in the analyze stage, and then leverage the
415
- * global unit data to filter replacements that turned out to be "invalid".
416
- */
417
- class TsurgeFunnelMigration extends TsurgeBaseMigration {
418
- }
419
- /**
420
- * Complex variant of a `Tsurge` migration.
421
- *
422
- * For example, every analyze worker may contribute to a list of TS
423
- * references that are later combined. The migrate phase can then compute actual
424
- * file updates for all individual compilation units, leveraging the global metadata
425
- * to e.g. see if there are any references from other compilation units that may be
426
- * problematic and prevent migration of a given file.
427
- */
428
- class TsurgeComplexMigration extends TsurgeBaseMigration {
429
- }
430
-
431
- /** A text replacement for the given file. */
432
- class Replacement {
433
- projectFile;
434
- update;
435
- constructor(projectFile, update) {
436
- this.projectFile = projectFile;
437
- this.update = update;
438
- }
439
- }
440
- /** An isolated text update that may be applied to a file. */
441
- class TextUpdate {
442
- data;
443
- constructor(data) {
444
- this.data = data;
445
- }
446
- }
447
-
448
- /** Confirms that the given data `T` is serializable. */
449
- function confirmAsSerializable(data) {
450
- return data;
451
- }
452
-
453
- /**
454
- * Gets a project file instance for the given file.
455
- *
456
- * Use this helper for dealing with project paths throughout your
457
- * migration. The return type is serializable.
458
- *
459
- * See {@link ProjectFile}.
460
- */
461
- function projectFile(file, { sortedRootDirs, projectRoot }) {
462
- const fs = checker.getFileSystem();
463
- const filePath = fs.resolve(typeof file === 'string' ? file : file.fileName);
464
- // Sorted root directories are sorted longest to shortest. First match
465
- // is the appropriate root directory for ID computation.
466
- for (const rootDir of sortedRootDirs) {
467
- if (!isWithinBasePath(fs, rootDir, filePath)) {
468
- continue;
469
- }
470
- return {
471
- id: fs.relative(rootDir, filePath),
472
- rootRelativePath: fs.relative(projectRoot, filePath),
473
- };
474
- }
475
- // E.g. project directory may be `src/`, but files may be looked up
476
- // from `node_modules/`. This is fine, but in those cases, no root
477
- // directory matches.
478
- const rootRelativePath = fs.relative(projectRoot, filePath);
479
- return {
480
- id: rootRelativePath,
481
- rootRelativePath: rootRelativePath,
482
- };
483
- }
484
- /**
485
- * Whether `path` is a descendant of the `base`?
486
- * E.g. `a/b/c` is within `a/b` but not within `a/x`.
487
- */
488
- function isWithinBasePath(fs, base, path) {
489
- return checker.isLocalRelativePath(fs.relative(base, path));
490
- }
491
-
492
264
  /**
493
265
  * Angular compiler file system implementation that leverages an
494
266
  * CLI schematic virtual file tree.
@@ -670,6 +442,174 @@ async function synchronouslyCombineUnitData(migration, unitDatas) {
670
442
  return combined;
671
443
  }
672
444
 
445
+ /**
446
+ * By default, Tsurge will always create an Angular compiler program
447
+ * for projects analyzed and migrated. This works perfectly fine in
448
+ * third-party where Tsurge migrations run in Angular CLI projects.
449
+ *
450
+ * In first party, when running against full Google3, creating an Angular
451
+ * program for e.g. plain `ts_library` targets is overly expensive and
452
+ * can result in out of memory issues for large TS targets. In 1P we can
453
+ * reliably distinguish between TS and Angular targets via the `angularCompilerOptions`.
454
+ */
455
+ function google3UsePlainTsProgramIfNoKnownAngularOption() {
456
+ return process.env['GOOGLE3_TSURGE'] === '1';
457
+ }
458
+
459
+ /** Options that are good defaults for Tsurge migrations. */
460
+ const defaultMigrationTsOptions = {
461
+ // Avoid checking libraries to speed up migrations.
462
+ skipLibCheck: true,
463
+ skipDefaultLibCheck: true,
464
+ noEmit: true,
465
+ // Does not apply to g3 and externally is enforced when the app is built by the compiler.
466
+ disableTypeScriptVersionCheck: true,
467
+ };
468
+ /**
469
+ * Creates an instance of a TypeScript program for the given project.
470
+ */
471
+ function createPlainTsProgram(tsHost, tsconfig, optionOverrides) {
472
+ const program = ts.createProgram({
473
+ rootNames: tsconfig.rootNames,
474
+ options: {
475
+ ...tsconfig.options,
476
+ ...defaultMigrationTsOptions,
477
+ ...optionOverrides,
478
+ },
479
+ });
480
+ return {
481
+ ngCompiler: null,
482
+ program,
483
+ userOptions: tsconfig.options,
484
+ programAbsoluteRootFileNames: tsconfig.rootNames,
485
+ host: tsHost,
486
+ };
487
+ }
488
+
489
+ /**
490
+ * Parses the configuration of the given TypeScript project and creates
491
+ * an instance of the Angular compiler for the project.
492
+ */
493
+ function createNgtscProgram(tsHost, tsconfig, optionOverrides) {
494
+ const ngtscProgram = new index.NgtscProgram(tsconfig.rootNames, {
495
+ ...tsconfig.options,
496
+ ...defaultMigrationTsOptions,
497
+ ...optionOverrides,
498
+ }, tsHost);
499
+ // Expose an easy way to debug-print ng semantic diagnostics.
500
+ if (process.env['DEBUG_NG_SEMANTIC_DIAGNOSTICS'] === '1') {
501
+ console.error(ts.formatDiagnosticsWithColorAndContext(ngtscProgram.getNgSemanticDiagnostics(), tsHost));
502
+ }
503
+ return {
504
+ ngCompiler: ngtscProgram.compiler,
505
+ program: ngtscProgram.getTsProgram(),
506
+ userOptions: tsconfig.options,
507
+ programAbsoluteRootFileNames: tsconfig.rootNames,
508
+ host: tsHost,
509
+ };
510
+ }
511
+
512
+ /** Code of the error raised by TypeScript when a tsconfig doesn't match any files. */
513
+ const NO_INPUTS_ERROR_CODE = 18003;
514
+ /** Parses the given tsconfig file, supporting Angular compiler options. */
515
+ function parseTsconfigOrDie(absoluteTsconfigPath, fs) {
516
+ const tsconfig = readConfiguration(absoluteTsconfigPath, {}, fs);
517
+ // Skip the "No inputs found..." error since we don't want to interrupt the migration if a
518
+ // tsconfig doesn't match a file. This will result in an empty `Program` which is still valid.
519
+ const errors = tsconfig.errors.filter((diag) => diag.code !== NO_INPUTS_ERROR_CODE);
520
+ if (errors.length) {
521
+ throw new Error(`Tsconfig could not be parsed or is invalid:\n\n` + `${errors.map((e) => e.messageText)}`);
522
+ }
523
+ return tsconfig;
524
+ }
525
+
526
+ /** Creates the base program info for the given tsconfig path. */
527
+ function createBaseProgramInfo(absoluteTsconfigPath, fs, optionOverrides = {}) {
528
+ if (fs === undefined) {
529
+ fs = new checker.NodeJSFileSystem();
530
+ checker.setFileSystem(fs);
531
+ }
532
+ const tsconfig = parseTsconfigOrDie(absoluteTsconfigPath, fs);
533
+ const tsHost = new NgtscCompilerHost(fs, tsconfig.options);
534
+ // When enabled, use a plain TS program if we are sure it's not
535
+ // an Angular project based on the `tsconfig.json`.
536
+ if (google3UsePlainTsProgramIfNoKnownAngularOption() &&
537
+ tsconfig.options['_useHostForImportGeneration'] === undefined) {
538
+ return createPlainTsProgram(tsHost, tsconfig, optionOverrides);
539
+ }
540
+ return createNgtscProgram(tsHost, tsconfig, optionOverrides);
541
+ }
542
+
543
+ /**
544
+ * @private
545
+ *
546
+ * Base class for the possible Tsurge migration variants.
547
+ *
548
+ * For example, this class exposes methods to conveniently create
549
+ * TypeScript programs, while also allowing migration authors to override.
550
+ */
551
+ class TsurgeBaseMigration {
552
+ /**
553
+ * Advanced Tsurge users can override this method, but most of the time,
554
+ * overriding {@link prepareProgram} is more desirable.
555
+ *
556
+ * By default:
557
+ * - In 3P: Ngtsc programs are being created.
558
+ * - In 1P: Ngtsc or TS programs are created based on the Blaze target.
559
+ */
560
+ createProgram(tsconfigAbsPath, fs, optionOverrides) {
561
+ return createBaseProgramInfo(tsconfigAbsPath, fs, optionOverrides);
562
+ }
563
+ // Optional function to prepare the base `ProgramInfo` even further,
564
+ // for the analyze and migrate phases. E.g. determining source files.
565
+ prepareProgram(info) {
566
+ const fullProgramSourceFiles = [...info.program.getSourceFiles()];
567
+ const sourceFiles = fullProgramSourceFiles.filter((f) => !f.isDeclarationFile &&
568
+ // Note `isShim` will work for the initial program, but for TCB programs, the shims are no longer annotated.
569
+ !checker.isShim(f) &&
570
+ !f.fileName.endsWith('.ngtypecheck.ts'));
571
+ // Sort it by length in reverse order (longest first). This speeds up lookups,
572
+ // since there's no need to keep going through the array once a match is found.
573
+ const sortedRootDirs = checker.getRootDirs(info.host, info.userOptions).sort((a, b) => b.length - a.length);
574
+ // TODO: Consider also following TS's logic here, finding the common source root.
575
+ // See: Program#getCommonSourceDirectory.
576
+ const primaryRoot = checker.absoluteFrom(info.userOptions.rootDir ?? sortedRootDirs.at(-1) ?? info.program.getCurrentDirectory());
577
+ return {
578
+ ...info,
579
+ sourceFiles,
580
+ fullProgramSourceFiles,
581
+ sortedRootDirs,
582
+ projectRoot: primaryRoot,
583
+ };
584
+ }
585
+ }
586
+
587
+ /**
588
+ * A simpler variant of a {@link TsurgeComplexMigration} that does not
589
+ * fan-out into multiple workers per compilation unit to compute
590
+ * the final migration replacements.
591
+ *
592
+ * This is faster and less resource intensive as workers and TS programs
593
+ * are only ever created once.
594
+ *
595
+ * This is commonly the case when migrations are refactored to eagerly
596
+ * compute replacements in the analyze stage, and then leverage the
597
+ * global unit data to filter replacements that turned out to be "invalid".
598
+ */
599
+ class TsurgeFunnelMigration extends TsurgeBaseMigration {
600
+ }
601
+ /**
602
+ * Complex variant of a `Tsurge` migration.
603
+ *
604
+ * For example, every analyze worker may contribute to a list of TS
605
+ * references that are later combined. The migrate phase can then compute actual
606
+ * file updates for all individual compilation units, leveraging the global metadata
607
+ * to e.g. see if there are any references from other compilation units that may be
608
+ * problematic and prevent migration of a given file.
609
+ */
610
+ class TsurgeComplexMigration extends TsurgeBaseMigration {
611
+ }
612
+
673
613
  /*!
674
614
  * @license
675
615
  * Copyright Google LLC All Rights Reserved.
@@ -677,24 +617,30 @@ async function synchronouslyCombineUnitData(migration, unitDatas) {
677
617
  * Use of this source code is governed by an MIT-style license that can be
678
618
  * found in the LICENSE file at https://angular.dev/license
679
619
  */
620
+ exports.MigrationStage = void 0;
621
+ (function (MigrationStage) {
622
+ /** The migration is analyzing an entrypoint */
623
+ MigrationStage[MigrationStage["Analysis"] = 0] = "Analysis";
624
+ /** The migration is about to migrate an entrypoint */
625
+ MigrationStage[MigrationStage["Migrate"] = 1] = "Migrate";
626
+ })(exports.MigrationStage || (exports.MigrationStage = {}));
680
627
  /** Runs a Tsurge within an Angular Devkit context. */
681
628
  async function runMigrationInDevkit(config) {
682
629
  const { buildPaths, testPaths } = await project_tsconfig_paths.getProjectTsConfigPaths(config.tree);
683
630
  if (!buildPaths.length && !testPaths.length) {
684
631
  throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run the migration.');
685
632
  }
633
+ const tsconfigPaths = [...buildPaths, ...testPaths];
686
634
  const fs = new DevkitMigrationFilesystem(config.tree);
687
635
  checker.setFileSystem(fs);
688
636
  const migration = config.getMigration(fs);
689
637
  const unitResults = [];
690
- const programInfos = [...buildPaths, ...testPaths].map((tsconfigPath) => {
691
- config.beforeProgramCreation?.(tsconfigPath);
638
+ const isFunnelMigration = migration instanceof TsurgeFunnelMigration;
639
+ for (const tsconfigPath of tsconfigPaths) {
640
+ config.beforeProgramCreation?.(tsconfigPath, exports.MigrationStage.Analysis);
692
641
  const baseInfo = migration.createProgram(tsconfigPath, fs);
693
642
  const info = migration.prepareProgram(baseInfo);
694
- config.afterProgramCreation?.(info, fs);
695
- return { info, tsconfigPath };
696
- });
697
- for (const { info, tsconfigPath } of programInfos) {
643
+ config.afterProgramCreation?.(info, fs, exports.MigrationStage.Analysis);
698
644
  config.beforeUnitAnalysis?.(tsconfigPath);
699
645
  unitResults.push(await migration.analyze(info));
700
646
  }
@@ -706,12 +652,16 @@ async function runMigrationInDevkit(config) {
706
652
  }
707
653
  const globalMeta = await migration.globalMeta(combined);
708
654
  let replacements;
709
- if (migration instanceof TsurgeFunnelMigration) {
655
+ if (isFunnelMigration) {
710
656
  replacements = (await migration.migrate(globalMeta)).replacements;
711
657
  }
712
658
  else {
713
659
  replacements = [];
714
- for (const { info } of programInfos) {
660
+ for (const tsconfigPath of tsconfigPaths) {
661
+ config.beforeProgramCreation?.(tsconfigPath, exports.MigrationStage.Migrate);
662
+ const baseInfo = migration.createProgram(tsconfigPath, fs);
663
+ const info = migration.prepareProgram(baseInfo);
664
+ config.afterProgramCreation?.(info, fs, exports.MigrationStage.Migrate);
715
665
  const result = await migration.migrate(globalMeta, info);
716
666
  replacements.push(...result.replacements);
717
667
  }
@@ -735,6 +685,67 @@ async function runMigrationInDevkit(config) {
735
685
  config.whenDone?.(await migration.stats(globalMeta));
736
686
  }
737
687
 
688
+ /** A text replacement for the given file. */
689
+ class Replacement {
690
+ projectFile;
691
+ update;
692
+ constructor(projectFile, update) {
693
+ this.projectFile = projectFile;
694
+ this.update = update;
695
+ }
696
+ }
697
+ /** An isolated text update that may be applied to a file. */
698
+ class TextUpdate {
699
+ data;
700
+ constructor(data) {
701
+ this.data = data;
702
+ }
703
+ }
704
+
705
+ /** Confirms that the given data `T` is serializable. */
706
+ function confirmAsSerializable(data) {
707
+ return data;
708
+ }
709
+
710
+ /**
711
+ * Gets a project file instance for the given file.
712
+ *
713
+ * Use this helper for dealing with project paths throughout your
714
+ * migration. The return type is serializable.
715
+ *
716
+ * See {@link ProjectFile}.
717
+ */
718
+ function projectFile(file, { sortedRootDirs, projectRoot }) {
719
+ const fs = checker.getFileSystem();
720
+ const filePath = fs.resolve(typeof file === 'string' ? file : file.fileName);
721
+ // Sorted root directories are sorted longest to shortest. First match
722
+ // is the appropriate root directory for ID computation.
723
+ for (const rootDir of sortedRootDirs) {
724
+ if (!isWithinBasePath(fs, rootDir, filePath)) {
725
+ continue;
726
+ }
727
+ return {
728
+ id: fs.relative(rootDir, filePath),
729
+ rootRelativePath: fs.relative(projectRoot, filePath),
730
+ };
731
+ }
732
+ // E.g. project directory may be `src/`, but files may be looked up
733
+ // from `node_modules/`. This is fine, but in those cases, no root
734
+ // directory matches.
735
+ const rootRelativePath = fs.relative(projectRoot, filePath);
736
+ return {
737
+ id: rootRelativePath,
738
+ rootRelativePath: rootRelativePath,
739
+ };
740
+ }
741
+ /**
742
+ * Whether `path` is a descendant of the `base`?
743
+ * E.g. `a/b/c` is within `a/b` but not within `a/x`.
744
+ */
745
+ function isWithinBasePath(fs, base, path) {
746
+ return checker.isLocalRelativePath(fs.relative(base, path));
747
+ }
748
+
738
749
  exports.Replacement = Replacement;
739
750
  exports.TextUpdate = TextUpdate;
740
751
  exports.TsurgeComplexMigration = TsurgeComplexMigration;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v20.0.0-next.4
3
+ * @license Angular v20.0.0-next.6
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v20.0.0-next.4
3
+ * @license Angular v20.0.0-next.6
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v20.0.0-next.4
3
+ * @license Angular v20.0.0-next.6
4
4
  * (c) 2010-2025 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -9,11 +9,13 @@
9
9
  var schematics = require('@angular-devkit/schematics');
10
10
  var fs = require('fs');
11
11
  var p = require('path');
12
- var compiler_host = require('./compiler_host-DwM3ugW3.js');
12
+ var change_tracker = require('./change_tracker-UMPkv-eH.js');
13
13
  var project_tsconfig_paths = require('./project_tsconfig_paths-CDVxT6Ov.js');
14
+ var compiler_host = require('./compiler_host-CAfDJO3W.js');
14
15
  var ts = require('typescript');
15
- var checker = require('./checker-k591b6WQ.js');
16
+ var checker = require('./checker-BFBQyesT.js');
16
17
  var property_name = require('./property_name-BBwFuqMe.js');
18
+ require('./compiler-BQ7R7w2v.js');
17
19
  require('os');
18
20
  require('@angular-devkit/core');
19
21
  require('module');
@@ -156,7 +158,7 @@ function migrateFileToLazyRoutes(sourceFile, program) {
156
158
  const typeChecker = program.getTypeChecker();
157
159
  const reflector = new checker.TypeScriptReflectionHost(typeChecker);
158
160
  const printer = ts.createPrinter();
159
- const tracker = new compiler_host.ChangeTracker(printer);
161
+ const tracker = new change_tracker.ChangeTracker(printer);
160
162
  const routeArraysToMigrate = findRoutesArrayToMigrate(sourceFile, typeChecker);
161
163
  if (routeArraysToMigrate.length === 0) {
162
164
  return { pendingChanges: [], skippedRoutes: [], migratedRoutes: [] };
@@ -347,7 +349,7 @@ function migrate(options) {
347
349
  const basePath = process.cwd();
348
350
  // TS and Schematic use paths in POSIX format even on Windows. This is needed as otherwise
349
351
  // string matching such as `sourceFile.fileName.startsWith(pathToMigrate)` might not work.
350
- const pathToMigrate = compiler_host.normalizePath(p.join(basePath, options.path));
352
+ const pathToMigrate = change_tracker.normalizePath(p.join(basePath, options.path));
351
353
  if (!buildPaths.length) {
352
354
  throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run the route lazy loading migration.');
353
355
  }