@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.
- package/fesm2022/_attribute-chunk.mjs +12 -0
- package/fesm2022/_attribute-chunk.mjs.map +1 -0
- package/fesm2022/_debug_node-chunk.mjs +18469 -0
- package/fesm2022/_debug_node-chunk.mjs.map +1 -0
- package/fesm2022/_effect-chunk.mjs +423 -0
- package/fesm2022/_effect-chunk.mjs.map +1 -0
- package/fesm2022/_effect-chunk2.mjs +2951 -0
- package/fesm2022/_effect-chunk2.mjs.map +1 -0
- package/fesm2022/_not_found-chunk.mjs +39 -0
- package/fesm2022/_not_found-chunk.mjs.map +1 -0
- package/fesm2022/_resource-chunk.mjs +378 -0
- package/fesm2022/_resource-chunk.mjs.map +1 -0
- package/fesm2022/_untracked-chunk.mjs +96 -0
- package/fesm2022/_untracked-chunk.mjs.map +1 -0
- package/fesm2022/_weak_ref-chunk.mjs +10 -0
- package/fesm2022/_weak_ref-chunk.mjs.map +1 -0
- package/fesm2022/core.mjs +2499 -4185
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives-di.mjs +23 -0
- package/fesm2022/primitives-di.mjs.map +1 -0
- package/fesm2022/primitives-event-dispatch.mjs +788 -0
- package/fesm2022/primitives-event-dispatch.mjs.map +1 -0
- package/fesm2022/primitives-signals.mjs +187 -0
- package/fesm2022/primitives-signals.mjs.map +1 -0
- package/fesm2022/rxjs-interop.mjs +210 -308
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/testing.mjs +2309 -3170
- package/fesm2022/testing.mjs.map +1 -1
- package/package.json +18 -12
- package/resources/best-practices.md +56 -0
- package/schematics/bundles/add-bootstrap-context-to-server-main.cjs +117 -0
- package/schematics/bundles/application-config-core.cjs +84 -0
- package/schematics/bundles/{apply_import_manager-DR9xXCle.cjs → apply_import_manager-1Zs_gpB6.cjs} +4 -5
- package/schematics/bundles/bootstrap-options-migration.cjs +598 -0
- package/schematics/bundles/cleanup-unused-imports.cjs +9 -13
- package/schematics/bundles/common-to-standalone-migration.cjs +381 -0
- package/schematics/bundles/{compiler_host-BXBP7CE2.cjs → compiler_host-DBwYMlTo.cjs} +10 -11
- package/schematics/bundles/control-flow-migration.cjs +122 -119
- package/schematics/bundles/{imports-CIX-JgAN.cjs → imports-DP72APSx.cjs} +6 -1
- package/schematics/bundles/{index-CfTQUOiz.cjs → index-B7I9sIUx.cjs} +36 -39
- package/schematics/bundles/inject-migration.cjs +148 -70
- package/schematics/bundles/leading_space-D9nQ8UQC.cjs +1 -1
- package/schematics/bundles/{migrate_ts_type_references-6NtAj-Wk.cjs → migrate_ts_type_references-UGIUl7En.cjs} +500 -24
- package/schematics/bundles/ng_component_template-Dsuq1Lw7.cjs +185 -0
- package/schematics/bundles/{ng_decorators-B5HCqr20.cjs → ng_decorators-DSFlWYQY.cjs} +2 -2
- package/schematics/bundles/ngclass-to-class-migration.cjs +542 -0
- package/schematics/bundles/ngstyle-to-style-migration.cjs +487 -0
- package/schematics/bundles/nodes-B16H9JUd.cjs +1 -1
- package/schematics/bundles/output-migration.cjs +16 -19
- package/schematics/bundles/parse_html-8VLCL37B.cjs +132 -0
- package/schematics/bundles/{project_paths-DcaODbky.cjs → project_paths-DvD50ouC.cjs} +14 -247
- package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.cjs +90 -0
- package/schematics/bundles/property_name-BBwFuqMe.cjs +1 -1
- package/schematics/bundles/route-lazy-loading.cjs +54 -26
- package/schematics/bundles/router-current-navigation.cjs +7 -18
- package/schematics/bundles/router-last-successful-navigation.cjs +7 -18
- package/schematics/bundles/router-testing-module-migration.cjs +502 -0
- package/schematics/bundles/self-closing-tags-migration.cjs +17 -216
- package/schematics/bundles/signal-input-migration.cjs +93 -29
- package/schematics/bundles/signal-queries-migration.cjs +22 -25
- package/schematics/bundles/signals.cjs +10 -13
- package/schematics/bundles/standalone-migration.cjs +135 -102
- package/schematics/bundles/{symbol-VPWguRxr.cjs → symbol-BObKoqes.cjs} +3 -2
- package/schematics/collection.json +23 -0
- package/schematics/migrations/common-to-standalone-migration/schema.json +14 -0
- package/schematics/migrations/ngclass-to-class-migration/schema.json +20 -0
- package/schematics/migrations/ngstyle-to-style-migration/schema.json +20 -0
- package/schematics/migrations/router-testing-module-migration/schema.json +14 -0
- package/schematics/migrations.json +16 -2
- package/{api.d.d.ts → types/_api-chunk.d.ts} +9 -6
- package/{chrome_dev_tools_performance.d.d.ts → types/_chrome_dev_tools_performance-chunk.d.ts} +26 -31
- package/{discovery.d.d.ts → types/_discovery-chunk.d.ts} +135 -98
- package/{signal.d.d.ts → types/_effect-chunk.d.ts} +14 -5
- package/{event_dispatcher.d.d.ts → types/_event_dispatcher-chunk.d.ts} +2 -2
- package/{graph.d.d.ts → types/_formatter-chunk.d.ts} +40 -7
- package/{weak_ref.d.d.ts → types/_weak_ref-chunk.d.ts} +2 -2
- package/{index.d.ts → types/core.d.ts} +233 -305
- package/{primitives/di/index.d.ts → types/primitives-di.d.ts} +2 -2
- package/{primitives/event-dispatch/index.d.ts → types/primitives-event-dispatch.d.ts} +4 -4
- package/{primitives/signals/index.d.ts → types/primitives-signals.d.ts} +7 -8
- package/{rxjs-interop/index.d.ts → types/rxjs-interop.d.ts} +8 -6
- package/{testing/index.d.ts → types/testing.d.ts} +7 -7
- package/fesm2022/attribute.mjs +0 -24
- package/fesm2022/attribute.mjs.map +0 -1
- package/fesm2022/debug_node.mjs +0 -31833
- package/fesm2022/debug_node.mjs.map +0 -1
- package/fesm2022/not_found.mjs +0 -56
- package/fesm2022/not_found.mjs.map +0 -1
- package/fesm2022/primitives/di.mjs +0 -23
- package/fesm2022/primitives/di.mjs.map +0 -1
- package/fesm2022/primitives/event-dispatch.mjs +0 -1622
- package/fesm2022/primitives/event-dispatch.mjs.map +0 -1
- package/fesm2022/primitives/signals.mjs +0 -89
- package/fesm2022/primitives/signals.mjs.map +0 -1
- package/fesm2022/resource.mjs +0 -633
- package/fesm2022/resource.mjs.map +0 -1
- package/fesm2022/root_effect_scheduler.mjs +0 -4007
- package/fesm2022/root_effect_scheduler.mjs.map +0 -1
- package/fesm2022/signal.mjs +0 -560
- package/fesm2022/signal.mjs.map +0 -1
- package/fesm2022/untracked.mjs +0 -117
- package/fesm2022/untracked.mjs.map +0 -1
- package/fesm2022/weak_ref.mjs +0 -12
- package/fesm2022/weak_ref.mjs.map +0 -1
- package/schematics/bundles/index-esqfDjNB.cjs +0 -22074
- 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.
|
|
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('
|
|
13
|
+
require('@angular/compiler-cli/private/migrations');
|
|
14
14
|
require('typescript');
|
|
15
|
-
require('
|
|
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-
|
|
17
|
+
require('./project_paths-DvD50ouC.cjs');
|
|
18
|
+
require('@angular-devkit/core');
|
|
24
19
|
require('node:path/posix');
|
|
25
|
-
require('./
|
|
26
|
-
require('./
|
|
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-
|
|
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.
|
|
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
|
|
10
|
+
var compilerCli = require('@angular/compiler-cli');
|
|
11
11
|
var fs = require('fs');
|
|
12
|
-
var
|
|
12
|
+
var path = require('path');
|
|
13
13
|
var ts = require('typescript');
|
|
14
|
-
var compiler_host = require('./compiler_host-
|
|
15
|
-
var project_tsconfig_paths = require('./project_tsconfig_paths-
|
|
16
|
-
var ng_decorators = require('./ng_decorators-
|
|
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-
|
|
19
|
-
var imports = require('./imports-
|
|
20
|
-
require('
|
|
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 =
|
|
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
|
-
?
|
|
404
|
-
:
|
|
405
|
-
if (importLocation
|
|
406
|
-
|
|
407
|
-
|
|
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
|
-
|
|
475
|
-
//
|
|
476
|
-
if (ts.
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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
|
-
|
|
483
|
+
declarationsToCopy.push(el);
|
|
490
484
|
}
|
|
491
485
|
}
|
|
492
|
-
|
|
493
|
-
|
|
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
|
-
//
|
|
499
|
-
|
|
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.
|
|
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
|
-
|
|
525
|
-
if (ts.
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
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 ===
|
|
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 ===
|
|
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
|
-
|
|
646
|
-
|
|
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,
|
|
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,
|
|
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(
|
|
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(
|
|
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(
|
|
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.
|
|
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 (
|
|
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
|
+
}
|