@openrewrite/recipes-angular 1.1.3 → 1.1.5

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 (124) hide show
  1. package/dist/index.d.ts +18 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +76 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/libraries/primeng/18/add-primeng-provider.d.ts +45 -0
  6. package/dist/libraries/primeng/18/add-primeng-provider.d.ts.map +1 -0
  7. package/dist/libraries/primeng/18/add-primeng-provider.js +354 -0
  8. package/dist/libraries/primeng/18/add-primeng-provider.js.map +1 -0
  9. package/dist/libraries/primeng/18/index.d.ts +19 -0
  10. package/dist/libraries/primeng/18/index.d.ts.map +1 -0
  11. package/dist/libraries/primeng/18/index.js +45 -0
  12. package/dist/libraries/primeng/18/index.js.map +1 -0
  13. package/dist/libraries/primeng/18/manual-migration-steps.d.ts +19 -0
  14. package/dist/libraries/primeng/18/manual-migration-steps.d.ts.map +1 -0
  15. package/dist/libraries/primeng/18/manual-migration-steps.js +45 -0
  16. package/dist/libraries/primeng/18/manual-migration-steps.js.map +1 -0
  17. package/dist/libraries/primeng/18/mark-deprecated-components.d.ts +9 -0
  18. package/dist/libraries/primeng/18/mark-deprecated-components.d.ts.map +1 -0
  19. package/dist/libraries/primeng/18/mark-deprecated-components.js +125 -0
  20. package/dist/libraries/primeng/18/mark-deprecated-components.js.map +1 -0
  21. package/dist/libraries/primeng/18/mark-deprecated-css-classes.d.ts +15 -0
  22. package/dist/libraries/primeng/18/mark-deprecated-css-classes.d.ts.map +1 -0
  23. package/dist/libraries/primeng/18/mark-deprecated-css-classes.js +108 -0
  24. package/dist/libraries/primeng/18/mark-deprecated-css-classes.js.map +1 -0
  25. package/dist/libraries/primeng/18/mark-drawer-size.d.ts +16 -0
  26. package/dist/libraries/primeng/18/mark-drawer-size.d.ts.map +1 -0
  27. package/dist/libraries/primeng/18/mark-drawer-size.js +90 -0
  28. package/dist/libraries/primeng/18/mark-drawer-size.js.map +1 -0
  29. package/dist/libraries/primeng/18/mark-removed-primeng-modules.d.ts +9 -0
  30. package/dist/libraries/primeng/18/mark-removed-primeng-modules.d.ts.map +1 -0
  31. package/dist/libraries/primeng/18/mark-removed-primeng-modules.js +186 -0
  32. package/dist/libraries/primeng/18/mark-removed-primeng-modules.js.map +1 -0
  33. package/dist/libraries/primeng/18/migrate-messages-to-message-loop.d.ts +15 -0
  34. package/dist/libraries/primeng/18/migrate-messages-to-message-loop.d.ts.map +1 -0
  35. package/dist/libraries/primeng/18/migrate-messages-to-message-loop.js +78 -0
  36. package/dist/libraries/primeng/18/migrate-messages-to-message-loop.js.map +1 -0
  37. package/dist/libraries/primeng/18/migrate-p-fluid-to-wrapper.d.ts +27 -0
  38. package/dist/libraries/primeng/18/migrate-p-fluid-to-wrapper.d.ts.map +1 -0
  39. package/dist/libraries/primeng/18/migrate-p-fluid-to-wrapper.js +495 -0
  40. package/dist/libraries/primeng/18/migrate-p-fluid-to-wrapper.js.map +1 -0
  41. package/dist/libraries/primeng/18/migrate-primeng-config.d.ts +8 -0
  42. package/dist/libraries/primeng/18/migrate-primeng-config.d.ts.map +1 -0
  43. package/dist/libraries/primeng/18/migrate-primeng-config.js +154 -0
  44. package/dist/libraries/primeng/18/migrate-primeng-config.js.map +1 -0
  45. package/dist/libraries/primeng/18/migrate-primeng-signal-assignments.d.ts +12 -0
  46. package/dist/libraries/primeng/18/migrate-primeng-signal-assignments.d.ts.map +1 -0
  47. package/dist/libraries/primeng/18/migrate-primeng-signal-assignments.js +112 -0
  48. package/dist/libraries/primeng/18/migrate-primeng-signal-assignments.js.map +1 -0
  49. package/dist/libraries/primeng/18/rename-calendar-to-datepicker.d.ts +8 -0
  50. package/dist/libraries/primeng/18/rename-calendar-to-datepicker.d.ts.map +1 -0
  51. package/dist/libraries/primeng/18/rename-calendar-to-datepicker.js +114 -0
  52. package/dist/libraries/primeng/18/rename-calendar-to-datepicker.js.map +1 -0
  53. package/dist/libraries/primeng/18/rename-dropdown-to-select.d.ts +8 -0
  54. package/dist/libraries/primeng/18/rename-dropdown-to-select.d.ts.map +1 -0
  55. package/dist/libraries/primeng/18/rename-dropdown-to-select.js +114 -0
  56. package/dist/libraries/primeng/18/rename-dropdown-to-select.js.map +1 -0
  57. package/dist/libraries/primeng/18/rename-inputswitch-to-toggleswitch.d.ts +8 -0
  58. package/dist/libraries/primeng/18/rename-inputswitch-to-toggleswitch.d.ts.map +1 -0
  59. package/dist/libraries/primeng/18/rename-inputswitch-to-toggleswitch.js +114 -0
  60. package/dist/libraries/primeng/18/rename-inputswitch-to-toggleswitch.js.map +1 -0
  61. package/dist/libraries/primeng/18/rename-message-interface.d.ts +8 -0
  62. package/dist/libraries/primeng/18/rename-message-interface.d.ts.map +1 -0
  63. package/dist/libraries/primeng/18/rename-message-interface.js +107 -0
  64. package/dist/libraries/primeng/18/rename-message-interface.js.map +1 -0
  65. package/dist/libraries/primeng/18/rename-overlaypanel-to-popover.d.ts +8 -0
  66. package/dist/libraries/primeng/18/rename-overlaypanel-to-popover.d.ts.map +1 -0
  67. package/dist/libraries/primeng/18/rename-overlaypanel-to-popover.js +114 -0
  68. package/dist/libraries/primeng/18/rename-overlaypanel-to-popover.js.map +1 -0
  69. package/dist/libraries/primeng/18/rename-sidebar-to-drawer.d.ts +8 -0
  70. package/dist/libraries/primeng/18/rename-sidebar-to-drawer.d.ts.map +1 -0
  71. package/dist/libraries/primeng/18/rename-sidebar-to-drawer.js +114 -0
  72. package/dist/libraries/primeng/18/rename-sidebar-to-drawer.js.map +1 -0
  73. package/dist/libraries/primeng/18/rename-template-selectors.d.ts +12 -0
  74. package/dist/libraries/primeng/18/rename-template-selectors.d.ts.map +1 -0
  75. package/dist/libraries/primeng/18/rename-template-selectors.js +79 -0
  76. package/dist/libraries/primeng/18/rename-template-selectors.js.map +1 -0
  77. package/dist/libraries/primeng/18/upgrade-components-to-18.d.ts +8 -0
  78. package/dist/libraries/primeng/18/upgrade-components-to-18.d.ts.map +1 -0
  79. package/dist/libraries/primeng/18/upgrade-components-to-18.js +73 -0
  80. package/dist/libraries/primeng/18/upgrade-components-to-18.js.map +1 -0
  81. package/dist/libraries/primeng/18/upgrade-to-primeng-18.d.ts +8 -0
  82. package/dist/libraries/primeng/18/upgrade-to-primeng-18.d.ts.map +1 -0
  83. package/dist/libraries/primeng/18/upgrade-to-primeng-18.js +68 -0
  84. package/dist/libraries/primeng/18/upgrade-to-primeng-18.js.map +1 -0
  85. package/dist/migration/explicit-standalone-flag.d.ts.map +1 -1
  86. package/dist/migration/explicit-standalone-flag.js +12 -5
  87. package/dist/migration/explicit-standalone-flag.js.map +1 -1
  88. package/dist/migration/replace-untyped-forms.d.ts +14 -2
  89. package/dist/migration/replace-untyped-forms.d.ts.map +1 -1
  90. package/dist/migration/replace-untyped-forms.js +108 -36
  91. package/dist/migration/replace-untyped-forms.js.map +1 -1
  92. package/dist/migration/upgrade-angular-peer-libs-to-18.d.ts +17 -0
  93. package/dist/migration/upgrade-angular-peer-libs-to-18.d.ts.map +1 -0
  94. package/dist/migration/upgrade-angular-peer-libs-to-18.js +49 -0
  95. package/dist/migration/upgrade-angular-peer-libs-to-18.js.map +1 -0
  96. package/dist/migration/upgrade-to-angular-18.d.ts.map +1 -1
  97. package/dist/migration/upgrade-to-angular-18.js +16 -7
  98. package/dist/migration/upgrade-to-angular-18.js.map +1 -1
  99. package/package.json +1 -1
  100. package/src/index.ts +57 -0
  101. package/src/libraries/primeng/18/add-primeng-provider.ts +359 -0
  102. package/src/libraries/primeng/18/index.ts +24 -0
  103. package/src/libraries/primeng/18/manual-migration-steps.ts +37 -0
  104. package/src/libraries/primeng/18/mark-deprecated-components.ts +128 -0
  105. package/src/libraries/primeng/18/mark-deprecated-css-classes.ts +109 -0
  106. package/src/libraries/primeng/18/mark-drawer-size.ts +85 -0
  107. package/src/libraries/primeng/18/mark-removed-primeng-modules.ts +198 -0
  108. package/src/libraries/primeng/18/migrate-messages-to-message-loop.ts +72 -0
  109. package/src/libraries/primeng/18/migrate-p-fluid-to-wrapper.ts +439 -0
  110. package/src/libraries/primeng/18/migrate-primeng-config.ts +112 -0
  111. package/src/libraries/primeng/18/migrate-primeng-signal-assignments.ts +83 -0
  112. package/src/libraries/primeng/18/rename-calendar-to-datepicker.ts +81 -0
  113. package/src/libraries/primeng/18/rename-dropdown-to-select.ts +81 -0
  114. package/src/libraries/primeng/18/rename-inputswitch-to-toggleswitch.ts +81 -0
  115. package/src/libraries/primeng/18/rename-message-interface.ts +78 -0
  116. package/src/libraries/primeng/18/rename-overlaypanel-to-popover.ts +81 -0
  117. package/src/libraries/primeng/18/rename-sidebar-to-drawer.ts +81 -0
  118. package/src/libraries/primeng/18/rename-template-selectors.ts +63 -0
  119. package/src/libraries/primeng/18/upgrade-components-to-18.ts +57 -0
  120. package/src/libraries/primeng/18/upgrade-to-primeng-18.ts +52 -0
  121. package/src/migration/explicit-standalone-flag.ts +11 -5
  122. package/src/migration/replace-untyped-forms.ts +111 -39
  123. package/src/migration/upgrade-angular-peer-libs-to-18.ts +33 -0
  124. package/src/migration/upgrade-to-angular-18.ts +16 -7
@@ -35,18 +35,22 @@ export class ExplicitStandaloneFlag extends Recipe {
35
35
 
36
36
  let standaloneIndex = -1;
37
37
  let standaloneValue: boolean | null = null;
38
+ let hasImplicitStandaloneProp = false;
38
39
 
39
40
  for (let i = 0; i < newClass.body.statements.length; i++) {
40
41
  const stmt = newClass.body.statements[i].element;
41
42
  if (stmt.kind === JS.Kind.PropertyAssignment) {
42
43
  const prop = stmt as JS.PropertyAssignment;
43
44
  const nameExpr = prop.name.element;
44
- if (isIdentifier(nameExpr) && nameExpr.simpleName === 'standalone') {
45
- standaloneIndex = i;
46
- if (prop.initializer && isLiteral(prop.initializer)) {
47
- standaloneValue = prop.initializer.value as boolean;
45
+ if (isIdentifier(nameExpr)) {
46
+ if (nameExpr.simpleName === 'standalone') {
47
+ standaloneIndex = i;
48
+ if (prop.initializer && isLiteral(prop.initializer)) {
49
+ standaloneValue = prop.initializer.value as boolean;
50
+ }
51
+ } else if (annotType.simpleName === 'Component' && nameExpr.simpleName === 'imports') {
52
+ hasImplicitStandaloneProp = true;
48
53
  }
49
- break;
50
54
  }
51
55
  }
52
56
  }
@@ -59,6 +63,8 @@ export class ExplicitStandaloneFlag extends Recipe {
59
63
  }
60
64
 
61
65
  if (standaloneIndex === -1) {
66
+ if (hasImplicitStandaloneProp) return a;
67
+
62
68
  const existingStmts = newClass.body.statements;
63
69
  if (existingStmts.length === 0) return a;
64
70
 
@@ -4,56 +4,128 @@
4
4
  * Moderne Proprietary. Only for use by Moderne customers under the terms of a commercial contract.
5
5
  */
6
6
 
7
- import {ExecutionContext, Recipe, TreeVisitor} from "@openrewrite/rewrite";
8
- import {ChangeImport, JavaScriptVisitor} from "@openrewrite/rewrite/javascript";
7
+ import {Cursor, ExecutionContext, produceAsync, Recipe, Tree, TreeVisitor} from "@openrewrite/rewrite";
8
+ import {JavaScriptVisitor, JS} from "@openrewrite/rewrite/javascript";
9
9
  import {J, isIdentifier} from "@openrewrite/rewrite/java";
10
- import {create} from "mutative";
11
10
 
12
11
  const MODULE = '@angular/forms';
13
12
 
14
- const FORM_RENAMES: [string, string][] = [
15
- ['FormControl', 'UntypedFormControl'],
16
- ['FormGroup', 'UntypedFormGroup'],
17
- ['FormArray', 'UntypedFormArray'],
18
- ['FormBuilder', 'UntypedFormBuilder'],
19
- ];
13
+ const RENAMES: Record<string, string> = {
14
+ FormControl: 'UntypedFormControl',
15
+ FormGroup: 'UntypedFormGroup',
16
+ FormArray: 'UntypedFormArray',
17
+ FormBuilder: 'UntypedFormBuilder',
18
+ };
20
19
 
21
- class RenameFormIdentifiers extends Recipe {
22
- readonly name = "org.openrewrite.angular.migration.replace-untyped-forms.rename-identifiers";
23
- readonly displayName: string = "Rename form identifiers to untyped variants";
24
- readonly description: string = "Renames form class identifiers in code usages.";
20
+ /**
21
+ * Renames `FormControl`, `FormGroup`, `FormArray`, and `FormBuilder` (from `@angular/forms`)
22
+ * to their `Untyped*` equivalents both the named-import specifiers and every identifier
23
+ * usage in the file body.
24
+ *
25
+ * Skips any class used in a parameterized type position (`FormGroup<T>`): the typed form is
26
+ * intentional and `UntypedFormGroup<T>` is invalid (`UntypedFormGroup` is `FormGroup<any>`).
27
+ *
28
+ * Done in a single visitor (rather than four sequential `ChangeImport` calls) because chaining
29
+ * `ChangeImport` on the same import block can produce malformed output — stray commas, missing
30
+ * newlines — when each step rewrites the partially-modified previous output.
31
+ */
32
+ export class ReplaceUntypedForms extends Recipe {
33
+ readonly name = "org.openrewrite.angular.migration.replace-untyped-forms";
34
+ readonly displayName: string = "Replace form classes with untyped variants";
35
+ readonly description: string = "Renames `FormControl`, `FormGroup`, `FormArray`, and `FormBuilder` to their " +
36
+ "`Untyped*` equivalents in imports and usages. Angular 14 introduced strictly typed forms, " +
37
+ "requiring existing untyped usages to migrate to the `Untyped*` aliases. Classes used in " +
38
+ "parameterized type positions (e.g. `FormGroup<T>`) are left unchanged because the user " +
39
+ "already opted into typed forms.";
25
40
 
26
41
  async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
27
- const renameMap = new Map(FORM_RENAMES);
28
42
  return new class extends JavaScriptVisitor<ExecutionContext> {
29
- override async visitIdentifier(identifier: J.Identifier, p: ExecutionContext): Promise<J | undefined> {
30
- let id = await super.visitIdentifier(identifier, p) as J.Identifier;
31
- if (!id) return id;
43
+ private parameterized = new Set<string>();
44
+ private hasFormsImport = false;
45
+ private importedRenames = new Set<string>();
32
46
 
33
- const newName = renameMap.get(id.simpleName);
34
- if (!newName) return id;
47
+ override async visit<R extends J>(tree: Tree, p: ExecutionContext, parent?: Cursor): Promise<R | undefined> {
48
+ // Pass 1: collect classes used in parameterized type positions.
49
+ // visitIdentifier doesn't fire for type names (they go through visitTypeName,
50
+ // which is a no-op), so we walk explicitly via visitParameterizedType.
51
+ const parameterized = this.parameterized;
52
+ await new (class extends JavaScriptVisitor<ExecutionContext> {
53
+ override async visitParameterizedType(pt: J.ParameterizedType, ctx: ExecutionContext): Promise<J | undefined> {
54
+ if (isIdentifier(pt.class)) {
55
+ const name = (pt.class as J.Identifier).simpleName;
56
+ if (RENAMES[name]) parameterized.add(name);
57
+ }
58
+ return super.visitParameterizedType(pt, ctx);
59
+ }
60
+ })().visit(tree, p, parent);
35
61
 
36
- return create(id, draft => {
37
- draft.simpleName = newName;
38
- }) as J.Identifier;
62
+ return super.visit<R>(tree, p, parent);
39
63
  }
40
- }();
41
- }
42
- }
43
64
 
44
- export class ReplaceUntypedForms extends Recipe {
45
- readonly name = "org.openrewrite.angular.migration.replace-untyped-forms";
46
- readonly displayName: string = "Replace form classes with untyped variants";
47
- readonly description: string = "Renames `FormControl`, `FormGroup`, `FormArray`, and `FormBuilder` to their " +
48
- "`Untyped*` equivalents in imports and usages. Angular 14 introduced strictly typed forms, " +
49
- "requiring existing untyped usages to migrate to the `Untyped*` aliases.";
50
-
51
- async recipeList(): Promise<Recipe[]> {
52
- return [
53
- ...FORM_RENAMES.map(([oldMember, newMember]) =>
54
- new ChangeImport({oldModule: MODULE, oldMember, newModule: MODULE, newMember})
55
- ),
56
- new RenameFormIdentifiers(),
57
- ];
65
+ protected async visitImportDeclaration(jsImport: JS.Import, p: ExecutionContext): Promise<J | undefined> {
66
+ const imp = await super.visitImportDeclaration(jsImport, p) as JS.Import;
67
+ if (!imp?.moduleSpecifier) return imp;
68
+
69
+ const moduleSpec = imp.moduleSpecifier.element;
70
+ if (moduleSpec.kind !== J.Kind.Literal) return imp;
71
+ if ((moduleSpec as J.Literal).value !== MODULE) return imp;
72
+
73
+ const namedBindings = imp.importClause?.namedBindings;
74
+ if (namedBindings?.kind !== JS.Kind.NamedImports) return imp;
75
+
76
+ const named = namedBindings as JS.NamedImports;
77
+ let modified = false;
78
+ const newSpecifiers = named.elements.elements.map(specRP => {
79
+ const spec = specRP.element as JS.ImportSpecifier;
80
+ if (!isIdentifier(spec.specifier)) return specRP;
81
+ const oldName = (spec.specifier as J.Identifier).simpleName;
82
+ const newName = RENAMES[oldName];
83
+ if (!newName) return specRP;
84
+ // Skip rename when the class is used parameterized in this file.
85
+ if (this.parameterized.has(oldName)) return specRP;
86
+
87
+ this.hasFormsImport = true;
88
+ this.importedRenames.add(oldName);
89
+ modified = true;
90
+
91
+ return {
92
+ ...specRP,
93
+ element: {
94
+ ...spec,
95
+ specifier: {
96
+ ...spec.specifier,
97
+ simpleName: newName,
98
+ },
99
+ },
100
+ };
101
+ });
102
+
103
+ if (!modified) return imp;
104
+
105
+ return {
106
+ ...imp,
107
+ importClause: {
108
+ ...imp.importClause!,
109
+ namedBindings: {
110
+ ...named,
111
+ elements: {
112
+ ...named.elements,
113
+ elements: newSpecifiers,
114
+ },
115
+ },
116
+ },
117
+ } as JS.Import;
118
+ }
119
+
120
+ override async visitIdentifier(identifier: J.Identifier, p: ExecutionContext): Promise<J | undefined> {
121
+ const id = await super.visitIdentifier(identifier, p) as J.Identifier;
122
+ if (!id) return id;
123
+ if (!this.hasFormsImport) return id;
124
+ if (!this.importedRenames.has(id.simpleName)) return id;
125
+ const newName = RENAMES[id.simpleName];
126
+ if (!newName) return id;
127
+ return produceAsync(id, async draft => { draft.simpleName = newName; });
128
+ }
129
+ };
58
130
  }
59
131
  }
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Copyright 2026 the original author or authors.
3
+ *
4
+ * Moderne Proprietary. Only for use by Moderne customers under the terms of a commercial contract.
5
+ */
6
+
7
+ import {Recipe} from "@openrewrite/rewrite";
8
+ import {UpgradeDependencyVersion} from "@openrewrite/rewrite/javascript";
9
+
10
+ /**
11
+ * Bumps third-party Angular UI / utility libraries to versions compatible with Angular 18.
12
+ * These libraries follow their own version cadence — they're not in lockstep with Angular's
13
+ * major, so each entry needs its own target. Each `UpgradeDependencyVersion` is a no-op for
14
+ * projects that don't depend on the package, so the recipe is safe to include unconditionally.
15
+ *
16
+ * Add new entries when a customer's project surfaces another Angular-peer-pinned library that
17
+ * needs an explicit version pin for Angular 18 support.
18
+ */
19
+ export class UpgradeAngularPeerLibsTo18 extends Recipe {
20
+ readonly name = "org.openrewrite.angular.UpgradeAngularPeerLibsTo18";
21
+ readonly displayName = "Upgrade known Angular peer libraries to versions compatible with Angular 18";
22
+ readonly description = "Bumps third-party Angular libraries (ng-bootstrap, ngx-bootstrap, …) " +
23
+ "to the version line compatible with Angular 18. Pair with `UpgradeToAngular18`.";
24
+
25
+ async recipeList(): Promise<Recipe[]> {
26
+ return [
27
+ // ng-bootstrap's major lags Angular's by one — v17.x is the Angular-18 release.
28
+ new UpgradeDependencyVersion({packageName: "@ng-bootstrap/ng-bootstrap", newVersion: "17.x"}),
29
+ // ngx-bootstrap aligns with Angular's major — v18.x → Angular 18.
30
+ new UpgradeDependencyVersion({packageName: "ngx-bootstrap", newVersion: "18.x"}),
31
+ ];
32
+ }
33
+ }
@@ -7,6 +7,7 @@
7
7
  import {Recipe} from "@openrewrite/rewrite";
8
8
  import {ChangeImport, UpgradeDependencyVersion} from "@openrewrite/rewrite/javascript";
9
9
  import {UpgradeToAngular17} from "./upgrade-to-angular-17";
10
+ import {UpgradeAngularPeerLibsTo18} from "./upgrade-angular-peer-libs-to-18";
10
11
  import {ReplaceAsyncWithWaitForAsync} from "./replace-async-with-wait-for-async";
11
12
  import {ReplaceHttpClientModule} from "./replace-http-client-module";
12
13
  import {FindPlatformWorkerUsage} from "../search/find-platform-worker-usage";
@@ -54,15 +55,23 @@ export class UpgradeToAngular18 extends Recipe {
54
55
  new FindResourceCacheProviderUsage(),
55
56
  new FindTestabilityPendingRequestUsage(),
56
57
  new FindAnimationDriverMatchesElement(),
57
- // Angular core packages
58
- new UpgradeDependencyVersion({packagePattern: "@angular/*", newVersion: "18.x"}),
59
- // Angular DevKit
60
- new UpgradeDependencyVersion({packagePattern: "@angular-devkit/*", newVersion: "18.x"}),
61
- new UpgradeDependencyVersion({packageName: "@schematics/angular", newVersion: "18.x"}),
58
+ // Bump every package whose target follows the Angular major (18.x) in a single
59
+ // atomic npm install. UpgradeDependencyVersion runs npm once per call, so packages
60
+ // that share a peer-dep graph MUST go in one matcher — otherwise a partial bump
61
+ // leaves the install failing with ERESOLVE. picomatch brace expansion lets us glob
62
+ // multiple package patterns in a single call.
63
+ new UpgradeDependencyVersion({
64
+ packagePattern: "{@angular/*,@angular-devkit/*,@schematics/angular}",
65
+ newVersion: "18.x",
66
+ }),
67
+ // Bump well-known third-party Angular libraries (ng-bootstrap, ngx-bootstrap, …) to
68
+ // their Angular-18-compatible versions. Kept as a separate recipe so it can be run
69
+ // independently or extended without touching this file every time.
70
+ new UpgradeAngularPeerLibsTo18(),
62
71
  // zone.js
63
72
  new UpgradeDependencyVersion({packageName: "zone.js", newVersion: "0.14.x"}),
64
- // TypeScript
65
- new UpgradeDependencyVersion({packageName: "typescript", newVersion: "5.5.x"}),
73
+ // TypeScript: Angular 18 compiler requires >=5.4.0 <5.5.0
74
+ new UpgradeDependencyVersion({packageName: "typescript", newVersion: "5.4.x"}),
66
75
  ];
67
76
  }
68
77
  }