@openrewrite/recipes-angular 1.9.0 → 1.10.0-20260813-195315

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 (120) hide show
  1. package/dist/index.d.ts +20 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +84 -2
  4. package/dist/index.js.map +1 -1
  5. package/dist/migration/add-eager-change-detection.d.ts +8 -0
  6. package/dist/migration/add-eager-change-detection.d.ts.map +1 -0
  7. package/dist/migration/add-eager-change-detection.js +130 -0
  8. package/dist/migration/add-eager-change-detection.js.map +1 -0
  9. package/dist/migration/add-istanbul-instrumenter.d.ts +8 -0
  10. package/dist/migration/add-istanbul-instrumenter.d.ts.map +1 -0
  11. package/dist/migration/add-istanbul-instrumenter.js +80 -0
  12. package/dist/migration/add-istanbul-instrumenter.js.map +1 -0
  13. package/dist/migration/add-no-incremental-hydration.d.ts +8 -0
  14. package/dist/migration/add-no-incremental-hydration.d.ts.map +1 -0
  15. package/dist/migration/add-no-incremental-hydration.js +69 -0
  16. package/dist/migration/add-no-incremental-hydration.js.map +1 -0
  17. package/dist/migration/add-strict-templates-false.d.ts +8 -0
  18. package/dist/migration/add-strict-templates-false.d.ts.map +1 -0
  19. package/dist/migration/add-strict-templates-false.js +84 -0
  20. package/dist/migration/add-strict-templates-false.js.map +1 -0
  21. package/dist/migration/add-trust-proxy-headers.d.ts +8 -0
  22. package/dist/migration/add-trust-proxy-headers.d.ts.map +1 -0
  23. package/dist/migration/add-trust-proxy-headers.js +82 -0
  24. package/dist/migration/add-trust-proxy-headers.js.map +1 -0
  25. package/dist/migration/add-with-xhr.d.ts +8 -0
  26. package/dist/migration/add-with-xhr.d.ts.map +1 -0
  27. package/dist/migration/add-with-xhr.js +70 -0
  28. package/dist/migration/add-with-xhr.js.map +1 -0
  29. package/dist/migration/js-support.d.ts +6 -0
  30. package/dist/migration/js-support.d.ts.map +1 -0
  31. package/dist/migration/js-support.js +94 -0
  32. package/dist/migration/js-support.js.map +1 -0
  33. package/dist/migration/json-support.d.ts +19 -0
  34. package/dist/migration/json-support.d.ts.map +1 -0
  35. package/dist/migration/json-support.js +117 -0
  36. package/dist/migration/json-support.js.map +1 -0
  37. package/dist/migration/migrate-input-to-signal.d.ts.map +1 -1
  38. package/dist/migration/migrate-input-to-signal.js +3 -67
  39. package/dist/migration/migrate-input-to-signal.js.map +1 -1
  40. package/dist/migration/migrate-model-with-output.d.ts +8 -0
  41. package/dist/migration/migrate-model-with-output.d.ts.map +1 -0
  42. package/dist/migration/migrate-model-with-output.js +192 -0
  43. package/dist/migration/migrate-model-with-output.js.map +1 -0
  44. package/dist/migration/remove-with-fetch.d.ts +8 -0
  45. package/dist/migration/remove-with-fetch.d.ts.map +1 -0
  46. package/dist/migration/remove-with-fetch.js +73 -0
  47. package/dist/migration/remove-with-fetch.js.map +1 -0
  48. package/dist/migration/rename-angular-js-globals.d.ts +8 -0
  49. package/dist/migration/rename-angular-js-globals.d.ts.map +1 -0
  50. package/dist/migration/rename-angular-js-globals.js +56 -0
  51. package/dist/migration/rename-angular-js-globals.js.map +1 -0
  52. package/dist/migration/rename-default-change-detection.d.ts +8 -0
  53. package/dist/migration/rename-default-change-detection.d.ts.map +1 -0
  54. package/dist/migration/rename-default-change-detection.js +52 -0
  55. package/dist/migration/rename-default-change-detection.js.map +1 -0
  56. package/dist/migration/rename-ssr-experimental-platform.d.ts +8 -0
  57. package/dist/migration/rename-ssr-experimental-platform.d.ts.map +1 -0
  58. package/dist/migration/rename-ssr-experimental-platform.js +124 -0
  59. package/dist/migration/rename-ssr-experimental-platform.js.map +1 -0
  60. package/dist/migration/replace-create-ng-module-ref.d.ts +8 -0
  61. package/dist/migration/replace-create-ng-module-ref.d.ts.map +1 -0
  62. package/dist/migration/replace-create-ng-module-ref.js +51 -0
  63. package/dist/migration/replace-create-ng-module-ref.js.map +1 -0
  64. package/dist/migration/suppress-safe-navigation-diagnostics.d.ts +8 -0
  65. package/dist/migration/suppress-safe-navigation-diagnostics.d.ts.map +1 -0
  66. package/dist/migration/suppress-safe-navigation-diagnostics.js +55 -0
  67. package/dist/migration/suppress-safe-navigation-diagnostics.js.map +1 -0
  68. package/dist/migration/upgrade-to-angular-22.d.ts +14 -0
  69. package/dist/migration/upgrade-to-angular-22.d.ts.map +1 -0
  70. package/dist/migration/upgrade-to-angular-22.js +112 -0
  71. package/dist/migration/upgrade-to-angular-22.js.map +1 -0
  72. package/dist/search/find-can-match-usage.d.ts +8 -0
  73. package/dist/search/find-can-match-usage.d.ts.map +1 -0
  74. package/dist/search/find-can-match-usage.js +53 -0
  75. package/dist/search/find-can-match-usage.js.map +1 -0
  76. package/dist/search/find-check-no-changes-usage.d.ts +8 -0
  77. package/dist/search/find-check-no-changes-usage.d.ts.map +1 -0
  78. package/dist/search/find-check-no-changes-usage.js +50 -0
  79. package/dist/search/find-check-no-changes-usage.js.map +1 -0
  80. package/dist/search/find-http-xhr-backend-usage.d.ts +8 -0
  81. package/dist/search/find-http-xhr-backend-usage.d.ts.map +1 -0
  82. package/dist/search/find-http-xhr-backend-usage.js +65 -0
  83. package/dist/search/find-http-xhr-backend-usage.js.map +1 -0
  84. package/dist/search/find-implicit-params-inheritance.d.ts +8 -0
  85. package/dist/search/find-implicit-params-inheritance.d.ts.map +1 -0
  86. package/dist/search/find-implicit-params-inheritance.js +74 -0
  87. package/dist/search/find-implicit-params-inheritance.js.map +1 -0
  88. package/dist/search/find-provide-routes-usage.d.ts +8 -0
  89. package/dist/search/find-provide-routes-usage.d.ts.map +1 -0
  90. package/dist/search/find-provide-routes-usage.js +64 -0
  91. package/dist/search/find-provide-routes-usage.js.map +1 -0
  92. package/dist/search/find-template-safe-navigation.d.ts +8 -0
  93. package/dist/search/find-template-safe-navigation.d.ts.map +1 -0
  94. package/dist/search/find-template-safe-navigation.js +105 -0
  95. package/dist/search/find-template-safe-navigation.js.map +1 -0
  96. package/package.json +1 -1
  97. package/src/index.ts +60 -0
  98. package/src/migration/add-eager-change-detection.ts +109 -0
  99. package/src/migration/add-istanbul-instrumenter.ts +62 -0
  100. package/src/migration/add-no-incremental-hydration.ts +49 -0
  101. package/src/migration/add-strict-templates-false.ts +62 -0
  102. package/src/migration/add-trust-proxy-headers.ts +61 -0
  103. package/src/migration/add-with-xhr.ts +50 -0
  104. package/src/migration/js-support.ts +92 -0
  105. package/src/migration/json-support.ts +119 -0
  106. package/src/migration/migrate-input-to-signal.ts +1 -67
  107. package/src/migration/migrate-model-with-output.ts +201 -0
  108. package/src/migration/remove-with-fetch.ts +53 -0
  109. package/src/migration/rename-angular-js-globals.ts +37 -0
  110. package/src/migration/rename-default-change-detection.ts +33 -0
  111. package/src/migration/rename-ssr-experimental-platform.ts +108 -0
  112. package/src/migration/replace-create-ng-module-ref.ts +32 -0
  113. package/src/migration/suppress-safe-navigation-diagnostics.ts +42 -0
  114. package/src/migration/upgrade-to-angular-22.ts +92 -0
  115. package/src/search/find-can-match-usage.ts +32 -0
  116. package/src/search/find-check-no-changes-usage.ts +29 -0
  117. package/src/search/find-http-xhr-backend-usage.ts +44 -0
  118. package/src/search/find-implicit-params-inheritance.ts +49 -0
  119. package/src/search/find-provide-routes-usage.ts +43 -0
  120. package/src/search/find-template-safe-navigation.ts +72 -0
@@ -0,0 +1,44 @@
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 {ExecutionContext, foundSearchResult, Recipe, TreeVisitor} from "@openrewrite/rewrite";
8
+ import {JavaScriptVisitor, JS} from "@openrewrite/rewrite/javascript";
9
+ import {isIdentifier, J} from "@openrewrite/rewrite/java";
10
+
11
+ export class FindHttpXhrBackendUsage extends Recipe {
12
+ readonly name = "org.openrewrite.angular.search.find-http-xhr-backend-usage";
13
+ readonly displayName: string = "Find `HttpXhrBackend` usage";
14
+ readonly description: string = "Finds imports of `HttpXhrBackend` from `@angular/common/http`. " +
15
+ "Angular 22 uses the Fetch API by default; add `withXhr()` to `provideHttpClient()` to keep using `XMLHttpRequest`, " +
16
+ "which is also required for upload progress reports.";
17
+
18
+ async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
19
+ return new class extends JavaScriptVisitor<ExecutionContext> {
20
+ protected async visitImportDeclaration(jsImport: JS.Import, p: ExecutionContext): Promise<J | undefined> {
21
+ const imp = await super.visitImportDeclaration(jsImport, p) as JS.Import;
22
+ if (!imp.moduleSpecifier) return imp;
23
+
24
+ const moduleSpec = imp.moduleSpecifier.element;
25
+ if (moduleSpec.kind !== J.Kind.Literal) return imp;
26
+ if ((moduleSpec as J.Literal).value !== '@angular/common/http') return imp;
27
+
28
+ const namedBindings = imp.importClause?.namedBindings;
29
+ if (namedBindings?.kind === JS.Kind.NamedImports) {
30
+ const named = namedBindings as JS.NamedImports;
31
+ for (const specifier of named.elements.elements) {
32
+ const spec = specifier.element as JS.ImportSpecifier;
33
+ if (isIdentifier(spec.specifier) && spec.specifier.simpleName === 'HttpXhrBackend') {
34
+ return foundSearchResult(imp,
35
+ "HttpXhrBackend is no longer the default in Angular 22. Use provideHttpClient(withXhr()) to keep XMLHttpRequest based requests. See https://angular.dev/api/common/http/withXhr");
36
+ }
37
+ }
38
+ }
39
+
40
+ return imp;
41
+ }
42
+ };
43
+ }
44
+ }
@@ -0,0 +1,49 @@
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 {ExecutionContext, foundSearchResult, Recipe, TreeVisitor} from "@openrewrite/rewrite";
8
+ import {JavaScriptVisitor} from "@openrewrite/rewrite/javascript";
9
+ import {isIdentifier, J} from "@openrewrite/rewrite/java";
10
+
11
+ export class FindImplicitParamsInheritance extends Recipe {
12
+ readonly name = "org.openrewrite.angular.search.find-implicit-params-inheritance";
13
+ readonly displayName: string = "Find router configuration relying on the default `paramsInheritanceStrategy`";
14
+ readonly description: string = "Finds `provideRouter()` and `RouterModule.forRoot()` calls that do not set `paramsInheritanceStrategy`. " +
15
+ "Angular 22 changed the default from `emptyOnly` to `always`, so route parameters and data are now inherited from all parent routes.";
16
+
17
+ async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
18
+ return new class extends JavaScriptVisitor<ExecutionContext> {
19
+ override async visitMethodInvocation(method: J.MethodInvocation, p: ExecutionContext): Promise<J | undefined> {
20
+ const m = await super.visitMethodInvocation(method, p) as J.MethodInvocation;
21
+ if (!m || !isIdentifier(m.name)) return m;
22
+
23
+ const isProvideRouter = !m.select && m.name.simpleName === 'provideRouter';
24
+ const isForRoot = m.name.simpleName === 'forRoot' &&
25
+ !!m.select && isIdentifier(m.select.element) && m.select.element.simpleName === 'RouterModule';
26
+ if (!isProvideRouter && !isForRoot) return m;
27
+
28
+ if (await declaresParamsInheritanceStrategy(m, p)) return m;
29
+
30
+ return foundSearchResult(m,
31
+ "paramsInheritanceStrategy defaults to 'always' as of Angular 22. Set it to 'emptyOnly' to keep the previous behavior.");
32
+ }
33
+ };
34
+ }
35
+ }
36
+
37
+ async function declaresParamsInheritanceStrategy(method: J.MethodInvocation, p: ExecutionContext): Promise<boolean> {
38
+ let found = false;
39
+ const detector = new class extends JavaScriptVisitor<ExecutionContext> {
40
+ override async visitIdentifier(identifier: J.Identifier, ctx: ExecutionContext): Promise<J | undefined> {
41
+ if (identifier.simpleName === 'paramsInheritanceStrategy') found = true;
42
+ return identifier;
43
+ }
44
+ }();
45
+ for (const element of method.arguments?.elements ?? []) {
46
+ await detector.visit(element.element, p);
47
+ }
48
+ return found;
49
+ }
@@ -0,0 +1,43 @@
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 {ExecutionContext, foundSearchResult, Recipe, TreeVisitor} from "@openrewrite/rewrite";
8
+ import {JavaScriptVisitor, JS} from "@openrewrite/rewrite/javascript";
9
+ import {isIdentifier, J} from "@openrewrite/rewrite/java";
10
+
11
+ export class FindProvideRoutesUsage extends Recipe {
12
+ readonly name = "org.openrewrite.angular.search.find-provide-routes-usage";
13
+ readonly displayName: string = "Find `provideRoutes` usage";
14
+ readonly description: string = "Finds imports of `provideRoutes` from `@angular/router`, which was removed in Angular 22. " +
15
+ "Use `provideRouter()`, or provide the `ROUTES` multi token directly.";
16
+
17
+ async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
18
+ return new class extends JavaScriptVisitor<ExecutionContext> {
19
+ protected async visitImportDeclaration(jsImport: JS.Import, p: ExecutionContext): Promise<J | undefined> {
20
+ const imp = await super.visitImportDeclaration(jsImport, p) as JS.Import;
21
+ if (!imp.moduleSpecifier) return imp;
22
+
23
+ const moduleSpec = imp.moduleSpecifier.element;
24
+ if (moduleSpec.kind !== J.Kind.Literal) return imp;
25
+ if ((moduleSpec as J.Literal).value !== '@angular/router') return imp;
26
+
27
+ const namedBindings = imp.importClause?.namedBindings;
28
+ if (namedBindings?.kind === JS.Kind.NamedImports) {
29
+ const named = namedBindings as JS.NamedImports;
30
+ for (const specifier of named.elements.elements) {
31
+ const spec = specifier.element as JS.ImportSpecifier;
32
+ if (isIdentifier(spec.specifier) && spec.specifier.simpleName === 'provideRoutes') {
33
+ return foundSearchResult(imp,
34
+ "provideRoutes() was removed in Angular 22. Use provideRouter(), or the ROUTES multi token if necessary.");
35
+ }
36
+ }
37
+ }
38
+
39
+ return imp;
40
+ }
41
+ };
42
+ }
43
+ }
@@ -0,0 +1,72 @@
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 {ExecutionContext, foundSearchResult, Recipe, TreeVisitor} from "@openrewrite/rewrite";
8
+ import {PlainText, PlainTextVisitor} from "@openrewrite/rewrite/text";
9
+ import {JavaScriptVisitor} from "@openrewrite/rewrite/javascript";
10
+ import {isIdentifier, isLiteral, J} from "@openrewrite/rewrite/java";
11
+
12
+ const MESSAGE = "Safe navigation in an Angular template returns undefined rather than null as of Angular 22. " +
13
+ "Review bindings that distinguish the two, such as comparisons against null and pipes that treat null and " +
14
+ "undefined differently. See https://angular.dev/errors/safe-navigation-undefined";
15
+
16
+ /** `{{ a?.b }}`, `[x]="a?.b"`, and `@if (a?.b)`, but not `a ?? b` or the `?.` of a TypeScript expression. */
17
+ const SAFE_NAVIGATION = /\?\.(?![.\d])/;
18
+
19
+ export class FindTemplateSafeNavigation extends Recipe {
20
+ readonly name = "org.openrewrite.angular.search.find-template-safe-navigation";
21
+ readonly displayName: string = "Find safe navigation in Angular templates";
22
+ readonly description: string = "Finds `?.` in HTML templates and in inline `template` metadata. Angular 22 changed " +
23
+ "safe navigation in templates to return `undefined` instead of `null`, which changes bindings that tell the two " +
24
+ "apart. Angular ships a `$safeNavigationMigration()` wrapper for this; this recipe reports the templates to review " +
25
+ "rather than rewriting the expressions.";
26
+
27
+ async recipeList(): Promise<Recipe[]> {
28
+ return [new FindHtmlSafeNavigation(), new FindInlineTemplateSafeNavigation()];
29
+ }
30
+ }
31
+
32
+ class FindHtmlSafeNavigation extends Recipe {
33
+ readonly name = "org.openrewrite.angular.search.find-template-safe-navigation.html";
34
+ readonly displayName: string = "Find safe navigation in HTML templates";
35
+ readonly description: string = "Finds `?.` in `.html` templates.";
36
+
37
+ async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
38
+ return new class extends PlainTextVisitor<ExecutionContext> {
39
+ override async visitText(text: PlainText, p: ExecutionContext): Promise<PlainText | undefined> {
40
+ const t = await super.visitText(text, p) as PlainText;
41
+ if (!t || !t.sourcePath.endsWith('.html')) return t;
42
+ if (!SAFE_NAVIGATION.test(t.text)) return t;
43
+
44
+ return foundSearchResult(t, MESSAGE);
45
+ }
46
+ }();
47
+ }
48
+ }
49
+
50
+ class FindInlineTemplateSafeNavigation extends Recipe {
51
+ readonly name = "org.openrewrite.angular.search.find-template-safe-navigation.inline";
52
+ readonly displayName: string = "Find safe navigation in inline templates";
53
+ readonly description: string = "Finds `?.` in inline `template` metadata of `@Component` decorators.";
54
+
55
+ async editor(): Promise<TreeVisitor<any, ExecutionContext>> {
56
+ return new class extends JavaScriptVisitor<ExecutionContext> {
57
+ protected async visitPropertyAssignment(property: any, p: ExecutionContext): Promise<J | undefined> {
58
+ const prop = await super.visitPropertyAssignment(property, p) as any;
59
+ if (!prop) return prop;
60
+
61
+ const name = prop.name?.element;
62
+ if (!isIdentifier(name) || name.simpleName !== 'template') return prop;
63
+
64
+ const initializer = prop.initializer;
65
+ if (!initializer || !isLiteral(initializer)) return prop;
66
+ if (!SAFE_NAVIGATION.test(initializer.valueSource ?? '')) return prop;
67
+
68
+ return foundSearchResult(prop, MESSAGE);
69
+ }
70
+ }();
71
+ }
72
+ }