@angular/core 19.2.0-next.3 → 19.2.0-rc.0

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 (42) hide show
  1. package/fesm2022/core.mjs +973 -988
  2. package/fesm2022/core.mjs.map +1 -1
  3. package/fesm2022/primitives/event-dispatch.mjs +1 -1
  4. package/fesm2022/primitives/signals.mjs +5 -5
  5. package/fesm2022/primitives/signals.mjs.map +1 -1
  6. package/fesm2022/rxjs-interop.mjs +1 -1
  7. package/fesm2022/testing.mjs +4 -4
  8. package/index.d.ts +68 -35
  9. package/package.json +1 -1
  10. package/primitives/event-dispatch/index.d.ts +1 -1
  11. package/primitives/signals/index.d.ts +2 -2
  12. package/rxjs-interop/index.d.ts +1 -1
  13. package/schematics/bundles/apply_import_manager-a930fcf1.js +71 -0
  14. package/schematics/bundles/{checker-32db85a6.js → checker-2eecc677.js} +17 -16
  15. package/schematics/bundles/cleanup-unused-imports.js +16 -15
  16. package/schematics/bundles/{compiler_host-540e221c.js → compiler_host-c280a924.js} +2 -2
  17. package/schematics/bundles/control-flow-migration.js +3 -3
  18. package/schematics/bundles/explicit-standalone-flag.js +3 -3
  19. package/schematics/bundles/imports-abe29092.js +1 -1
  20. package/schematics/bundles/{index-d5020c9c.js → index-24a2ad1e.js} +9 -9
  21. package/schematics/bundles/{index-7ee8967e.js → index-3891dd55.js} +4 -4
  22. package/schematics/bundles/inject-migration.js +8 -7
  23. package/schematics/bundles/leading_space-d190b83b.js +1 -1
  24. package/schematics/bundles/{migrate_ts_type_references-26986908.js → migrate_ts_type_references-71b3a951.js} +20 -20
  25. package/schematics/bundles/{nodes-a9f0b985.js → ng_decorators-e699c081.js} +1 -14
  26. package/schematics/bundles/nodes-a535b2be.js +27 -0
  27. package/schematics/bundles/output-migration.js +21 -20
  28. package/schematics/bundles/pending-tasks.js +3 -3
  29. package/schematics/bundles/{program-507de2f1.js → program-24da9092.js} +90 -45
  30. package/schematics/bundles/{apply_import_manager-f4d044b2.js → project_paths-b073c4d6.js} +3 -57
  31. package/schematics/bundles/project_tsconfig_paths-e9ccccbf.js +1 -1
  32. package/schematics/bundles/property_name-7c8433f5.js +31 -0
  33. package/schematics/bundles/provide-initializer.js +3 -3
  34. package/schematics/bundles/route-lazy-loading.js +8 -12
  35. package/schematics/bundles/self-closing-tags-migration.js +448 -0
  36. package/schematics/bundles/signal-input-migration.js +20 -19
  37. package/schematics/bundles/signal-queries-migration.js +26 -25
  38. package/schematics/bundles/signals.js +7 -6
  39. package/schematics/bundles/standalone-migration.js +12 -11
  40. package/schematics/collection.json +6 -0
  41. package/schematics/ng-generate/self-closing-tags-migration/schema.json +14 -0
  42. package/testing/index.d.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.2.0-next.3
3
+ * @license Angular v19.2.0-rc.0
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -11,11 +11,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
11
11
  var schematics = require('@angular-devkit/schematics');
12
12
  var p = require('path');
13
13
  var project_tsconfig_paths = require('./project_tsconfig_paths-e9ccccbf.js');
14
- var compiler_host = require('./compiler_host-540e221c.js');
14
+ var compiler_host = require('./compiler_host-c280a924.js');
15
15
  var ts = require('typescript');
16
16
  var imports = require('./imports-abe29092.js');
17
17
  require('@angular-devkit/core');
18
- require('./checker-32db85a6.js');
18
+ require('./checker-2eecc677.js');
19
19
  require('os');
20
20
  require('fs');
21
21
  require('module');
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.2.0-next.3
3
+ * @license Angular v19.2.0-rc.0
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -11,10 +11,11 @@ Object.defineProperty(exports, '__esModule', { value: true });
11
11
  var schematics = require('@angular-devkit/schematics');
12
12
  var fs = require('fs');
13
13
  var p = require('path');
14
- var compiler_host = require('./compiler_host-540e221c.js');
14
+ var compiler_host = require('./compiler_host-c280a924.js');
15
15
  var project_tsconfig_paths = require('./project_tsconfig_paths-e9ccccbf.js');
16
16
  var ts = require('typescript');
17
- var checker = require('./checker-32db85a6.js');
17
+ var checker = require('./checker-2eecc677.js');
18
+ var property_name = require('./property_name-7c8433f5.js');
18
19
  require('os');
19
20
  require('@angular-devkit/core');
20
21
  require('module');
@@ -36,11 +37,6 @@ function findClassDeclaration(reference, typeChecker) {
36
37
  ?.declarations?.find(ts__default["default"].isClassDeclaration) || null);
37
38
  }
38
39
 
39
- /** Finds a property with a specific name in an object literal expression. */
40
- function findLiteralProperty(literal, name) {
41
- return literal.properties.find((prop) => prop.name && ts__default["default"].isIdentifier(prop.name) && prop.name.text === name);
42
- }
43
-
44
40
  /*!
45
41
  * @license
46
42
  * Copyright Google LLC All Rights Reserved.
@@ -64,7 +60,7 @@ function isStandaloneComponent(node, reflector) {
64
60
  }
65
61
  const arg = decorator.args[0];
66
62
  if (ts__default["default"].isObjectLiteralExpression(arg)) {
67
- const property = findLiteralProperty(arg, 'standalone');
63
+ const property = property_name.findLiteralProperty(arg, 'standalone');
68
64
  if (property) {
69
65
  return property.initializer.getText() === 'true';
70
66
  }
@@ -270,10 +266,10 @@ function migrateRoute(element, route, typeChecker, reflector, tracker) {
270
266
  const skippedRoutes = [];
271
267
  const migratedRoutes = [];
272
268
  const importsToRemove = [];
273
- const component = findLiteralProperty(element, 'component');
269
+ const component = property_name.findLiteralProperty(element, 'component');
274
270
  // this can be empty string or a variable that is not a string, or not present at all
275
- const routePath = findLiteralProperty(element, 'path')?.getText() ?? '';
276
- const children = findLiteralProperty(element, 'children');
271
+ const routePath = property_name.findLiteralProperty(element, 'path')?.getText() ?? '';
272
+ const children = property_name.findLiteralProperty(element, 'children');
277
273
  // recursively migrate children routes first if they exist
278
274
  if (children && ts__default["default"].isArrayLiteralExpression(children.initializer)) {
279
275
  for (const childRoute of children.initializer.elements) {
@@ -0,0 +1,448 @@
1
+ 'use strict';
2
+ /**
3
+ * @license Angular v19.2.0-rc.0
4
+ * (c) 2010-2024 Google LLC. https://angular.io/
5
+ * License: MIT
6
+ */
7
+ 'use strict';
8
+
9
+ Object.defineProperty(exports, '__esModule', { value: true });
10
+
11
+ var schematics = require('@angular-devkit/schematics');
12
+ var project_tsconfig_paths = require('./project_tsconfig_paths-e9ccccbf.js');
13
+ var project_paths = require('./project_paths-b073c4d6.js');
14
+ require('os');
15
+ var ts = require('typescript');
16
+ var checker = require('./checker-2eecc677.js');
17
+ require('./program-24da9092.js');
18
+ require('path');
19
+ var ng_decorators = require('./ng_decorators-e699c081.js');
20
+ var property_name = require('./property_name-7c8433f5.js');
21
+ require('@angular-devkit/core');
22
+ require('node:path/posix');
23
+ require('fs');
24
+ require('module');
25
+ require('url');
26
+ require('./imports-abe29092.js');
27
+
28
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
29
+
30
+ var ts__default = /*#__PURE__*/_interopDefaultLegacy(ts);
31
+
32
+ /**
33
+ * Unwraps a given expression TypeScript node. Expressions can be wrapped within multiple
34
+ * parentheses or as expression. e.g. "(((({exp}))))()". The function should return the
35
+ * TypeScript node referring to the inner expression. e.g "exp".
36
+ */
37
+ function unwrapExpression(node) {
38
+ if (ts__default["default"].isParenthesizedExpression(node) || ts__default["default"].isAsExpression(node)) {
39
+ return unwrapExpression(node.expression);
40
+ }
41
+ else {
42
+ return node;
43
+ }
44
+ }
45
+
46
+ /** Extracts `@Directive` or `@Component` metadata from the given class. */
47
+ function extractAngularClassMetadata(typeChecker, node) {
48
+ const decorators = ts__default["default"].getDecorators(node);
49
+ if (!decorators || !decorators.length) {
50
+ return null;
51
+ }
52
+ const ngDecorators = ng_decorators.getAngularDecorators(typeChecker, decorators);
53
+ const componentDecorator = ngDecorators.find((dec) => dec.name === 'Component');
54
+ const directiveDecorator = ngDecorators.find((dec) => dec.name === 'Directive');
55
+ const decorator = componentDecorator ?? directiveDecorator;
56
+ // In case no decorator could be found on the current class, skip.
57
+ if (!decorator) {
58
+ return null;
59
+ }
60
+ const decoratorCall = decorator.node.expression;
61
+ // In case the decorator call is not valid, skip this class declaration.
62
+ if (decoratorCall.arguments.length !== 1) {
63
+ return null;
64
+ }
65
+ const metadata = unwrapExpression(decoratorCall.arguments[0]);
66
+ // Ensure that the metadata is an object literal expression.
67
+ if (!ts__default["default"].isObjectLiteralExpression(metadata)) {
68
+ return null;
69
+ }
70
+ return {
71
+ type: componentDecorator ? 'component' : 'directive',
72
+ node: metadata,
73
+ };
74
+ }
75
+
76
+ const LF_CHAR = 10;
77
+ const CR_CHAR = 13;
78
+ const LINE_SEP_CHAR = 8232;
79
+ const PARAGRAPH_CHAR = 8233;
80
+ /** Gets the line and character for the given position from the line starts map. */
81
+ function getLineAndCharacterFromPosition(lineStartsMap, position) {
82
+ const lineIndex = findClosestLineStartPosition(lineStartsMap, position);
83
+ return { character: position - lineStartsMap[lineIndex], line: lineIndex };
84
+ }
85
+ /**
86
+ * Computes the line start map of the given text. This can be used in order to
87
+ * retrieve the line and character of a given text position index.
88
+ */
89
+ function computeLineStartsMap(text) {
90
+ const result = [0];
91
+ let pos = 0;
92
+ while (pos < text.length) {
93
+ const char = text.charCodeAt(pos++);
94
+ // Handles the "CRLF" line break. In that case we peek the character
95
+ // after the "CR" and check if it is a line feed.
96
+ if (char === CR_CHAR) {
97
+ if (text.charCodeAt(pos) === LF_CHAR) {
98
+ pos++;
99
+ }
100
+ result.push(pos);
101
+ }
102
+ else if (char === LF_CHAR || char === LINE_SEP_CHAR || char === PARAGRAPH_CHAR) {
103
+ result.push(pos);
104
+ }
105
+ }
106
+ result.push(pos);
107
+ return result;
108
+ }
109
+ /** Finds the closest line start for the given position. */
110
+ function findClosestLineStartPosition(linesMap, position, low = 0, high = linesMap.length - 1) {
111
+ while (low <= high) {
112
+ const pivotIdx = Math.floor((low + high) / 2);
113
+ const pivotEl = linesMap[pivotIdx];
114
+ if (pivotEl === position) {
115
+ return pivotIdx;
116
+ }
117
+ else if (position > pivotEl) {
118
+ low = pivotIdx + 1;
119
+ }
120
+ else {
121
+ high = pivotIdx - 1;
122
+ }
123
+ }
124
+ // In case there was no exact match, return the closest "lower" line index. We also
125
+ // subtract the index by one because want the index of the previous line start.
126
+ return low - 1;
127
+ }
128
+
129
+ /**
130
+ * Visitor that can be used to determine Angular templates referenced within given
131
+ * TypeScript source files (inline templates or external referenced templates)
132
+ */
133
+ class NgComponentTemplateVisitor {
134
+ typeChecker;
135
+ resolvedTemplates = [];
136
+ fs = checker.getFileSystem();
137
+ constructor(typeChecker) {
138
+ this.typeChecker = typeChecker;
139
+ }
140
+ visitNode(node) {
141
+ if (node.kind === ts__default["default"].SyntaxKind.ClassDeclaration) {
142
+ this.visitClassDeclaration(node);
143
+ }
144
+ ts__default["default"].forEachChild(node, (n) => this.visitNode(n));
145
+ }
146
+ visitClassDeclaration(node) {
147
+ const metadata = extractAngularClassMetadata(this.typeChecker, node);
148
+ if (metadata === null || metadata.type !== 'component') {
149
+ return;
150
+ }
151
+ const sourceFile = node.getSourceFile();
152
+ const sourceFileName = sourceFile.fileName;
153
+ // Walk through all component metadata properties and determine the referenced
154
+ // HTML templates (either external or inline)
155
+ metadata.node.properties.forEach((property) => {
156
+ if (!ts__default["default"].isPropertyAssignment(property)) {
157
+ return;
158
+ }
159
+ const propertyName = property_name.getPropertyNameText(property.name);
160
+ // In case there is an inline template specified, ensure that the value is statically
161
+ // analyzable by checking if the initializer is a string literal-like node.
162
+ if (propertyName === 'template' && ts__default["default"].isStringLiteralLike(property.initializer)) {
163
+ // Need to add an offset of one to the start because the template quotes are
164
+ // not part of the template content.
165
+ // The `getText()` method gives us the original raw text.
166
+ // We could have used the `text` property, but if the template is defined as a backtick
167
+ // string then the `text` property contains a "cooked" version of the string. Such cooked
168
+ // strings will have converted CRLF characters to only LF. This messes up string
169
+ // replacements in template migrations.
170
+ // The raw text returned by `getText()` includes the enclosing quotes so we change the
171
+ // `content` and `start` values accordingly.
172
+ const content = property.initializer.getText().slice(1, -1);
173
+ const start = property.initializer.getStart() + 1;
174
+ this.resolvedTemplates.push({
175
+ filePath: sourceFileName,
176
+ container: node,
177
+ content,
178
+ inline: true,
179
+ start: start,
180
+ getCharacterAndLineOfPosition: (pos) => ts__default["default"].getLineAndCharacterOfPosition(sourceFile, pos + start),
181
+ });
182
+ }
183
+ if (propertyName === 'templateUrl' && ts__default["default"].isStringLiteralLike(property.initializer)) {
184
+ const absolutePath = this.fs.resolve(this.fs.dirname(sourceFileName), property.initializer.text);
185
+ if (!this.fs.exists(absolutePath)) {
186
+ return;
187
+ }
188
+ const fileContent = this.fs.readFile(absolutePath);
189
+ const lineStartsMap = computeLineStartsMap(fileContent);
190
+ this.resolvedTemplates.push({
191
+ filePath: absolutePath,
192
+ container: node,
193
+ content: fileContent,
194
+ inline: false,
195
+ start: 0,
196
+ getCharacterAndLineOfPosition: (pos) => getLineAndCharacterFromPosition(lineStartsMap, pos),
197
+ });
198
+ }
199
+ });
200
+ }
201
+ }
202
+
203
+ function parseTemplate(template) {
204
+ let parsed;
205
+ try {
206
+ // Note: we use the HtmlParser here, instead of the `parseTemplate` function, because the
207
+ // latter returns an Ivy AST, not an HTML AST. The HTML AST has the advantage of preserving
208
+ // interpolated text as text nodes containing a mixture of interpolation tokens and text tokens,
209
+ // rather than turning them into `BoundText` nodes like the Ivy AST does. This allows us to
210
+ // easily get the text-only ranges without having to reconstruct the original text.
211
+ parsed = new checker.HtmlParser().parse(template, '', {
212
+ // Allows for ICUs to be parsed.
213
+ tokenizeExpansionForms: true,
214
+ // Explicitly disable blocks so that their characters are treated as plain text.
215
+ tokenizeBlocks: true,
216
+ preserveLineEndings: true,
217
+ });
218
+ // Don't migrate invalid templates.
219
+ if (parsed.errors && parsed.errors.length > 0) {
220
+ const errors = parsed.errors.map((e) => ({ type: 'parse', error: e }));
221
+ return { tree: undefined, errors };
222
+ }
223
+ }
224
+ catch (e) {
225
+ return { tree: undefined, errors: [{ type: 'parse', error: e }] };
226
+ }
227
+ return { tree: parsed, errors: [] };
228
+ }
229
+
230
+ function migrateTemplateToSelfClosingTags(template) {
231
+ let parsed = parseTemplate(template);
232
+ if (parsed.tree === undefined) {
233
+ return { migrated: template, changed: false, replacementCount: 0 };
234
+ }
235
+ const visitor = new AngularElementCollector();
236
+ checker.visitAll(visitor, parsed.tree.rootNodes);
237
+ let newTemplate = template;
238
+ let changedOffset = 0;
239
+ let replacementCount = 0;
240
+ for (let element of visitor.elements) {
241
+ const { start, end, tagName } = element;
242
+ const currentLength = newTemplate.length;
243
+ const templatePart = newTemplate.slice(start + changedOffset, end + changedOffset);
244
+ const convertedTemplate = replaceWithSelfClosingTag(templatePart, tagName);
245
+ // if the template has changed, replace the original template with the new one
246
+ if (convertedTemplate.length !== templatePart.length) {
247
+ newTemplate = replaceTemplate(newTemplate, convertedTemplate, start, end, changedOffset);
248
+ changedOffset += newTemplate.length - currentLength;
249
+ replacementCount++;
250
+ }
251
+ }
252
+ return { migrated: newTemplate, changed: changedOffset !== 0, replacementCount };
253
+ }
254
+ function replaceWithSelfClosingTag(html, tagName) {
255
+ const pattern = new RegExp(`<\\s*${tagName}\\s*([^>]*?(?:"[^"]*"|'[^']*'|[^'">])*)\\s*>([\\s\\S]*?)<\\s*/\\s*${tagName}\\s*>`, 'gi');
256
+ return html.replace(pattern, (_, content) => `<${tagName}${content ? ` ${content}` : ''} />`);
257
+ }
258
+ /**
259
+ * Replace the value in the template with the new value based on the start and end position + offset
260
+ */
261
+ function replaceTemplate(template, replaceValue, start, end, offset) {
262
+ return template.slice(0, start + offset) + replaceValue + template.slice(end + offset);
263
+ }
264
+ const ALL_HTML_TAGS = new checker.DomElementSchemaRegistry().allKnownElementNames();
265
+ class AngularElementCollector extends checker.RecursiveVisitor {
266
+ elements = [];
267
+ constructor() {
268
+ super();
269
+ }
270
+ visitElement(element) {
271
+ const isHtmlTag = ALL_HTML_TAGS.includes(element.name);
272
+ if (isHtmlTag) {
273
+ return;
274
+ }
275
+ const hasNoContent = this.elementHasNoContent(element);
276
+ const hasNoClosingTag = this.elementHasNoClosingTag(element);
277
+ if (hasNoContent && !hasNoClosingTag) {
278
+ this.elements.push({
279
+ tagName: element.name,
280
+ start: element.sourceSpan.start.offset,
281
+ end: element.sourceSpan.end.offset,
282
+ });
283
+ }
284
+ return super.visitElement(element, null);
285
+ }
286
+ elementHasNoContent(element) {
287
+ if (!element.children?.length) {
288
+ return true;
289
+ }
290
+ if (element.children.length === 1) {
291
+ const child = element.children[0];
292
+ return child instanceof checker.Text && /^\s*$/.test(child.value);
293
+ }
294
+ return false;
295
+ }
296
+ elementHasNoClosingTag(element) {
297
+ const { startSourceSpan, endSourceSpan } = element;
298
+ if (!endSourceSpan) {
299
+ return true;
300
+ }
301
+ return (startSourceSpan.start.offset === endSourceSpan.start.offset &&
302
+ startSourceSpan.end.offset === endSourceSpan.end.offset);
303
+ }
304
+ }
305
+
306
+ class SelfClosingTagsMigration extends project_paths.TsurgeFunnelMigration {
307
+ config;
308
+ constructor(config = {}) {
309
+ super();
310
+ this.config = config;
311
+ }
312
+ async analyze(info) {
313
+ const { sourceFiles, program } = info;
314
+ const typeChecker = program.getTypeChecker();
315
+ const tagReplacements = [];
316
+ for (const sf of sourceFiles) {
317
+ ts__default["default"].forEachChild(sf, (node) => {
318
+ if (!ts__default["default"].isClassDeclaration(node)) {
319
+ return;
320
+ }
321
+ const file = project_paths.projectFile(node.getSourceFile(), info);
322
+ if (this.config.shouldMigrate && this.config.shouldMigrate(file) === false) {
323
+ return;
324
+ }
325
+ const templateVisitor = new NgComponentTemplateVisitor(typeChecker);
326
+ templateVisitor.visitNode(node);
327
+ templateVisitor.resolvedTemplates.forEach((template) => {
328
+ const { migrated, changed, replacementCount } = migrateTemplateToSelfClosingTags(template.content);
329
+ if (changed) {
330
+ const fileToMigrate = template.inline
331
+ ? file
332
+ : project_paths.projectFile(template.filePath, info);
333
+ const end = template.start + template.content.length;
334
+ const replacements = [
335
+ prepareTextReplacement(fileToMigrate, migrated, template.start, end),
336
+ ];
337
+ const fileReplacements = tagReplacements.find((tagReplacement) => tagReplacement.file === file);
338
+ if (fileReplacements) {
339
+ fileReplacements.replacements.push(...replacements);
340
+ fileReplacements.replacementCount += replacementCount;
341
+ }
342
+ else {
343
+ tagReplacements.push({ file, replacements, replacementCount });
344
+ }
345
+ }
346
+ });
347
+ });
348
+ }
349
+ return project_paths.confirmAsSerializable({ tagReplacements });
350
+ }
351
+ async combine(unitA, unitB) {
352
+ return project_paths.confirmAsSerializable({
353
+ tagReplacements: unitA.tagReplacements.concat(unitB.tagReplacements),
354
+ });
355
+ }
356
+ async globalMeta(combinedData) {
357
+ const globalMeta = {
358
+ tagReplacements: combinedData.tagReplacements,
359
+ };
360
+ return project_paths.confirmAsSerializable(globalMeta);
361
+ }
362
+ async stats(globalMetadata) {
363
+ const touchedFilesCount = globalMetadata.tagReplacements.length;
364
+ const replacementCount = globalMetadata.tagReplacements.reduce((acc, cur) => acc + cur.replacementCount, 0);
365
+ return {
366
+ counters: {
367
+ touchedFilesCount,
368
+ replacementCount,
369
+ },
370
+ };
371
+ }
372
+ async migrate(globalData) {
373
+ return { replacements: globalData.tagReplacements.flatMap(({ replacements }) => replacements) };
374
+ }
375
+ }
376
+ function prepareTextReplacement(file, replacement, start, end) {
377
+ return new project_paths.Replacement(file, new project_paths.TextUpdate({
378
+ position: start,
379
+ end: end,
380
+ toInsert: replacement,
381
+ }));
382
+ }
383
+
384
+ function migrate(options) {
385
+ return async (tree, context) => {
386
+ const { buildPaths, testPaths } = await project_tsconfig_paths.getProjectTsConfigPaths(tree);
387
+ if (!buildPaths.length && !testPaths.length) {
388
+ throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run self-closing tags migration.');
389
+ }
390
+ const fs = new project_paths.DevkitMigrationFilesystem(tree);
391
+ checker.setFileSystem(fs);
392
+ const migration = new SelfClosingTagsMigration({
393
+ shouldMigrate: (file) => {
394
+ return (file.rootRelativePath.startsWith(fs.normalize(options.path)) &&
395
+ !/(^|\/)node_modules\//.test(file.rootRelativePath));
396
+ },
397
+ });
398
+ const unitResults = [];
399
+ const programInfos = [...buildPaths, ...testPaths].map((tsconfigPath) => {
400
+ context.logger.info(`Preparing analysis for: ${tsconfigPath}..`);
401
+ const baseInfo = migration.createProgram(tsconfigPath, fs);
402
+ const info = migration.prepareProgram(baseInfo);
403
+ return { info, tsconfigPath };
404
+ });
405
+ // Analyze phase. Treat all projects as compilation units as
406
+ // this allows us to support references between those.
407
+ for (const { info, tsconfigPath } of programInfos) {
408
+ context.logger.info(`Scanning for component tags: ${tsconfigPath}..`);
409
+ unitResults.push(await migration.analyze(info));
410
+ }
411
+ context.logger.info(``);
412
+ context.logger.info(`Processing analysis data between targets..`);
413
+ context.logger.info(``);
414
+ const combined = await project_paths.synchronouslyCombineUnitData(migration, unitResults);
415
+ if (combined === null) {
416
+ context.logger.error('Migration failed unexpectedly with no analysis data');
417
+ return;
418
+ }
419
+ const globalMeta = await migration.globalMeta(combined);
420
+ const replacementsPerFile = new Map();
421
+ for (const { tsconfigPath } of programInfos) {
422
+ context.logger.info(`Migrating: ${tsconfigPath}..`);
423
+ const { replacements } = await migration.migrate(globalMeta);
424
+ const changesPerFile = project_paths.groupReplacementsByFile(replacements);
425
+ for (const [file, changes] of changesPerFile) {
426
+ if (!replacementsPerFile.has(file)) {
427
+ replacementsPerFile.set(file, changes);
428
+ }
429
+ }
430
+ }
431
+ context.logger.info(`Applying changes..`);
432
+ for (const [file, changes] of replacementsPerFile) {
433
+ const recorder = tree.beginUpdate(file);
434
+ for (const c of changes) {
435
+ recorder
436
+ .remove(c.data.position, c.data.end - c.data.position)
437
+ .insertLeft(c.data.position, c.data.toInsert);
438
+ }
439
+ tree.commitUpdate(recorder);
440
+ }
441
+ const { counters: { touchedFilesCount, replacementCount }, } = await migration.stats(globalMeta);
442
+ context.logger.info('');
443
+ context.logger.info(`Successfully migrated to self-closing tags 🎉`);
444
+ context.logger.info(` -> Migrated ${replacementCount} components to self-closing tags in ${touchedFilesCount} component files.`);
445
+ };
446
+ }
447
+
448
+ exports.migrate = migrate;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.2.0-next.3
3
+ * @license Angular v19.2.0-rc.0
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -9,15 +9,16 @@
9
9
  Object.defineProperty(exports, '__esModule', { value: true });
10
10
 
11
11
  var schematics = require('@angular-devkit/schematics');
12
- var migrate_ts_type_references = require('./migrate_ts_type_references-26986908.js');
12
+ var migrate_ts_type_references = require('./migrate_ts_type_references-71b3a951.js');
13
13
  var ts = require('typescript');
14
14
  require('os');
15
- var checker = require('./checker-32db85a6.js');
16
- var program = require('./program-507de2f1.js');
15
+ var checker = require('./checker-2eecc677.js');
16
+ var program = require('./program-24da9092.js');
17
17
  require('path');
18
- var apply_import_manager = require('./apply_import_manager-f4d044b2.js');
19
- var index = require('./index-d5020c9c.js');
18
+ var project_paths = require('./project_paths-b073c4d6.js');
19
+ var index = require('./index-24a2ad1e.js');
20
20
  var assert = require('assert');
21
+ var apply_import_manager = require('./apply_import_manager-a930fcf1.js');
21
22
  var project_tsconfig_paths = require('./project_tsconfig_paths-e9ccccbf.js');
22
23
  require('./leading_space-d190b83b.js');
23
24
  require('fs');
@@ -108,7 +109,7 @@ function getInputDescriptor(hostOrInfo, node) {
108
109
  className = node.parent.name?.text ?? '<anonymous>';
109
110
  }
110
111
  const info = hostOrInfo instanceof MigrationHost ? hostOrInfo.programInfo : hostOrInfo;
111
- const file = apply_import_manager.projectFile(node.getSourceFile(), info);
112
+ const file = project_paths.projectFile(node.getSourceFile(), info);
112
113
  // Inputs may be detected in `.d.ts` files. Ensure that if the file IDs
113
114
  // match regardless of extension. E.g. `/google3/blaze-out/bin/my_file.ts` should
114
115
  // have the same ID as `/google3/my_file.ts`.
@@ -187,7 +188,7 @@ class KnownInputs {
187
188
  }
188
189
  const directiveInfo = this._classToDirectiveInfo.get(data.node.parent);
189
190
  const inputInfo = {
190
- file: apply_import_manager.projectFile(data.node.getSourceFile(), this.programInfo),
191
+ file: project_paths.projectFile(data.node.getSourceFile(), this.programInfo),
191
192
  metadata: data.metadata,
192
193
  descriptor: data.descriptor,
193
194
  container: directiveInfo,
@@ -1041,7 +1042,7 @@ function convertToSignalInput(node, { resolvedMetadata: metadata, resolvedType,
1041
1042
  if (leadingTodoText !== null) {
1042
1043
  replacements.push(migrate_ts_type_references.insertPrecedingLine(node, info, '// TODO: Notes from signal input migration:'), ...migrate_ts_type_references.cutStringToLineLimit(leadingTodoText, 70).map((line) => migrate_ts_type_references.insertPrecedingLine(node, info, `// ${line}`)));
1043
1044
  }
1044
- replacements.push(new apply_import_manager.Replacement(apply_import_manager.projectFile(node.getSourceFile(), info), new apply_import_manager.TextUpdate({
1045
+ replacements.push(new project_paths.Replacement(project_paths.projectFile(node.getSourceFile(), info), new project_paths.TextUpdate({
1045
1046
  position: node.getStart(),
1046
1047
  end: node.getEnd(),
1047
1048
  toInsert: newPropertyText,
@@ -1159,7 +1160,7 @@ function pass7__migrateTemplateReferences(host, references) {
1159
1160
  const appendText = reference.from.isObjectShorthandExpression
1160
1161
  ? `: ${reference.from.read.name}()`
1161
1162
  : `()`;
1162
- host.replacements.push(new apply_import_manager.Replacement(reference.from.templateFile, new apply_import_manager.TextUpdate({
1163
+ host.replacements.push(new project_paths.Replacement(reference.from.templateFile, new project_paths.TextUpdate({
1163
1164
  position: reference.from.read.sourceSpan.end,
1164
1165
  end: reference.from.read.sourceSpan.end,
1165
1166
  toInsert: appendText,
@@ -1199,7 +1200,7 @@ function pass8__migrateHostBindings(host, references, info) {
1199
1200
  const appendText = reference.from.isObjectShorthandExpression
1200
1201
  ? `: ${reference.from.read.name}()`
1201
1202
  : `()`;
1202
- host.replacements.push(new apply_import_manager.Replacement(apply_import_manager.projectFile(bindingField.getSourceFile(), info), new apply_import_manager.TextUpdate({ position: readEndPos, end: readEndPos, toInsert: appendText })));
1203
+ host.replacements.push(new project_paths.Replacement(project_paths.projectFile(bindingField.getSourceFile(), info), new project_paths.TextUpdate({ position: readEndPos, end: readEndPos, toInsert: appendText })));
1203
1204
  }
1204
1205
  }
1205
1206
 
@@ -1262,7 +1263,7 @@ function filterIncompatibilitiesForBestEffortMode(knownInputs) {
1262
1263
  * Tsurge migration for migrating Angular `@Input()` declarations to
1263
1264
  * signal inputs, with support for batch execution.
1264
1265
  */
1265
- class SignalInputMigration extends apply_import_manager.TsurgeComplexMigration {
1266
+ class SignalInputMigration extends project_paths.TsurgeComplexMigration {
1266
1267
  config;
1267
1268
  upgradedAnalysisPhaseResults = null;
1268
1269
  constructor(config = {}) {
@@ -1271,7 +1272,7 @@ class SignalInputMigration extends apply_import_manager.TsurgeComplexMigration {
1271
1272
  }
1272
1273
  // Override the default program creation, to add extra flags.
1273
1274
  createProgram(tsconfigAbsPath, fs) {
1274
- return apply_import_manager.createBaseProgramInfo(tsconfigAbsPath, fs, {
1275
+ return project_paths.createBaseProgramInfo(tsconfigAbsPath, fs, {
1275
1276
  _compilePoisonedComponents: true,
1276
1277
  // We want to migrate non-exported classes too.
1277
1278
  compileNonExportedClasses: true,
@@ -1343,13 +1344,13 @@ class SignalInputMigration extends apply_import_manager.TsurgeComplexMigration {
1343
1344
  knownInputs,
1344
1345
  };
1345
1346
  }
1346
- return apply_import_manager.confirmAsSerializable(unitData);
1347
+ return project_paths.confirmAsSerializable(unitData);
1347
1348
  }
1348
1349
  async combine(unitA, unitB) {
1349
- return apply_import_manager.confirmAsSerializable(combineCompilationUnitData(unitA, unitB));
1350
+ return project_paths.confirmAsSerializable(combineCompilationUnitData(unitA, unitB));
1350
1351
  }
1351
1352
  async globalMeta(combinedData) {
1352
- return apply_import_manager.confirmAsSerializable(convertToGlobalMeta(combinedData));
1353
+ return project_paths.confirmAsSerializable(convertToGlobalMeta(combinedData));
1353
1354
  }
1354
1355
  async migrate(globalMetadata, info, nonBatchData) {
1355
1356
  const knownInputs = nonBatchData?.knownInputs ?? new KnownInputs(info, this.config);
@@ -1443,7 +1444,7 @@ function migrate(options) {
1443
1444
  if (!buildPaths.length && !testPaths.length) {
1444
1445
  throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run signal input migration.');
1445
1446
  }
1446
- const fs = new apply_import_manager.DevkitMigrationFilesystem(tree);
1447
+ const fs = new project_paths.DevkitMigrationFilesystem(tree);
1447
1448
  checker.setFileSystem(fs);
1448
1449
  const migration = new SignalInputMigration({
1449
1450
  bestEffortMode: options.bestEffortMode,
@@ -1475,7 +1476,7 @@ function migrate(options) {
1475
1476
  context.logger.info(``);
1476
1477
  context.logger.info(`Processing analysis data between targets..`);
1477
1478
  context.logger.info(``);
1478
- const combined = await apply_import_manager.synchronouslyCombineUnitData(migration, unitResults);
1479
+ const combined = await project_paths.synchronouslyCombineUnitData(migration, unitResults);
1479
1480
  if (combined === null) {
1480
1481
  context.logger.error('Migration failed unexpectedly with no analysis data');
1481
1482
  return;
@@ -1485,7 +1486,7 @@ function migrate(options) {
1485
1486
  for (const { info, tsconfigPath } of programInfos) {
1486
1487
  context.logger.info(`Migrating: ${tsconfigPath}..`);
1487
1488
  const { replacements } = await migration.migrate(globalMeta, info);
1488
- const changesPerFile = apply_import_manager.groupReplacementsByFile(replacements);
1489
+ const changesPerFile = project_paths.groupReplacementsByFile(replacements);
1489
1490
  for (const [file, changes] of changesPerFile) {
1490
1491
  if (!replacementsPerFile.has(file)) {
1491
1492
  replacementsPerFile.set(file, changes);