@angular/core 19.0.0-next.9 → 19.0.0-rc.1

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 +21183 -19410
  2. package/fesm2022/core.mjs.map +1 -1
  3. package/fesm2022/primitives/event-dispatch.mjs +71 -47
  4. package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
  5. package/fesm2022/primitives/signals.mjs +8 -6
  6. package/fesm2022/primitives/signals.mjs.map +1 -1
  7. package/fesm2022/rxjs-interop.mjs +90 -10
  8. package/fesm2022/rxjs-interop.mjs.map +1 -1
  9. package/fesm2022/testing.mjs +174 -113
  10. package/fesm2022/testing.mjs.map +1 -1
  11. package/index.d.ts +524 -92
  12. package/package.json +1 -1
  13. package/primitives/event-dispatch/index.d.ts +7 -4
  14. package/primitives/signals/index.d.ts +3 -1
  15. package/rxjs-interop/index.d.ts +35 -4
  16. package/schematics/bundles/{checker-3b2ea20f.js → checker-9ca42e51.js} +2303 -1006
  17. package/schematics/bundles/combine_units-a16385aa.js +1634 -0
  18. package/schematics/bundles/{compiler_host-b4ba5a28.js → compiler_host-31afa4ed.js} +8 -5
  19. package/schematics/bundles/control-flow-migration.js +3 -3
  20. package/schematics/bundles/explicit-standalone-flag.js +29 -9
  21. package/schematics/bundles/imports-4ac08251.js +1 -1
  22. package/schematics/bundles/inject-migration.js +222 -54
  23. package/schematics/bundles/leading_space-d190b83b.js +1 -1
  24. package/schematics/bundles/migrate_ts_type_references-b2a28742.js +1463 -0
  25. package/schematics/bundles/nodes-0e7d45ca.js +1 -1
  26. package/schematics/bundles/output-migration.js +575 -0
  27. package/schematics/bundles/pending-tasks.js +3 -3
  28. package/schematics/bundles/{program-6534a30a.js → program-71beec0b.js} +1385 -460
  29. package/schematics/bundles/project_tsconfig_paths-e9ccccbf.js +1 -1
  30. package/schematics/bundles/provide-initializer.js +179 -0
  31. package/schematics/bundles/route-lazy-loading.js +9 -4
  32. package/schematics/bundles/signal-input-migration.js +183 -311
  33. package/schematics/bundles/signal-queries-migration.js +404 -146
  34. package/schematics/bundles/signals.js +54 -0
  35. package/schematics/bundles/standalone-migration.js +29 -12
  36. package/schematics/collection.json +11 -0
  37. package/schematics/migrations.json +7 -1
  38. package/schematics/ng-generate/output-migration/schema.json +19 -0
  39. package/schematics/ng-generate/signal-queries-migration/schema.json +11 -0
  40. package/schematics/ng-generate/signals/schema.json +65 -0
  41. package/testing/index.d.ts +1 -1
  42. package/schematics/bundles/group_replacements-e1b5cbf8.js +0 -31571
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-next.9
3
+ * @license Angular v19.0.0-rc.1
4
4
  * (c) 2010-2024 Google LLC. https://angular.io/
5
5
  * License: MIT
6
6
  */
@@ -0,0 +1,575 @@
1
+ 'use strict';
2
+ /**
3
+ * @license Angular v19.0.0-rc.1
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 combine_units = require('./combine_units-a16385aa.js');
14
+ require('os');
15
+ var ts = require('typescript');
16
+ var checker = require('./checker-9ca42e51.js');
17
+ var assert = require('assert');
18
+ var program = require('./program-71beec0b.js');
19
+ require('path');
20
+ require('@angular-devkit/core');
21
+ require('node:path/posix');
22
+ require('fs');
23
+ require('module');
24
+ require('url');
25
+
26
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
27
+
28
+ var ts__default = /*#__PURE__*/_interopDefaultLegacy(ts);
29
+ var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert);
30
+
31
+ function isOutputDeclarationEligibleForMigration(node) {
32
+ return (node.initializer !== undefined &&
33
+ ts__default["default"].isNewExpression(node.initializer) &&
34
+ ts__default["default"].isIdentifier(node.initializer.expression) &&
35
+ node.initializer.expression.text === 'EventEmitter');
36
+ }
37
+ function isPotentialOutputCallUsage(node, name) {
38
+ if (ts__default["default"].isCallExpression(node) &&
39
+ ts__default["default"].isPropertyAccessExpression(node.expression) &&
40
+ ts__default["default"].isIdentifier(node.expression.name)) {
41
+ return node.expression?.name.text === name;
42
+ }
43
+ else {
44
+ return false;
45
+ }
46
+ }
47
+ function isPotentialPipeCallUsage(node) {
48
+ return isPotentialOutputCallUsage(node, 'pipe');
49
+ }
50
+ function isPotentialNextCallUsage(node) {
51
+ return isPotentialOutputCallUsage(node, 'next');
52
+ }
53
+ function isPotentialCompleteCallUsage(node) {
54
+ return isPotentialOutputCallUsage(node, 'complete');
55
+ }
56
+ function isTargetOutputDeclaration(node, checker, reflector, dtsReader) {
57
+ const targetSymbol = checker.getSymbolAtLocation(node);
58
+ if (targetSymbol !== undefined) {
59
+ const propertyDeclaration = getTargetPropertyDeclaration(targetSymbol);
60
+ if (propertyDeclaration !== null &&
61
+ isOutputDeclaration(propertyDeclaration, reflector, dtsReader)) {
62
+ return propertyDeclaration;
63
+ }
64
+ }
65
+ return null;
66
+ }
67
+ /** Gets whether the given property is an Angular `@Output`. */
68
+ function isOutputDeclaration(node, reflector, dtsReader) {
69
+ // `.d.ts` file, so we check the `static ecmp` metadata on the `declare class`.
70
+ if (node.getSourceFile().isDeclarationFile) {
71
+ if (!ts__default["default"].isIdentifier(node.name) ||
72
+ !ts__default["default"].isClassDeclaration(node.parent) ||
73
+ node.parent.name === undefined) {
74
+ return false;
75
+ }
76
+ const ref = new checker.Reference(node.parent);
77
+ const directiveMeta = dtsReader.getDirectiveMetadata(ref);
78
+ return !!directiveMeta?.outputs.getByClassPropertyName(node.name.text);
79
+ }
80
+ // `.ts` file, so we check for the `@Output()` decorator.
81
+ return getOutputDecorator(node, reflector) !== null;
82
+ }
83
+ function getTargetPropertyDeclaration(targetSymbol) {
84
+ const valDeclaration = targetSymbol.valueDeclaration;
85
+ if (valDeclaration !== undefined && ts__default["default"].isPropertyDeclaration(valDeclaration)) {
86
+ return valDeclaration;
87
+ }
88
+ return null;
89
+ }
90
+ /** Returns Angular `@Output` decorator or null when a given property declaration is not an @Output */
91
+ function getOutputDecorator(node, reflector) {
92
+ const decorators = reflector.getDecoratorsOfDeclaration(node);
93
+ const ngDecorators = decorators !== null ? checker.getAngularDecorators(decorators, ['Output'], /* isCore */ false) : [];
94
+ return ngDecorators.length > 0 ? ngDecorators[0] : null;
95
+ }
96
+ // THINK: this utility + type is not specific to @Output, really, maybe move it to tsurge?
97
+ /** Computes an unique ID for a given Angular `@Output` property. */
98
+ function getUniqueIdForProperty(info, prop) {
99
+ const { id } = combine_units.projectFile(prop.getSourceFile(), info);
100
+ id.replace(/\.d\.ts$/, '.ts');
101
+ return `${id}@@${prop.parent.name ?? 'unknown-class'}@@${prop.name.getText()}`;
102
+ }
103
+ function isTestRunnerImport(node) {
104
+ if (ts__default["default"].isImportDeclaration(node)) {
105
+ const moduleSpecifier = node.moduleSpecifier.getText();
106
+ return moduleSpecifier.includes('jasmine') || moduleSpecifier.includes('catalyst');
107
+ }
108
+ return false;
109
+ }
110
+ // TODO: code duplication with signals migration - sort it out
111
+ /**
112
+ * Gets whether the given read is used to access
113
+ * the specified field.
114
+ *
115
+ * E.g. whether `<my-read>.toArray` is detected.
116
+ */
117
+ function checkNonTsReferenceAccessesField(ref, fieldName) {
118
+ const readFromPath = ref.from.readAstPath.at(-1);
119
+ const parentRead = ref.from.readAstPath.at(-2);
120
+ if (ref.from.read !== readFromPath) {
121
+ return null;
122
+ }
123
+ if (!(parentRead instanceof checker.PropertyRead) || parentRead.name !== fieldName) {
124
+ return null;
125
+ }
126
+ return parentRead;
127
+ }
128
+ /**
129
+ * Gets whether the given reference is accessed to call the
130
+ * specified function on it.
131
+ *
132
+ * E.g. whether `<my-read>.toArray()` is detected.
133
+ */
134
+ function checkNonTsReferenceCallsField(ref, fieldName) {
135
+ const propertyAccess = checkNonTsReferenceAccessesField(ref, fieldName);
136
+ if (propertyAccess === null) {
137
+ return null;
138
+ }
139
+ const accessIdx = ref.from.readAstPath.indexOf(propertyAccess);
140
+ if (accessIdx === -1) {
141
+ return null;
142
+ }
143
+ const potentialRead = ref.from.readAstPath[accessIdx];
144
+ if (potentialRead === undefined) {
145
+ return null;
146
+ }
147
+ return potentialRead;
148
+ }
149
+
150
+ const printer = ts__default["default"].createPrinter();
151
+ function calculateDeclarationReplacement(info, node, aliasParam) {
152
+ const sf = node.getSourceFile();
153
+ const payloadTypes = node.initializer !== undefined && ts__default["default"].isNewExpression(node.initializer)
154
+ ? node.initializer?.typeArguments
155
+ : undefined;
156
+ const outputCall = ts__default["default"].factory.createCallExpression(ts__default["default"].factory.createIdentifier('output'), payloadTypes, aliasParam !== undefined
157
+ ? [
158
+ ts__default["default"].factory.createObjectLiteralExpression([
159
+ ts__default["default"].factory.createPropertyAssignment('alias', ts__default["default"].factory.createStringLiteral(aliasParam, true)),
160
+ ], false),
161
+ ]
162
+ : []);
163
+ const existingModifiers = (node.modifiers ?? []).filter((modifier) => !ts__default["default"].isDecorator(modifier) && modifier.kind !== ts__default["default"].SyntaxKind.ReadonlyKeyword);
164
+ const updatedOutputDeclaration = ts__default["default"].factory.createPropertyDeclaration(
165
+ // Think: this logic of dealing with modifiers is applicable to all signal-based migrations
166
+ ts__default["default"].factory.createNodeArray([
167
+ ...existingModifiers,
168
+ ts__default["default"].factory.createModifier(ts__default["default"].SyntaxKind.ReadonlyKeyword),
169
+ ]), node.name, undefined, undefined, outputCall);
170
+ return prepareTextReplacementForNode(info, node, printer.printNode(ts__default["default"].EmitHint.Unspecified, updatedOutputDeclaration, sf));
171
+ }
172
+ function calculateImportReplacements(info, sourceFiles) {
173
+ const importReplacements = {};
174
+ for (const sf of sourceFiles) {
175
+ const importManager = new checker.ImportManager();
176
+ const addOnly = [];
177
+ const addRemove = [];
178
+ const file = combine_units.projectFile(sf, info);
179
+ importManager.addImport({
180
+ requestedFile: sf,
181
+ exportModuleSpecifier: '@angular/core',
182
+ exportSymbolName: 'output',
183
+ });
184
+ combine_units.applyImportManagerChanges(importManager, addOnly, [sf], info);
185
+ importManager.removeImport(sf, 'Output', '@angular/core');
186
+ importManager.removeImport(sf, 'EventEmitter', '@angular/core');
187
+ combine_units.applyImportManagerChanges(importManager, addRemove, [sf], info);
188
+ importReplacements[file.id] = {
189
+ add: addOnly,
190
+ addAndRemove: addRemove,
191
+ };
192
+ }
193
+ return importReplacements;
194
+ }
195
+ function calculateNextFnReplacement(info, node) {
196
+ return prepareTextReplacementForNode(info, node, 'emit');
197
+ }
198
+ function calculateNextFnReplacementInTemplate(file, span) {
199
+ return prepareTextReplacement(file, 'emit', span.start, span.end);
200
+ }
201
+ function calculateNextFnReplacementInHostBinding(file, offset, span) {
202
+ return prepareTextReplacement(file, 'emit', offset + span.start, offset + span.end);
203
+ }
204
+ function calculateCompleteCallReplacement(info, node) {
205
+ return prepareTextReplacementForNode(info, node, '', node.getFullStart());
206
+ }
207
+ function calculatePipeCallReplacement(info, node) {
208
+ if (ts__default["default"].isPropertyAccessExpression(node.expression)) {
209
+ const sf = node.getSourceFile();
210
+ const importManager = new checker.ImportManager();
211
+ const outputToObservableIdent = importManager.addImport({
212
+ requestedFile: sf,
213
+ exportModuleSpecifier: '@angular/core/rxjs-interop',
214
+ exportSymbolName: 'outputToObservable',
215
+ });
216
+ const toObsCallExp = ts__default["default"].factory.createCallExpression(outputToObservableIdent, undefined, [
217
+ node.expression.expression,
218
+ ]);
219
+ const pipePropAccessExp = ts__default["default"].factory.updatePropertyAccessExpression(node.expression, toObsCallExp, node.expression.name);
220
+ const pipeCallExp = ts__default["default"].factory.updateCallExpression(node, pipePropAccessExp, [], node.arguments);
221
+ const replacements = [
222
+ prepareTextReplacementForNode(info, node, printer.printNode(ts__default["default"].EmitHint.Unspecified, pipeCallExp, sf)),
223
+ ];
224
+ combine_units.applyImportManagerChanges(importManager, replacements, [sf], info);
225
+ return replacements;
226
+ }
227
+ else {
228
+ // TODO: assert instead?
229
+ throw new Error(`Unexpected call expression for .pipe - expected a property access but got "${node.getText()}"`);
230
+ }
231
+ }
232
+ function prepareTextReplacementForNode(info, node, replacement, start) {
233
+ const sf = node.getSourceFile();
234
+ return new combine_units.Replacement(combine_units.projectFile(sf, info), new combine_units.TextUpdate({
235
+ position: start ?? node.getStart(),
236
+ end: node.getEnd(),
237
+ toInsert: replacement,
238
+ }));
239
+ }
240
+ function prepareTextReplacement(file, replacement, start, end) {
241
+ return new combine_units.Replacement(file, new combine_units.TextUpdate({
242
+ position: start,
243
+ end: end,
244
+ toInsert: replacement,
245
+ }));
246
+ }
247
+
248
+ class OutputMigration extends combine_units.TsurgeFunnelMigration {
249
+ config;
250
+ constructor(config = {}) {
251
+ super();
252
+ this.config = config;
253
+ }
254
+ async analyze(info) {
255
+ const { sourceFiles, program: program$1 } = info;
256
+ const outputFieldReplacements = {};
257
+ const problematicUsages = {};
258
+ let problematicDeclarationCount = 0;
259
+ const filesWithOutputDeclarations = new Set();
260
+ const checker$1 = program$1.getTypeChecker();
261
+ const reflector = new checker.TypeScriptReflectionHost(checker$1);
262
+ const dtsReader = new program.DtsMetadataReader(checker$1, reflector);
263
+ const evaluator = new program.PartialEvaluator(reflector, checker$1, null);
264
+ const ngCompiler = info.ngCompiler;
265
+ assert__default["default"](ngCompiler !== null, 'Requires ngCompiler to run the migration');
266
+ const resourceLoader = ngCompiler['resourceManager'];
267
+ // Pre-Analyze the program and get access to the template type checker.
268
+ const { templateTypeChecker } = ngCompiler['ensureAnalyzed']();
269
+ const knownFields = {
270
+ // Note: We don't support cross-target migration of `Partial<T>` usages.
271
+ // This is an acceptable limitation for performance reasons.
272
+ shouldTrackClassReference: (node) => false,
273
+ attemptRetrieveDescriptorFromSymbol: (s) => {
274
+ const propDeclaration = getTargetPropertyDeclaration(s);
275
+ if (propDeclaration !== null) {
276
+ const classFieldID = getUniqueIdForProperty(info, propDeclaration);
277
+ if (classFieldID !== null) {
278
+ return {
279
+ node: propDeclaration,
280
+ key: classFieldID,
281
+ };
282
+ }
283
+ }
284
+ return null;
285
+ },
286
+ };
287
+ let isTestFile = false;
288
+ const outputMigrationVisitor = (node) => {
289
+ // detect output declarations
290
+ if (ts__default["default"].isPropertyDeclaration(node)) {
291
+ const outputDecorator = getOutputDecorator(node, reflector);
292
+ if (outputDecorator !== null) {
293
+ if (isOutputDeclarationEligibleForMigration(node)) {
294
+ const outputDef = {
295
+ id: getUniqueIdForProperty(info, node),
296
+ aliasParam: outputDecorator.args?.at(0),
297
+ };
298
+ const outputFile = combine_units.projectFile(node.getSourceFile(), info);
299
+ if (this.config.shouldMigrate === undefined ||
300
+ this.config.shouldMigrate({
301
+ key: outputDef.id,
302
+ node: node,
303
+ }, outputFile)) {
304
+ const aliasParam = outputDef.aliasParam;
305
+ const aliasOptionValue = aliasParam ? evaluator.evaluate(aliasParam) : undefined;
306
+ if (aliasOptionValue == undefined || typeof aliasOptionValue === 'string') {
307
+ filesWithOutputDeclarations.add(node.getSourceFile());
308
+ addOutputReplacement(outputFieldReplacements, outputDef.id, outputFile, calculateDeclarationReplacement(info, node, aliasOptionValue?.toString()));
309
+ }
310
+ else {
311
+ problematicUsages[outputDef.id] = true;
312
+ problematicDeclarationCount++;
313
+ }
314
+ }
315
+ }
316
+ else {
317
+ problematicDeclarationCount++;
318
+ }
319
+ }
320
+ }
321
+ // detect .next usages that should be migrated to .emit
322
+ if (isPotentialNextCallUsage(node) && ts__default["default"].isPropertyAccessExpression(node.expression)) {
323
+ const propertyDeclaration = isTargetOutputDeclaration(node.expression.expression, checker$1, reflector, dtsReader);
324
+ if (propertyDeclaration !== null) {
325
+ const id = getUniqueIdForProperty(info, propertyDeclaration);
326
+ const outputFile = combine_units.projectFile(node.getSourceFile(), info);
327
+ addOutputReplacement(outputFieldReplacements, id, outputFile, calculateNextFnReplacement(info, node.expression.name));
328
+ }
329
+ }
330
+ // detect .complete usages that should be removed
331
+ if (isPotentialCompleteCallUsage(node) && ts__default["default"].isPropertyAccessExpression(node.expression)) {
332
+ const propertyDeclaration = isTargetOutputDeclaration(node.expression.expression, checker$1, reflector, dtsReader);
333
+ if (propertyDeclaration !== null) {
334
+ const id = getUniqueIdForProperty(info, propertyDeclaration);
335
+ const outputFile = combine_units.projectFile(node.getSourceFile(), info);
336
+ if (ts__default["default"].isExpressionStatement(node.parent)) {
337
+ addOutputReplacement(outputFieldReplacements, id, outputFile, calculateCompleteCallReplacement(info, node.parent));
338
+ }
339
+ else {
340
+ problematicUsages[id] = true;
341
+ }
342
+ }
343
+ }
344
+ // detect imports of test runners
345
+ if (isTestRunnerImport(node)) {
346
+ isTestFile = true;
347
+ }
348
+ // detect unsafe access of the output property
349
+ if (isPotentialPipeCallUsage(node) && ts__default["default"].isPropertyAccessExpression(node.expression)) {
350
+ const propertyDeclaration = isTargetOutputDeclaration(node.expression.expression, checker$1, reflector, dtsReader);
351
+ if (propertyDeclaration !== null) {
352
+ const id = getUniqueIdForProperty(info, propertyDeclaration);
353
+ if (isTestFile) {
354
+ const outputFile = combine_units.projectFile(node.getSourceFile(), info);
355
+ addOutputReplacement(outputFieldReplacements, id, outputFile, ...calculatePipeCallReplacement(info, node));
356
+ }
357
+ else {
358
+ problematicUsages[id] = true;
359
+ }
360
+ }
361
+ }
362
+ ts__default["default"].forEachChild(node, outputMigrationVisitor);
363
+ };
364
+ // calculate output migration replacements
365
+ for (const sf of sourceFiles) {
366
+ isTestFile = false;
367
+ ts__default["default"].forEachChild(sf, outputMigrationVisitor);
368
+ }
369
+ // take care of the references in templates and host bindings
370
+ const referenceResult = { references: [] };
371
+ const { visitor: templateHostRefVisitor } = combine_units.createFindAllSourceFileReferencesVisitor(info, checker$1, reflector, resourceLoader, evaluator, templateTypeChecker, knownFields, null, // TODO: capture known output names as an optimization
372
+ referenceResult);
373
+ // calculate template / host binding replacements
374
+ for (const sf of sourceFiles) {
375
+ ts__default["default"].forEachChild(sf, templateHostRefVisitor);
376
+ }
377
+ for (const ref of referenceResult.references) {
378
+ // detect .next usages that should be migrated to .emit in template and host binding expressions
379
+ if (ref.kind === combine_units.ReferenceKind.InTemplate) {
380
+ const callExpr = checkNonTsReferenceCallsField(ref, 'next');
381
+ if (callExpr !== null) {
382
+ addOutputReplacement(outputFieldReplacements, ref.target.key, ref.from.templateFile, calculateNextFnReplacementInTemplate(ref.from.templateFile, callExpr.nameSpan));
383
+ }
384
+ }
385
+ else if (ref.kind === combine_units.ReferenceKind.InHostBinding) {
386
+ const callExpr = checkNonTsReferenceCallsField(ref, 'next');
387
+ if (callExpr !== null) {
388
+ addOutputReplacement(outputFieldReplacements, ref.target.key, ref.from.file, calculateNextFnReplacementInHostBinding(ref.from.file, ref.from.hostPropertyNode.getStart() + 1, callExpr.nameSpan));
389
+ }
390
+ }
391
+ }
392
+ // calculate import replacements but do so only for files that have output declarations
393
+ const importReplacements = calculateImportReplacements(info, filesWithOutputDeclarations);
394
+ return combine_units.confirmAsSerializable({
395
+ problematicDeclarationCount,
396
+ outputFields: outputFieldReplacements,
397
+ importReplacements,
398
+ problematicUsages,
399
+ });
400
+ }
401
+ async combine(unitA, unitB) {
402
+ const outputFields = {};
403
+ const importReplacements = {};
404
+ const problematicUsages = {};
405
+ let problematicDeclarationCount = 0;
406
+ for (const unit of [unitA, unitB]) {
407
+ for (const declIdStr of Object.keys(unit.outputFields)) {
408
+ const declId = declIdStr;
409
+ // THINK: detect clash? Should we have an utility to merge data based on unique IDs?
410
+ outputFields[declId] = unit.outputFields[declId];
411
+ }
412
+ for (const fileIDStr of Object.keys(unit.importReplacements)) {
413
+ const fileID = fileIDStr;
414
+ importReplacements[fileID] = unit.importReplacements[fileID];
415
+ }
416
+ problematicDeclarationCount += unit.problematicDeclarationCount;
417
+ }
418
+ for (const unit of [unitA, unitB]) {
419
+ for (const declIdStr of Object.keys(unit.problematicUsages)) {
420
+ const declId = declIdStr;
421
+ problematicUsages[declId] = unit.problematicUsages[declId];
422
+ }
423
+ }
424
+ return combine_units.confirmAsSerializable({
425
+ problematicDeclarationCount,
426
+ outputFields,
427
+ importReplacements,
428
+ problematicUsages,
429
+ });
430
+ }
431
+ async globalMeta(combinedData) {
432
+ const globalMeta = {
433
+ importReplacements: combinedData.importReplacements,
434
+ outputFields: combinedData.outputFields,
435
+ problematicDeclarationCount: combinedData.problematicDeclarationCount,
436
+ problematicUsages: {},
437
+ };
438
+ for (const keyStr of Object.keys(combinedData.problematicUsages)) {
439
+ const key = keyStr;
440
+ // it might happen that a problematic usage is detected but we didn't see the declaration - skipping those
441
+ if (globalMeta.outputFields[key] !== undefined) {
442
+ globalMeta.problematicUsages[key] = true;
443
+ }
444
+ }
445
+ // Noop here as we don't have any form of special global metadata.
446
+ return combine_units.confirmAsSerializable(combinedData);
447
+ }
448
+ async stats(globalMetadata) {
449
+ const detectedOutputs = new Set(Object.keys(globalMetadata.outputFields)).size +
450
+ globalMetadata.problematicDeclarationCount;
451
+ const problematicOutputs = new Set(Object.keys(globalMetadata.problematicUsages)).size +
452
+ globalMetadata.problematicDeclarationCount;
453
+ const successRate = detectedOutputs > 0 ? (detectedOutputs - problematicOutputs) / detectedOutputs : 1;
454
+ return {
455
+ counters: {
456
+ detectedOutputs,
457
+ problematicOutputs,
458
+ successRate,
459
+ },
460
+ };
461
+ }
462
+ async migrate(globalData) {
463
+ const migratedFiles = new Set();
464
+ const problematicFiles = new Set();
465
+ const replacements = [];
466
+ for (const declIdStr of Object.keys(globalData.outputFields)) {
467
+ const declId = declIdStr;
468
+ const outputField = globalData.outputFields[declId];
469
+ if (!globalData.problematicUsages[declId]) {
470
+ replacements.push(...outputField.replacements);
471
+ migratedFiles.add(outputField.file.id);
472
+ }
473
+ else {
474
+ problematicFiles.add(outputField.file.id);
475
+ }
476
+ }
477
+ for (const fileIDStr of Object.keys(globalData.importReplacements)) {
478
+ const fileID = fileIDStr;
479
+ if (migratedFiles.has(fileID)) {
480
+ const importReplacements = globalData.importReplacements[fileID];
481
+ if (problematicFiles.has(fileID)) {
482
+ replacements.push(...importReplacements.add);
483
+ }
484
+ else {
485
+ replacements.push(...importReplacements.addAndRemove);
486
+ }
487
+ }
488
+ }
489
+ return { replacements };
490
+ }
491
+ }
492
+ function addOutputReplacement(outputFieldReplacements, outputId, file, ...replacements) {
493
+ let existingReplacements = outputFieldReplacements[outputId];
494
+ if (existingReplacements === undefined) {
495
+ outputFieldReplacements[outputId] = existingReplacements = {
496
+ file: file,
497
+ replacements: [],
498
+ };
499
+ }
500
+ existingReplacements.replacements.push(...replacements);
501
+ }
502
+
503
+ function migrate(options) {
504
+ return async (tree, context) => {
505
+ const { buildPaths, testPaths } = await project_tsconfig_paths.getProjectTsConfigPaths(tree);
506
+ if (!buildPaths.length && !testPaths.length) {
507
+ throw new schematics.SchematicsException('Could not find any tsconfig file. Cannot run output migration.');
508
+ }
509
+ const fs = new combine_units.DevkitMigrationFilesystem(tree);
510
+ checker.setFileSystem(fs);
511
+ const migration = new OutputMigration({
512
+ shouldMigrate: (_, file) => {
513
+ return (file.rootRelativePath.startsWith(fs.normalize(options.path)) &&
514
+ !/(^|\/)node_modules\//.test(file.rootRelativePath));
515
+ },
516
+ });
517
+ const analysisPath = fs.resolve(options.analysisDir);
518
+ const unitResults = [];
519
+ const programInfos = [...buildPaths, ...testPaths].map((tsconfigPath) => {
520
+ context.logger.info(`Preparing analysis for: ${tsconfigPath}..`);
521
+ const baseInfo = migration.createProgram(tsconfigPath, fs);
522
+ const info = migration.prepareProgram(baseInfo);
523
+ // Support restricting the analysis to subfolders for larger projects.
524
+ if (analysisPath !== '/') {
525
+ info.sourceFiles = info.sourceFiles.filter((sf) => sf.fileName.startsWith(analysisPath));
526
+ info.fullProgramSourceFiles = info.fullProgramSourceFiles.filter((sf) => sf.fileName.startsWith(analysisPath));
527
+ }
528
+ return { info, tsconfigPath };
529
+ });
530
+ // Analyze phase. Treat all projects as compilation units as
531
+ // this allows us to support references between those.
532
+ for (const { info, tsconfigPath } of programInfos) {
533
+ context.logger.info(`Scanning for outputs: ${tsconfigPath}..`);
534
+ unitResults.push(await migration.analyze(info));
535
+ }
536
+ context.logger.info(``);
537
+ context.logger.info(`Processing analysis data between targets..`);
538
+ context.logger.info(``);
539
+ const combined = await combine_units.synchronouslyCombineUnitData(migration, unitResults);
540
+ if (combined === null) {
541
+ context.logger.error('Migration failed unexpectedly with no analysis data');
542
+ return;
543
+ }
544
+ const globalMeta = await migration.globalMeta(combined);
545
+ const replacementsPerFile = new Map();
546
+ for (const { info, tsconfigPath } of programInfos) {
547
+ context.logger.info(`Migrating: ${tsconfigPath}..`);
548
+ const { replacements } = await migration.migrate(globalMeta);
549
+ const changesPerFile = combine_units.groupReplacementsByFile(replacements);
550
+ for (const [file, changes] of changesPerFile) {
551
+ if (!replacementsPerFile.has(file)) {
552
+ replacementsPerFile.set(file, changes);
553
+ }
554
+ }
555
+ }
556
+ context.logger.info(`Applying changes..`);
557
+ for (const [file, changes] of replacementsPerFile) {
558
+ const recorder = tree.beginUpdate(file);
559
+ for (const c of changes) {
560
+ recorder
561
+ .remove(c.data.position, c.data.end - c.data.position)
562
+ .insertLeft(c.data.position, c.data.toInsert);
563
+ }
564
+ tree.commitUpdate(recorder);
565
+ }
566
+ const { counters: { detectedOutputs, problematicOutputs, successRate }, } = await migration.stats(globalMeta);
567
+ const migratedOutputs = detectedOutputs - problematicOutputs;
568
+ const successRatePercent = (successRate * 100).toFixed(2);
569
+ context.logger.info('');
570
+ context.logger.info(`Successfully migrated to outputs as functions 🎉`);
571
+ context.logger.info(` -> Migrated ${migratedOutputs} out of ${detectedOutputs} detected outputs (${successRatePercent} %).`);
572
+ };
573
+ }
574
+
575
+ exports.migrate = migrate;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
  /**
3
- * @license Angular v19.0.0-next.9
3
+ * @license Angular v19.0.0-rc.1
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-b4ba5a28.js');
14
+ var compiler_host = require('./compiler_host-31afa4ed.js');
15
15
  var ts = require('typescript');
16
16
  var imports = require('./imports-4ac08251.js');
17
17
  require('@angular-devkit/core');
18
- require('./checker-3b2ea20f.js');
18
+ require('./checker-9ca42e51.js');
19
19
  require('os');
20
20
  require('fs');
21
21
  require('module');