@angular/core 20.0.0-next.1 → 20.0.0-next.3
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/core.mjs +770 -2144
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives/di.mjs +3 -2
- package/fesm2022/primitives/di.mjs.map +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +2 -589
- package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +44 -13
- package/fesm2022/primitives/signals.mjs.map +1 -1
- package/fesm2022/rxjs-interop.mjs +7 -39
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/testing.mjs +116 -143
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/weak_ref-DrMdAIDh.mjs +12 -0
- package/fesm2022/weak_ref-DrMdAIDh.mjs.map +1 -0
- package/index.d.ts +14366 -15214
- package/navigation_types.d-u4EOrrdZ.d.ts +121 -0
- package/package.json +2 -2
- package/primitives/di/index.d.ts +66 -59
- package/primitives/event-dispatch/index.d.ts +205 -309
- package/primitives/signals/index.d.ts +161 -195
- package/rxjs-interop/index.d.ts +71 -100
- package/schematics/bundles/{apply_import_manager-e2a7fe5b.js → apply_import_manager-BXQEjo09.js} +15 -19
- package/schematics/bundles/{checker-af521da6.js → checker-BHb19MHt.js} +3695 -1175
- package/schematics/bundles/cleanup-unused-imports.js +56 -89
- package/schematics/bundles/{compiler_host-5a29293c.js → compiler_host-Bk3repE2.js} +19 -23
- package/schematics/bundles/control-flow-migration.js +81 -38
- package/schematics/bundles/{imports-047fbbc8.js → imports-CIX-JgAN.js} +9 -14
- package/schematics/bundles/{index-1bef3025.js → index-BL9kAIe5.js} +62 -66
- package/schematics/bundles/{program-a449f9bf.js → index-I8VbxQcO.js} +1508 -3178
- package/schematics/bundles/inject-flags.js +147 -0
- package/schematics/bundles/inject-migration.js +121 -127
- package/schematics/bundles/{leading_space-f8944434.js → leading_space-D9nQ8UQC.js} +1 -1
- package/schematics/bundles/{migrate_ts_type_references-2a3e9e6b.js → migrate_ts_type_references-KlOTWeDl.js} +121 -126
- package/schematics/bundles/{ng_decorators-b0d8b324.js → ng_decorators-DznZ5jMl.js} +4 -8
- package/schematics/bundles/{nodes-7758dbf6.js → nodes-B16H9JUd.js} +2 -6
- package/schematics/bundles/output-migration.js +94 -128
- package/schematics/bundles/{project_tsconfig_paths-b558633b.js → project_tsconfig_paths-CDVxT6Ov.js} +1 -1
- package/schematics/bundles/{property_name-ac18447e.js → property_name-BBwFuqMe.js} +3 -7
- package/schematics/bundles/route-lazy-loading.js +35 -41
- package/schematics/bundles/{project_paths-17dc204d.js → run_in_devkit-C0JPtK2u.js} +283 -216
- package/schematics/bundles/self-closing-tags-migration.js +55 -91
- package/schematics/bundles/signal-input-migration.js +121 -156
- package/schematics/bundles/signal-queries-migration.js +119 -154
- package/schematics/bundles/signals.js +12 -14
- package/schematics/bundles/standalone-migration.js +180 -200
- package/schematics/bundles/symbol-VPWguRxr.js +25 -0
- package/schematics/bundles/test-bed-get.js +98 -0
- package/schematics/migrations.json +8 -14
- package/testing/index.d.ts +289 -471
- package/weak_ref.d-ttyj86RV.d.ts +9 -0
- package/schematics/bundles/explicit-standalone-flag.js +0 -184
- package/schematics/bundles/index-ef1bffbb.js +0 -30
- package/schematics/bundles/pending-tasks.js +0 -103
- package/schematics/bundles/provide-initializer.js +0 -186
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v20.0.0-next.
|
|
3
|
+
* @license Angular v20.0.0-next.3
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
var core = require('@angular-devkit/core');
|
|
10
|
-
var posixPath = require('node:path/posix');
|
|
11
9
|
var os = require('os');
|
|
12
10
|
var ts = require('typescript');
|
|
13
|
-
var checker = require('./checker-
|
|
14
|
-
var
|
|
11
|
+
var checker = require('./checker-BHb19MHt.js');
|
|
12
|
+
var index = require('./index-I8VbxQcO.js');
|
|
13
|
+
var schematics = require('@angular-devkit/schematics');
|
|
14
|
+
var core = require('@angular-devkit/core');
|
|
15
|
+
var posixPath = require('node:path/posix');
|
|
15
16
|
require('path');
|
|
17
|
+
var project_tsconfig_paths = require('./project_tsconfig_paths-CDVxT6Ov.js');
|
|
16
18
|
|
|
17
|
-
function
|
|
18
|
-
|
|
19
|
-
function _interopNamespace(e) {
|
|
20
|
-
if (e && e.__esModule) return e;
|
|
19
|
+
function _interopNamespaceDefault(e) {
|
|
21
20
|
var n = Object.create(null);
|
|
22
21
|
if (e) {
|
|
23
22
|
Object.keys(e).forEach(function (k) {
|
|
@@ -30,13 +29,12 @@ function _interopNamespace(e) {
|
|
|
30
29
|
}
|
|
31
30
|
});
|
|
32
31
|
}
|
|
33
|
-
n
|
|
32
|
+
n.default = e;
|
|
34
33
|
return Object.freeze(n);
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
var
|
|
38
|
-
var
|
|
39
|
-
var ts__default = /*#__PURE__*/_interopDefaultLegacy(ts);
|
|
36
|
+
var os__namespace = /*#__PURE__*/_interopNamespaceDefault(os);
|
|
37
|
+
var posixPath__namespace = /*#__PURE__*/_interopNamespaceDefault(posixPath);
|
|
40
38
|
|
|
41
39
|
/// <reference types="node" />
|
|
42
40
|
class NgtscCompilerHost {
|
|
@@ -49,11 +47,11 @@ class NgtscCompilerHost {
|
|
|
49
47
|
getSourceFile(fileName, languageVersion) {
|
|
50
48
|
const text = this.readFile(fileName);
|
|
51
49
|
return text !== undefined
|
|
52
|
-
?
|
|
50
|
+
? ts.createSourceFile(fileName, text, languageVersion, true)
|
|
53
51
|
: undefined;
|
|
54
52
|
}
|
|
55
53
|
getDefaultLibFileName(options) {
|
|
56
|
-
return this.fs.join(this.getDefaultLibLocation(),
|
|
54
|
+
return this.fs.join(this.getDefaultLibLocation(), ts.getDefaultLibFileName(options));
|
|
57
55
|
}
|
|
58
56
|
getDefaultLibLocation() {
|
|
59
57
|
return this.fs.getDefaultLibLocation();
|
|
@@ -74,9 +72,9 @@ class NgtscCompilerHost {
|
|
|
74
72
|
}
|
|
75
73
|
getNewLine() {
|
|
76
74
|
switch (this.options.newLine) {
|
|
77
|
-
case
|
|
75
|
+
case ts.NewLineKind.CarriageReturnLineFeed:
|
|
78
76
|
return '\r\n';
|
|
79
|
-
case
|
|
77
|
+
case ts.NewLineKind.LineFeed:
|
|
80
78
|
return '\n';
|
|
81
79
|
default:
|
|
82
80
|
return os__namespace.EOL;
|
|
@@ -99,17 +97,23 @@ class NgtscCompilerHost {
|
|
|
99
97
|
}
|
|
100
98
|
|
|
101
99
|
// We use TypeScript's native `ts.matchFiles` utility for the virtual file systems
|
|
100
|
+
// and their TypeScript compiler host `readDirectory` implementation. TypeScript's
|
|
101
|
+
// function implements complex logic for matching files with respect to root
|
|
102
|
+
// directory, extensions, excludes, includes etc. The function is currently
|
|
103
|
+
// internal but we can use it as the API most likely will not change any time soon,
|
|
104
|
+
// nor does it seem like this is being made public any time soon.
|
|
105
|
+
// Related issue for tracking: https://github.com/microsoft/TypeScript/issues/13793.
|
|
102
106
|
/**
|
|
103
107
|
* Creates a {@link ts.CompilerHost#readDirectory} implementation function,
|
|
104
108
|
* that leverages the specified file system (that may be e.g. virtual).
|
|
105
109
|
*/
|
|
106
110
|
function createFileSystemTsReadDirectoryFn(fs) {
|
|
107
|
-
if (
|
|
111
|
+
if (ts.matchFiles === undefined) {
|
|
108
112
|
throw Error('Unable to read directory in configured file system. This means that ' +
|
|
109
113
|
'TypeScript changed its file matching internals.\n\nPlease consider downgrading your ' +
|
|
110
114
|
'TypeScript version, and report an issue in the Angular framework repository.');
|
|
111
115
|
}
|
|
112
|
-
const matchFilesFn =
|
|
116
|
+
const matchFilesFn = ts.matchFiles.bind(ts);
|
|
113
117
|
return (rootDir, extensions, excludes, includes, depth) => {
|
|
114
118
|
const directoryExists = (p) => {
|
|
115
119
|
const resolvedPath = fs.resolve(p);
|
|
@@ -148,7 +152,7 @@ function calcProjectFileAndBasePath(project, host = checker.getFileSystem()) {
|
|
|
148
152
|
function readConfiguration(project, existingOptions, host = checker.getFileSystem()) {
|
|
149
153
|
try {
|
|
150
154
|
const fs = checker.getFileSystem();
|
|
151
|
-
const readConfigFile = (configFile) =>
|
|
155
|
+
const readConfigFile = (configFile) => ts.readConfigFile(configFile, (file) => host.readFile(host.resolve(file)));
|
|
152
156
|
const readAngularCompilerOptions = (configFile, parentOptions = {}) => {
|
|
153
157
|
const { config, error } = readConfigFile(configFile);
|
|
154
158
|
if (error) {
|
|
@@ -185,7 +189,7 @@ function readConfiguration(project, existingOptions, host = checker.getFileSyste
|
|
|
185
189
|
errors: [error],
|
|
186
190
|
rootNames: [],
|
|
187
191
|
options: {},
|
|
188
|
-
emitFlags:
|
|
192
|
+
emitFlags: index.EmitFlags.Default,
|
|
189
193
|
};
|
|
190
194
|
}
|
|
191
195
|
const existingCompilerOptions = {
|
|
@@ -195,29 +199,29 @@ function readConfiguration(project, existingOptions, host = checker.getFileSyste
|
|
|
195
199
|
...existingOptions,
|
|
196
200
|
};
|
|
197
201
|
const parseConfigHost = createParseConfigHost(host, fs);
|
|
198
|
-
const { options, errors, fileNames: rootNames, projectReferences, } =
|
|
199
|
-
let emitFlags =
|
|
202
|
+
const { options, errors, fileNames: rootNames, projectReferences, } = ts.parseJsonConfigFileContent(config, parseConfigHost, basePath, existingCompilerOptions, configFileName);
|
|
203
|
+
let emitFlags = index.EmitFlags.Default;
|
|
200
204
|
if (!(options['skipMetadataEmit'] || options['flatModuleOutFile'])) {
|
|
201
|
-
emitFlags |=
|
|
205
|
+
emitFlags |= index.EmitFlags.Metadata;
|
|
202
206
|
}
|
|
203
207
|
if (options['skipTemplateCodegen']) {
|
|
204
|
-
emitFlags = emitFlags & ~
|
|
208
|
+
emitFlags = emitFlags & ~index.EmitFlags.Codegen;
|
|
205
209
|
}
|
|
206
210
|
return { project: projectFile, rootNames, projectReferences, options, errors, emitFlags };
|
|
207
211
|
}
|
|
208
212
|
catch (e) {
|
|
209
213
|
const errors = [
|
|
210
214
|
{
|
|
211
|
-
category:
|
|
215
|
+
category: ts.DiagnosticCategory.Error,
|
|
212
216
|
messageText: e.stack ?? e.message,
|
|
213
217
|
file: undefined,
|
|
214
218
|
start: undefined,
|
|
215
219
|
length: undefined,
|
|
216
220
|
source: 'angular',
|
|
217
|
-
code:
|
|
221
|
+
code: index.UNKNOWN_ERROR_CODE,
|
|
218
222
|
},
|
|
219
223
|
];
|
|
220
|
-
return { project: '', errors, rootNames: [], options: {}, emitFlags:
|
|
224
|
+
return { project: '', errors, rootNames: [], options: {}, emitFlags: index.EmitFlags.Default };
|
|
221
225
|
}
|
|
222
226
|
}
|
|
223
227
|
function createParseConfigHost(host, fs = checker.getFileSystem()) {
|
|
@@ -248,7 +252,7 @@ function getExtendedConfigPathWorker(configFile, extendsValue, host, fs) {
|
|
|
248
252
|
else {
|
|
249
253
|
const parseConfigHost = createParseConfigHost(host, fs);
|
|
250
254
|
// Path isn't a rooted or relative path, resolve like a module.
|
|
251
|
-
const { resolvedModule } =
|
|
255
|
+
const { resolvedModule } = ts.nodeModuleNameResolver(extendsValue, configFile, { moduleResolution: ts.ModuleResolutionKind.Node10, resolveJsonModule: true }, parseConfigHost);
|
|
252
256
|
if (resolvedModule) {
|
|
253
257
|
return checker.absoluteFrom(resolvedModule.resolvedFileName);
|
|
254
258
|
}
|
|
@@ -256,187 +260,6 @@ function getExtendedConfigPathWorker(configFile, extendsValue, host, fs) {
|
|
|
256
260
|
return null;
|
|
257
261
|
}
|
|
258
262
|
|
|
259
|
-
/**
|
|
260
|
-
* Angular compiler file system implementation that leverages an
|
|
261
|
-
* CLI schematic virtual file tree.
|
|
262
|
-
*/
|
|
263
|
-
class DevkitMigrationFilesystem {
|
|
264
|
-
tree;
|
|
265
|
-
constructor(tree) {
|
|
266
|
-
this.tree = tree;
|
|
267
|
-
}
|
|
268
|
-
extname(path) {
|
|
269
|
-
return core.extname(path);
|
|
270
|
-
}
|
|
271
|
-
isRoot(path) {
|
|
272
|
-
return path === core.normalize('/');
|
|
273
|
-
}
|
|
274
|
-
isRooted(path) {
|
|
275
|
-
return this.normalize(path).startsWith('/');
|
|
276
|
-
}
|
|
277
|
-
dirname(file) {
|
|
278
|
-
return this.normalize(core.dirname(file));
|
|
279
|
-
}
|
|
280
|
-
join(basePath, ...paths) {
|
|
281
|
-
return this.normalize(core.join(basePath, ...paths));
|
|
282
|
-
}
|
|
283
|
-
relative(from, to) {
|
|
284
|
-
return this.normalize(core.relative(from, to));
|
|
285
|
-
}
|
|
286
|
-
basename(filePath, extension) {
|
|
287
|
-
return posixPath__namespace.basename(filePath, extension);
|
|
288
|
-
}
|
|
289
|
-
normalize(path) {
|
|
290
|
-
return core.normalize(path);
|
|
291
|
-
}
|
|
292
|
-
resolve(...paths) {
|
|
293
|
-
const normalizedPaths = paths.map((p) => core.normalize(p));
|
|
294
|
-
// In dev-kit, the NodeJS working directory should never be
|
|
295
|
-
// considered, so `/` is the last resort over `cwd`.
|
|
296
|
-
return this.normalize(posixPath__namespace.resolve(core.normalize('/'), ...normalizedPaths));
|
|
297
|
-
}
|
|
298
|
-
pwd() {
|
|
299
|
-
return '/';
|
|
300
|
-
}
|
|
301
|
-
isCaseSensitive() {
|
|
302
|
-
return true;
|
|
303
|
-
}
|
|
304
|
-
exists(path) {
|
|
305
|
-
return statPath(this.tree, path) !== null;
|
|
306
|
-
}
|
|
307
|
-
readFile(path) {
|
|
308
|
-
return this.tree.readText(path);
|
|
309
|
-
}
|
|
310
|
-
readFileBuffer(path) {
|
|
311
|
-
const buffer = this.tree.read(path);
|
|
312
|
-
if (buffer === null) {
|
|
313
|
-
throw new Error(`File does not exist: ${path}`);
|
|
314
|
-
}
|
|
315
|
-
return buffer;
|
|
316
|
-
}
|
|
317
|
-
readdir(path) {
|
|
318
|
-
const dir = this.tree.getDir(path);
|
|
319
|
-
return [
|
|
320
|
-
...dir.subdirs,
|
|
321
|
-
...dir.subfiles,
|
|
322
|
-
];
|
|
323
|
-
}
|
|
324
|
-
lstat(path) {
|
|
325
|
-
const stat = statPath(this.tree, path);
|
|
326
|
-
if (stat === null) {
|
|
327
|
-
throw new Error(`File does not exist for "lstat": ${path}`);
|
|
328
|
-
}
|
|
329
|
-
return stat;
|
|
330
|
-
}
|
|
331
|
-
stat(path) {
|
|
332
|
-
const stat = statPath(this.tree, path);
|
|
333
|
-
if (stat === null) {
|
|
334
|
-
throw new Error(`File does not exist for "stat": ${path}`);
|
|
335
|
-
}
|
|
336
|
-
return stat;
|
|
337
|
-
}
|
|
338
|
-
realpath(filePath) {
|
|
339
|
-
return filePath;
|
|
340
|
-
}
|
|
341
|
-
getDefaultLibLocation() {
|
|
342
|
-
return 'node_modules/typescript/lib';
|
|
343
|
-
}
|
|
344
|
-
ensureDir(path) {
|
|
345
|
-
// Migrations should compute replacements and not write directly.
|
|
346
|
-
throw new Error('DevkitFilesystem#ensureDir is not supported.');
|
|
347
|
-
}
|
|
348
|
-
writeFile(path, data) {
|
|
349
|
-
// Migrations should compute replacements and not write directly.
|
|
350
|
-
throw new Error('DevkitFilesystem#writeFile is not supported.');
|
|
351
|
-
}
|
|
352
|
-
removeFile(path) {
|
|
353
|
-
// Migrations should compute replacements and not write directly.
|
|
354
|
-
throw new Error('DevkitFilesystem#removeFile is not supported.');
|
|
355
|
-
}
|
|
356
|
-
copyFile(from, to) {
|
|
357
|
-
// Migrations should compute replacements and not write directly.
|
|
358
|
-
throw new Error('DevkitFilesystem#copyFile is not supported.');
|
|
359
|
-
}
|
|
360
|
-
moveFile(from, to) {
|
|
361
|
-
// Migrations should compute replacements and not write directly.
|
|
362
|
-
throw new Error('DevkitFilesystem#moveFile is not supported.');
|
|
363
|
-
}
|
|
364
|
-
removeDeep(path) {
|
|
365
|
-
// Migrations should compute replacements and not write directly.
|
|
366
|
-
throw new Error('DevkitFilesystem#removeDeep is not supported.');
|
|
367
|
-
}
|
|
368
|
-
chdir(_path) {
|
|
369
|
-
throw new Error('FileSystem#chdir is not supported.');
|
|
370
|
-
}
|
|
371
|
-
symlink() {
|
|
372
|
-
throw new Error('FileSystem#symlink is not supported.');
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
/** Stats the given path in the virtual tree. */
|
|
376
|
-
function statPath(tree, path) {
|
|
377
|
-
let fileInfo = null;
|
|
378
|
-
let dirInfo = null;
|
|
379
|
-
try {
|
|
380
|
-
fileInfo = tree.get(path);
|
|
381
|
-
}
|
|
382
|
-
catch (e) {
|
|
383
|
-
if (e.constructor.name === 'PathIsDirectoryException') {
|
|
384
|
-
dirInfo = tree.getDir(path);
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
throw e;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
if (fileInfo !== null || dirInfo !== null) {
|
|
391
|
-
return {
|
|
392
|
-
isDirectory: () => dirInfo !== null,
|
|
393
|
-
isFile: () => fileInfo !== null,
|
|
394
|
-
isSymbolicLink: () => false,
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
return null;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Groups the given replacements per project relative
|
|
402
|
-
* file path.
|
|
403
|
-
*
|
|
404
|
-
* This allows for simple execution of the replacements
|
|
405
|
-
* against a given file. E.g. via {@link applyTextUpdates}.
|
|
406
|
-
*/
|
|
407
|
-
function groupReplacementsByFile(replacements) {
|
|
408
|
-
const result = new Map();
|
|
409
|
-
for (const { projectFile, update } of replacements) {
|
|
410
|
-
if (!result.has(projectFile.rootRelativePath)) {
|
|
411
|
-
result.set(projectFile.rootRelativePath, []);
|
|
412
|
-
}
|
|
413
|
-
result.get(projectFile.rootRelativePath).push(update);
|
|
414
|
-
}
|
|
415
|
-
return result;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
* Synchronously combines unit data for the given migration.
|
|
420
|
-
*
|
|
421
|
-
* Note: This helper is useful for testing and execution of
|
|
422
|
-
* Tsurge migrations in non-batchable environments. In general,
|
|
423
|
-
* prefer parallel execution of combining via e.g. Beam combiners.
|
|
424
|
-
*/
|
|
425
|
-
async function synchronouslyCombineUnitData(migration, unitDatas) {
|
|
426
|
-
if (unitDatas.length === 0) {
|
|
427
|
-
return null;
|
|
428
|
-
}
|
|
429
|
-
if (unitDatas.length === 1) {
|
|
430
|
-
return unitDatas[0];
|
|
431
|
-
}
|
|
432
|
-
let combined = unitDatas[0];
|
|
433
|
-
for (let i = 1; i < unitDatas.length; i++) {
|
|
434
|
-
const other = unitDatas[i];
|
|
435
|
-
combined = await migration.combine(combined, other);
|
|
436
|
-
}
|
|
437
|
-
return combined;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
263
|
/**
|
|
441
264
|
* By default, Tsurge will always create an Angular compiler program
|
|
442
265
|
* for projects analyzed and migrated. This works perfectly fine in
|
|
@@ -464,7 +287,7 @@ const defaultMigrationTsOptions = {
|
|
|
464
287
|
* Creates an instance of a TypeScript program for the given project.
|
|
465
288
|
*/
|
|
466
289
|
function createPlainTsProgram(tsHost, tsconfig, optionOverrides) {
|
|
467
|
-
const program =
|
|
290
|
+
const program = ts.createProgram({
|
|
468
291
|
rootNames: tsconfig.rootNames,
|
|
469
292
|
options: {
|
|
470
293
|
...tsconfig.options,
|
|
@@ -486,14 +309,14 @@ function createPlainTsProgram(tsHost, tsconfig, optionOverrides) {
|
|
|
486
309
|
* an instance of the Angular compiler for the project.
|
|
487
310
|
*/
|
|
488
311
|
function createNgtscProgram(tsHost, tsconfig, optionOverrides) {
|
|
489
|
-
const ngtscProgram = new
|
|
312
|
+
const ngtscProgram = new index.NgtscProgram(tsconfig.rootNames, {
|
|
490
313
|
...tsconfig.options,
|
|
491
314
|
...defaultMigrationTsOptions,
|
|
492
315
|
...optionOverrides,
|
|
493
316
|
}, tsHost);
|
|
494
317
|
// Expose an easy way to debug-print ng semantic diagnostics.
|
|
495
318
|
if (process.env['DEBUG_NG_SEMANTIC_DIAGNOSTICS'] === '1') {
|
|
496
|
-
console.error(
|
|
319
|
+
console.error(ts.formatDiagnosticsWithColorAndContext(ngtscProgram.getNgSemanticDiagnostics(), tsHost));
|
|
497
320
|
}
|
|
498
321
|
return {
|
|
499
322
|
ngCompiler: ngtscProgram.compiler,
|
|
@@ -666,13 +489,257 @@ function isWithinBasePath(fs, base, path) {
|
|
|
666
489
|
return checker.isLocalRelativePath(fs.relative(base, path));
|
|
667
490
|
}
|
|
668
491
|
|
|
669
|
-
|
|
492
|
+
/**
|
|
493
|
+
* Angular compiler file system implementation that leverages an
|
|
494
|
+
* CLI schematic virtual file tree.
|
|
495
|
+
*/
|
|
496
|
+
class DevkitMigrationFilesystem {
|
|
497
|
+
tree;
|
|
498
|
+
constructor(tree) {
|
|
499
|
+
this.tree = tree;
|
|
500
|
+
}
|
|
501
|
+
extname(path) {
|
|
502
|
+
return core.extname(path);
|
|
503
|
+
}
|
|
504
|
+
isRoot(path) {
|
|
505
|
+
return path === core.normalize('/');
|
|
506
|
+
}
|
|
507
|
+
isRooted(path) {
|
|
508
|
+
return this.normalize(path).startsWith('/');
|
|
509
|
+
}
|
|
510
|
+
dirname(file) {
|
|
511
|
+
return this.normalize(core.dirname(file));
|
|
512
|
+
}
|
|
513
|
+
join(basePath, ...paths) {
|
|
514
|
+
return this.normalize(core.join(basePath, ...paths));
|
|
515
|
+
}
|
|
516
|
+
relative(from, to) {
|
|
517
|
+
return this.normalize(core.relative(from, to));
|
|
518
|
+
}
|
|
519
|
+
basename(filePath, extension) {
|
|
520
|
+
return posixPath__namespace.basename(filePath, extension);
|
|
521
|
+
}
|
|
522
|
+
normalize(path) {
|
|
523
|
+
return core.normalize(path);
|
|
524
|
+
}
|
|
525
|
+
resolve(...paths) {
|
|
526
|
+
const normalizedPaths = paths.map((p) => core.normalize(p));
|
|
527
|
+
// In dev-kit, the NodeJS working directory should never be
|
|
528
|
+
// considered, so `/` is the last resort over `cwd`.
|
|
529
|
+
return this.normalize(posixPath__namespace.resolve(core.normalize('/'), ...normalizedPaths));
|
|
530
|
+
}
|
|
531
|
+
pwd() {
|
|
532
|
+
return '/';
|
|
533
|
+
}
|
|
534
|
+
isCaseSensitive() {
|
|
535
|
+
return true;
|
|
536
|
+
}
|
|
537
|
+
exists(path) {
|
|
538
|
+
return statPath(this.tree, path) !== null;
|
|
539
|
+
}
|
|
540
|
+
readFile(path) {
|
|
541
|
+
return this.tree.readText(path);
|
|
542
|
+
}
|
|
543
|
+
readFileBuffer(path) {
|
|
544
|
+
const buffer = this.tree.read(path);
|
|
545
|
+
if (buffer === null) {
|
|
546
|
+
throw new Error(`File does not exist: ${path}`);
|
|
547
|
+
}
|
|
548
|
+
return buffer;
|
|
549
|
+
}
|
|
550
|
+
readdir(path) {
|
|
551
|
+
const dir = this.tree.getDir(path);
|
|
552
|
+
return [
|
|
553
|
+
...dir.subdirs,
|
|
554
|
+
...dir.subfiles,
|
|
555
|
+
];
|
|
556
|
+
}
|
|
557
|
+
lstat(path) {
|
|
558
|
+
const stat = statPath(this.tree, path);
|
|
559
|
+
if (stat === null) {
|
|
560
|
+
throw new Error(`File does not exist for "lstat": ${path}`);
|
|
561
|
+
}
|
|
562
|
+
return stat;
|
|
563
|
+
}
|
|
564
|
+
stat(path) {
|
|
565
|
+
const stat = statPath(this.tree, path);
|
|
566
|
+
if (stat === null) {
|
|
567
|
+
throw new Error(`File does not exist for "stat": ${path}`);
|
|
568
|
+
}
|
|
569
|
+
return stat;
|
|
570
|
+
}
|
|
571
|
+
realpath(filePath) {
|
|
572
|
+
return filePath;
|
|
573
|
+
}
|
|
574
|
+
getDefaultLibLocation() {
|
|
575
|
+
return 'node_modules/typescript/lib';
|
|
576
|
+
}
|
|
577
|
+
ensureDir(path) {
|
|
578
|
+
// Migrations should compute replacements and not write directly.
|
|
579
|
+
throw new Error('DevkitFilesystem#ensureDir is not supported.');
|
|
580
|
+
}
|
|
581
|
+
writeFile(path, data) {
|
|
582
|
+
// Migrations should compute replacements and not write directly.
|
|
583
|
+
throw new Error('DevkitFilesystem#writeFile is not supported.');
|
|
584
|
+
}
|
|
585
|
+
removeFile(path) {
|
|
586
|
+
// Migrations should compute replacements and not write directly.
|
|
587
|
+
throw new Error('DevkitFilesystem#removeFile is not supported.');
|
|
588
|
+
}
|
|
589
|
+
copyFile(from, to) {
|
|
590
|
+
// Migrations should compute replacements and not write directly.
|
|
591
|
+
throw new Error('DevkitFilesystem#copyFile is not supported.');
|
|
592
|
+
}
|
|
593
|
+
moveFile(from, to) {
|
|
594
|
+
// Migrations should compute replacements and not write directly.
|
|
595
|
+
throw new Error('DevkitFilesystem#moveFile is not supported.');
|
|
596
|
+
}
|
|
597
|
+
removeDeep(path) {
|
|
598
|
+
// Migrations should compute replacements and not write directly.
|
|
599
|
+
throw new Error('DevkitFilesystem#removeDeep is not supported.');
|
|
600
|
+
}
|
|
601
|
+
chdir(_path) {
|
|
602
|
+
throw new Error('FileSystem#chdir is not supported.');
|
|
603
|
+
}
|
|
604
|
+
symlink() {
|
|
605
|
+
throw new Error('FileSystem#symlink is not supported.');
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
/** Stats the given path in the virtual tree. */
|
|
609
|
+
function statPath(tree, path) {
|
|
610
|
+
let fileInfo = null;
|
|
611
|
+
let dirInfo = null;
|
|
612
|
+
try {
|
|
613
|
+
fileInfo = tree.get(path);
|
|
614
|
+
}
|
|
615
|
+
catch (e) {
|
|
616
|
+
if (e.constructor.name === 'PathIsDirectoryException') {
|
|
617
|
+
dirInfo = tree.getDir(path);
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
throw e;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (fileInfo !== null || dirInfo !== null) {
|
|
624
|
+
return {
|
|
625
|
+
isDirectory: () => dirInfo !== null,
|
|
626
|
+
isFile: () => fileInfo !== null,
|
|
627
|
+
isSymbolicLink: () => false,
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
return null;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Groups the given replacements per project relative
|
|
635
|
+
* file path.
|
|
636
|
+
*
|
|
637
|
+
* This allows for simple execution of the replacements
|
|
638
|
+
* against a given file. E.g. via {@link applyTextUpdates}.
|
|
639
|
+
*/
|
|
640
|
+
function groupReplacementsByFile(replacements) {
|
|
641
|
+
const result = new Map();
|
|
642
|
+
for (const { projectFile, update } of replacements) {
|
|
643
|
+
if (!result.has(projectFile.rootRelativePath)) {
|
|
644
|
+
result.set(projectFile.rootRelativePath, []);
|
|
645
|
+
}
|
|
646
|
+
result.get(projectFile.rootRelativePath).push(update);
|
|
647
|
+
}
|
|
648
|
+
return result;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Synchronously combines unit data for the given migration.
|
|
653
|
+
*
|
|
654
|
+
* Note: This helper is useful for testing and execution of
|
|
655
|
+
* Tsurge migrations in non-batchable environments. In general,
|
|
656
|
+
* prefer parallel execution of combining via e.g. Beam combiners.
|
|
657
|
+
*/
|
|
658
|
+
async function synchronouslyCombineUnitData(migration, unitDatas) {
|
|
659
|
+
if (unitDatas.length === 0) {
|
|
660
|
+
return null;
|
|
661
|
+
}
|
|
662
|
+
if (unitDatas.length === 1) {
|
|
663
|
+
return unitDatas[0];
|
|
664
|
+
}
|
|
665
|
+
let combined = unitDatas[0];
|
|
666
|
+
for (let i = 1; i < unitDatas.length; i++) {
|
|
667
|
+
const other = unitDatas[i];
|
|
668
|
+
combined = await migration.combine(combined, other);
|
|
669
|
+
}
|
|
670
|
+
return combined;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/*!
|
|
674
|
+
* @license
|
|
675
|
+
* Copyright Google LLC All Rights Reserved.
|
|
676
|
+
*
|
|
677
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
678
|
+
* found in the LICENSE file at https://angular.dev/license
|
|
679
|
+
*/
|
|
680
|
+
/** Runs a Tsurge within an Angular Devkit context. */
|
|
681
|
+
async function runMigrationInDevkit(config) {
|
|
682
|
+
const { buildPaths, testPaths } = await project_tsconfig_paths.getProjectTsConfigPaths(config.tree);
|
|
683
|
+
if (!buildPaths.length && !testPaths.length) {
|
|
684
|
+
throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run the migration.');
|
|
685
|
+
}
|
|
686
|
+
const fs = new DevkitMigrationFilesystem(config.tree);
|
|
687
|
+
checker.setFileSystem(fs);
|
|
688
|
+
const migration = config.getMigration(fs);
|
|
689
|
+
const unitResults = [];
|
|
690
|
+
const programInfos = [...buildPaths, ...testPaths].map((tsconfigPath) => {
|
|
691
|
+
config.beforeProgramCreation?.(tsconfigPath);
|
|
692
|
+
const baseInfo = migration.createProgram(tsconfigPath, fs);
|
|
693
|
+
const info = migration.prepareProgram(baseInfo);
|
|
694
|
+
config.afterProgramCreation?.(info, fs);
|
|
695
|
+
return { info, tsconfigPath };
|
|
696
|
+
});
|
|
697
|
+
for (const { info, tsconfigPath } of programInfos) {
|
|
698
|
+
config.beforeUnitAnalysis?.(tsconfigPath);
|
|
699
|
+
unitResults.push(await migration.analyze(info));
|
|
700
|
+
}
|
|
701
|
+
config.afterAllAnalyzed?.();
|
|
702
|
+
const combined = await synchronouslyCombineUnitData(migration, unitResults);
|
|
703
|
+
if (combined === null) {
|
|
704
|
+
config.afterAnalysisFailure?.();
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
const globalMeta = await migration.globalMeta(combined);
|
|
708
|
+
let replacements;
|
|
709
|
+
if (migration instanceof TsurgeFunnelMigration) {
|
|
710
|
+
replacements = (await migration.migrate(globalMeta)).replacements;
|
|
711
|
+
}
|
|
712
|
+
else {
|
|
713
|
+
replacements = [];
|
|
714
|
+
for (const { info } of programInfos) {
|
|
715
|
+
const result = await migration.migrate(globalMeta, info);
|
|
716
|
+
replacements.push(...result.replacements);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
const replacementsPerFile = new Map();
|
|
720
|
+
const changesPerFile = groupReplacementsByFile(replacements);
|
|
721
|
+
for (const [file, changes] of changesPerFile) {
|
|
722
|
+
if (!replacementsPerFile.has(file)) {
|
|
723
|
+
replacementsPerFile.set(file, changes);
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
for (const [file, changes] of replacementsPerFile) {
|
|
727
|
+
const recorder = config.tree.beginUpdate(file);
|
|
728
|
+
for (const c of changes) {
|
|
729
|
+
recorder
|
|
730
|
+
.remove(c.data.position, c.data.end - c.data.position)
|
|
731
|
+
.insertRight(c.data.position, c.data.toInsert);
|
|
732
|
+
}
|
|
733
|
+
config.tree.commitUpdate(recorder);
|
|
734
|
+
}
|
|
735
|
+
config.whenDone?.(await migration.stats(globalMeta));
|
|
736
|
+
}
|
|
737
|
+
|
|
670
738
|
exports.Replacement = Replacement;
|
|
671
739
|
exports.TextUpdate = TextUpdate;
|
|
672
740
|
exports.TsurgeComplexMigration = TsurgeComplexMigration;
|
|
673
741
|
exports.TsurgeFunnelMigration = TsurgeFunnelMigration;
|
|
674
742
|
exports.confirmAsSerializable = confirmAsSerializable;
|
|
675
743
|
exports.createBaseProgramInfo = createBaseProgramInfo;
|
|
676
|
-
exports.groupReplacementsByFile = groupReplacementsByFile;
|
|
677
744
|
exports.projectFile = projectFile;
|
|
678
|
-
exports.
|
|
745
|
+
exports.runMigrationInDevkit = runMigrationInDevkit;
|