@silvestv/migration-planificator 3.0.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 (122) hide show
  1. package/LICENSE +96 -0
  2. package/README.fr.md +359 -0
  3. package/README.md +360 -0
  4. package/SECURITY.md +187 -0
  5. package/dist/client.bundle.js +357 -0
  6. package/dist/src/core/app-analyzer.js +134 -0
  7. package/dist/src/core/ast/matchers/html/html-attribute-matcher.js +86 -0
  8. package/dist/src/core/ast/matchers/html/html-component-matcher.js +40 -0
  9. package/dist/src/core/ast/matchers/html/html-element-matcher.js +54 -0
  10. package/dist/src/core/ast/matchers/html/html-parser.js +58 -0
  11. package/dist/src/core/ast/matchers/html/html-pipe-matcher.js +95 -0
  12. package/dist/src/core/ast/matchers/html/html-text-matcher.js +53 -0
  13. package/dist/src/core/ast/matchers/html/index.js +118 -0
  14. package/dist/src/core/ast/matchers/index.js +377 -0
  15. package/dist/src/core/ast/matchers/ts/collection-matcher.js +51 -0
  16. package/dist/src/core/ast/matchers/ts/context-matcher.js +275 -0
  17. package/dist/src/core/ast/matchers/ts/decorator-matcher.js +465 -0
  18. package/dist/src/core/ast/matchers/ts/expression-matcher.js +237 -0
  19. package/dist/src/core/ast/matchers/ts/file-matcher.js +97 -0
  20. package/dist/src/core/ast/matchers/ts/hierarchy-matcher.js +172 -0
  21. package/dist/src/core/ast/matchers/ts/import-matcher.js +39 -0
  22. package/dist/src/core/ast/matchers/ts/index.js +53 -0
  23. package/dist/src/core/ast/matchers/ts/node-matcher.js +156 -0
  24. package/dist/src/core/ast/matchers/ts/symbol-matcher.js +281 -0
  25. package/dist/src/core/ast/matchers/ts/type-matcher.js +207 -0
  26. package/dist/src/core/ast/matchers/utils/matcher-helpers.js +37 -0
  27. package/dist/src/core/ast/scanner-ast.js +444 -0
  28. package/dist/src/core/project-detector.js +196 -0
  29. package/dist/src/core/project-strategy/index.js +9 -0
  30. package/dist/src/core/project-strategy/nx-strategy.js +130 -0
  31. package/dist/src/core/project-strategy/project-strategy.interface.js +2 -0
  32. package/dist/src/core/project-strategy/standalone-strategy.js +74 -0
  33. package/dist/src/core/project-strategy/strategy-factory.js +15 -0
  34. package/dist/src/core/rules-loader.js +89 -0
  35. package/dist/src/core/scan-reporter.js +316 -0
  36. package/dist/src/core/scanner-delta.js +339 -0
  37. package/dist/src/core/scanner-orchestrator.js +266 -0
  38. package/dist/src/core/scanner-regex.js +298 -0
  39. package/dist/src/core/workload/calculator.js +82 -0
  40. package/dist/src/core/workload/constants.js +15 -0
  41. package/dist/src/core/workload/grouping.js +18 -0
  42. package/dist/src/core/workload/hierarchy-calculator.js +127 -0
  43. package/dist/src/core/workload/index.js +11 -0
  44. package/dist/src/core/workload/metadata.js +20 -0
  45. package/dist/src/core/workload/special-workload.js +101 -0
  46. package/dist/src/core/workload/target-resolver.js +34 -0
  47. package/dist/src/data/angular-migration-rules.json +2337 -0
  48. package/dist/src/data/markdown/angular-migration-17-18.md +408 -0
  49. package/dist/src/data/markdown/angular-migration-18-19.md +600 -0
  50. package/dist/src/data/markdown/angular-migration-19-20.md +521 -0
  51. package/dist/src/data/rules/rearchitecture/rearchitecture-rules.json +66 -0
  52. package/dist/src/data/rules/to18/rules-18-obligatoire.json +374 -0
  53. package/dist/src/data/rules/to18/rules-18-optionnelle.json +188 -0
  54. package/dist/src/data/rules/to18/rules-18-recommande.json +218 -0
  55. package/dist/src/data/rules/to19/rules-19-obligatoire.json +348 -0
  56. package/dist/src/data/rules/to19/rules-19-optionnelle.json +223 -0
  57. package/dist/src/data/rules/to19/rules-19-recommande.json +200 -0
  58. package/dist/src/data/rules/to20/rules-20-obligatoire.json +556 -0
  59. package/dist/src/data/rules/to20/rules-20-optionnelle.json +190 -0
  60. package/dist/src/data/rules/to20/rules-20-recommande.json +151 -0
  61. package/dist/src/index.js +161 -0
  62. package/dist/src/models/chip-config.js +45 -0
  63. package/dist/src/models/interfaces/app-details.interface.js +2 -0
  64. package/dist/src/models/interfaces/ast-interfaces.js +5 -0
  65. package/dist/src/models/interfaces/ast-pattern.interface.js +2 -0
  66. package/dist/src/models/interfaces/client-interfaces.js +6 -0
  67. package/dist/src/models/interfaces/detection-stats.interface.js +2 -0
  68. package/dist/src/models/interfaces/html-match.interface.js +2 -0
  69. package/dist/src/models/interfaces/html-report-data.interface.js +2 -0
  70. package/dist/src/models/interfaces/lib-details.interface.js +2 -0
  71. package/dist/src/models/interfaces/migration-rules.interface.js +2 -0
  72. package/dist/src/models/interfaces/parsed-args.interface.js +2 -0
  73. package/dist/src/models/interfaces/project-info.interface.js +2 -0
  74. package/dist/src/models/interfaces/project-overview-data.interface.js +2 -0
  75. package/dist/src/models/interfaces/rule-match.interface.js +2 -0
  76. package/dist/src/models/interfaces/rule.interface.js +2 -0
  77. package/dist/src/models/interfaces/rules-by-priority.interface.js +2 -0
  78. package/dist/src/models/interfaces/scanner-comparison.interface.js +2 -0
  79. package/dist/src/models/interfaces/special-workload.interface.js +2 -0
  80. package/dist/src/models/interfaces/workload-report.interface.js +2 -0
  81. package/dist/src/models/types/build-block-blob.type.js +2 -0
  82. package/dist/src/models/types/migration-version.type.js +2 -0
  83. package/dist/src/models/types/project-type.type.js +2 -0
  84. package/dist/src/models/types/risk-level.type.js +2 -0
  85. package/dist/src/models/types/rule-category.type.js +2 -0
  86. package/dist/src/models/types/rule-priority.type.js +2 -0
  87. package/dist/src/models/types/rule-workload-type.type.js +2 -0
  88. package/dist/src/templates/landing/applications-analyzed.template.js +18 -0
  89. package/dist/src/templates/landing/card-app-info.template.js +63 -0
  90. package/dist/src/templates/landing/card-lib-info.template.js +67 -0
  91. package/dist/src/templates/landing/libs-analyzed.template.js +22 -0
  92. package/dist/src/templates/landing/nx-summary.template.js +115 -0
  93. package/dist/src/templates/landing/project-overview.template.js +27 -0
  94. package/dist/src/templates/page/index-page.template.js +95 -0
  95. package/dist/src/templates/page/main.template.js +83 -0
  96. package/dist/src/templates/page/migration-guide.template.js +175 -0
  97. package/dist/src/templates/page/workload-report.template.js +53 -0
  98. package/dist/src/templates/workload/dashboard.template.js +184 -0
  99. package/dist/src/templates/workload/filters-panel.template.js +215 -0
  100. package/dist/src/templates/workload/guide-rule-card.template.js +107 -0
  101. package/dist/src/templates/workload/hierarchy-nx.template.js +104 -0
  102. package/dist/src/templates/workload/hierarchy-shared.js +163 -0
  103. package/dist/src/templates/workload/hierarchy-standalone.template.js +36 -0
  104. package/dist/src/templates/workload/hierarchy.template.js +35 -0
  105. package/dist/src/templates/workload/rule-modal.template.js +280 -0
  106. package/dist/src/utils/core/args-parser.js +123 -0
  107. package/dist/src/utils/core/array-helpers.js +18 -0
  108. package/dist/src/utils/core/ast-helpers.js +99 -0
  109. package/dist/src/utils/core/file-helpers.js +109 -0
  110. package/dist/src/utils/core/html-helpers.js +36 -0
  111. package/dist/src/utils/core/index.js +28 -0
  112. package/dist/src/utils/core/logger.js +38 -0
  113. package/dist/src/utils/core/rule-helpers.js +15 -0
  114. package/dist/src/utils/core/workload-formatter.js +6 -0
  115. package/dist/src/utils/shared/array-helpers.js +25 -0
  116. package/dist/src/utils/shared/date-helpers.js +109 -0
  117. package/dist/src/utils/shared/html-helpers.js +37 -0
  118. package/dist/src/utils/shared/index.js +25 -0
  119. package/dist/src/utils/shared/rule-helpers.js +20 -0
  120. package/dist/src/utils/shared/time-formatters.js +76 -0
  121. package/dist/styles.css +2 -0
  122. package/package.json +107 -0
@@ -0,0 +1,374 @@
1
+ [
2
+ {
3
+ "key": "angular_18_environment",
4
+ "summary": "Mise à jour environnement Angular 18 (Node 18.19.1+, TypeScript 5.4+)",
5
+ "description": "Angular 18 requiert Node.js 18.19.1 ou supérieur et TypeScript 5.4+. Ces versions apportent le support des signaux et des améliorations de compilation. Les versions antérieures provoquent des erreurs de build.",
6
+ "estimated_time_per_occurrence": 60,
7
+ "onFile": "package.json",
8
+ "fileTypes": ["package.json"],
9
+ "regex": "\"@angular/(core|cli)\"\\s*:\\s*\"(?:(?:\\^|~)?1[0-7](?:\\.\\d+){0,2})\"",
10
+ "category": "environment",
11
+ "auto_fixable": false,
12
+ "migration_command": "npx ng update @angular/core@18 @angular/cli@18",
13
+ "risk_level": "high",
14
+ "code_description": "// Migration Angular 18\n// Node : >= 18.19.1\n// TypeScript : ~5.4.0\n// Commande :\n// nvm install 18.19.1\n// npm i typescript@~5.4.0\n// npx ng update @angular/core@18 @angular/cli@18",
15
+ "doc_url": "https://angular.dev/reference/migrations"
16
+ },
17
+ {
18
+ "key": "node_version_18",
19
+ "summary": "Mise à jour Node.js vers 18.19.1+",
20
+ "description": "Angular 18 nécessite Node.js version 18.19.1 ou supérieure pour supporter les nouvelles fonctionnalités TypeScript 5.4 et les optimisations du compilateur. Cette mise à jour est critique car les versions antérieures peuvent causer des erreurs de build.",
21
+ "estimated_time_per_occurrence": 15,
22
+ "onFile": "package.json",
23
+ "fileTypes": [
24
+ "package.json"
25
+ ],
26
+ "regex": "\"engines\"\\s*:\\s*\\{[^}]*\"node\"\\s*:\\s*\"(?:(?:[<>=~^]*)(1[0-7]|18\\.(?:[0-9]|1[0-8])(?:\\.[0-9]+)?))\"",
27
+ "category": "environment",
28
+ "auto_fixable": false,
29
+ "migration_command": null,
30
+ "risk_level": "high",
31
+ "code_description": "// Vérifier et mettre à jour Node.js\n// Avant: Node v16.x\n// Après: Node v18.19.1+\n// Commande: node --version",
32
+ "doc_url": "https://angular.dev/reference/migrations"
33
+ },
34
+ {
35
+ "key": "typescript_5_4",
36
+ "summary": "Mise à jour TypeScript vers 5.4+",
37
+ "description": "TypeScript 5.4 apporte des améliorations de performance et de nouveaux contrôles de type requis par Angular 18. La migration est automatisable via npm et nécessite une vérification de compatibilité des types existants.",
38
+ "estimated_time_per_occurrence": 10,
39
+ "onFile": "package.json",
40
+ "fileTypes": [
41
+ "package.json"
42
+ ],
43
+ "regex": "^(?![\\s\\S]*\"typescript\"[\\s\\S]*\"[<>=~^]*(?:5\\.[4-9]|[6-9]\\d*)\\.)[\\s\\S]+",
44
+ "category": "environment",
45
+ "auto_fixable": true,
46
+ "migration_command": "npm install typescript@~5.4.0",
47
+ "risk_level": "medium",
48
+ "code_description": "// package.json\n// Avant: \"typescript\": \"~4.9.0\"\n// Après: \"typescript\": \"~5.4.0\"",
49
+ "doc_url": "https://angular.dev/reference/migrations"
50
+ },
51
+ {
52
+ "key": "import_async_to_waitForAsync",
53
+ "summary": "Renommer import { async } en { waitForAsync }",
54
+ "description": "L'import 'async' de @angular/core est renommé en 'waitForAsync' pour éviter les conflits avec le mot-clé async/await natif de JavaScript. Tous les tests utilisant async() doivent être mis à jour.",
55
+ "estimated_time_per_occurrence": 2,
56
+ "onFile": null,
57
+ "fileTypes": [
58
+ "*.ts"
59
+ ],
60
+ "regex": "import\\s*\\{[^}]*\\basync\\b[^}]*\\}\\s*from\\s*['\"]@angular/core['\"]",
61
+ "astPattern": {
62
+ "nodeType": "ImportDeclaration",
63
+ "moduleSpecifier": "@angular/core",
64
+ "namedImports": {
65
+ "contains": "async"
66
+ },
67
+ "excludeContext": [
68
+ "StringLiteral",
69
+ "Comment"
70
+ ]
71
+ },
72
+ "category": "imports",
73
+ "auto_fixable": true,
74
+ "migration_command": null,
75
+ "risk_level": "low",
76
+ "code_description": "// Avant:\nimport { async } from '@angular/core';\n\n// Après:\nimport { waitForAsync } from '@angular/core';",
77
+ "doc_url": "https://angular.dev/reference/migrations"
78
+ },
79
+ {
80
+ "key": "import_statekey_transferstate_core",
81
+ "summary": "Déplacer StateKey/TransferState vers @angular/core",
82
+ "description": "StateKey et TransferState sont déplacés de @angular/platform-browser vers @angular/core pour une meilleure cohérence architecturale. Cela affecte principalement le code SSR et le transfert d'état.",
83
+ "estimated_time_per_occurrence": 2,
84
+ "onFile": null,
85
+ "fileTypes": [
86
+ "*.ts"
87
+ ],
88
+ "regex": "import\\s*\\{[^}]*(StateKey|TransferState)[^}]*\\}\\s*from\\s*['\"]@angular/platform-browser['\"]",
89
+ "astPattern": {
90
+ "nodeType": "ImportDeclaration",
91
+ "moduleSpecifier": "@angular/platform-browser",
92
+ "namedImports": {
93
+ "containsAny": [
94
+ "StateKey",
95
+ "TransferState"
96
+ ]
97
+ },
98
+ "excludeContext": [
99
+ "StringLiteral",
100
+ "Comment"
101
+ ]
102
+ },
103
+ "category": "imports",
104
+ "auto_fixable": true,
105
+ "migration_command": null,
106
+ "risk_level": "low",
107
+ "code_description": "// Avant:\nimport { StateKey, TransferState } from '@angular/platform-browser';\n\n// Après:\nimport { StateKey, TransferState } from '@angular/core';",
108
+ "doc_url": "https://angular.dev/reference/migrations"
109
+ },
110
+ {
111
+ "key": "platformDynamicServer_to_platformServer",
112
+ "summary": "Remplacer platformDynamicServer par platformServer",
113
+ "description": "platformDynamicServer est obsolète et remplacé par platformServer qui nécessite un import explicite du compilateur Angular. Cette migration affecte la configuration SSR et nécessite l'ajout de @angular/compiler.",
114
+ "estimated_time_per_occurrence": 5,
115
+ "onFile": null,
116
+ "fileTypes": [
117
+ "*.ts"
118
+ ],
119
+ "regex": "(?<![\"\\'])\\bplatformDynamicServer\\b(?![\"\\'])",
120
+ "astPattern": {
121
+ "nodeType": "Identifier",
122
+ "name": "platformDynamicServer",
123
+ "excludeContext": [
124
+ "Comment",
125
+ "StringLiteral",
126
+ "ImportSpecifier"
127
+ ]
128
+ },
129
+ "category": "api",
130
+ "auto_fixable": true,
131
+ "migration_command": null,
132
+ "risk_level": "medium",
133
+ "code_description": "// Avant:\nimport { platformDynamicServer } from '@angular/platform-server';\n\n// Après:\nimport { platformServer } from '@angular/platform-server';\nimport '@angular/compiler';",
134
+ "doc_url": "https://angular.dev/reference/migrations"
135
+ },
136
+ {
137
+ "key": "remove_ServerTransferStateModule",
138
+ "summary": "Supprimer ServerTransferStateModule (obsolète)",
139
+ "description": "Supprime le module `ServerTransferStateModule`, supprimé en Angular 18. Il est désormais remplacé par le mécanisme `TransferState` intégré côté client.",
140
+ "estimated_time_per_occurrence": 3,
141
+ "onFile": null,
142
+ "fileTypes": [
143
+ "*.ts"
144
+ ],
145
+ "regex": "\\bServerTransferStateModule\\b",
146
+ "astPattern": {
147
+ "nodeType": "Identifier",
148
+ "name": "ServerTransferStateModule",
149
+ "excludeContext": [
150
+ "Comment",
151
+ "StringLiteral",
152
+ "ImportSpecifier"
153
+ ],
154
+ "context": [
155
+ "ArrayLiteralExpression",
156
+ "ImportDeclaration"
157
+ ]
158
+ },
159
+ "category": "imports",
160
+ "auto_fixable": true,
161
+ "migration_command": null,
162
+ "risk_level": "low",
163
+ "code_description": "// Avant:\nimport { ServerTransferStateModule } from '@angular/platform-server';\n@NgModule({ imports: [ServerTransferStateModule] })\n\n// Après:\n// Supprimer complètement, plus nécessaire",
164
+ "doc_url": "https://angular.dev/update-guide"
165
+ },
166
+ {
167
+ "key": "remove_matchesElement",
168
+ "summary": "Supprimer animationDriver.matchesElement()",
169
+ "description": "La méthode matchesElement() de l'animation driver est supprimée sans remplacement direct. Il faut refactoriser le code pour utiliser des approches alternatives de sélection d'éléments comme querySelector ou des directives Angular.",
170
+ "estimated_time_per_occurrence": 10,
171
+ "onFile": null,
172
+ "fileTypes": [
173
+ "*.ts"
174
+ ],
175
+ "regex": "\\.matchesElement\\s*\\(",
176
+ "astPattern": {
177
+ "nodeType": "CallExpression",
178
+ "expression": {
179
+ "nodeType": "PropertyAccessExpression",
180
+ "propertyName": "matchesElement"
181
+ },
182
+ "excludeContext": [
183
+ "StringLiteral",
184
+ "Comment"
185
+ ]
186
+ },
187
+ "category": "api",
188
+ "auto_fixable": false,
189
+ "migration_command": null,
190
+ "risk_level": "medium",
191
+ "code_description": "// Avant:\nanimationDriver.matchesElement(element, selector);\n\n// Après:\n// Supprimer - utiliser une autre approche\n// (pas de remplacement direct)",
192
+ "doc_url": "https://angular.dev/reference/migrations"
193
+ },
194
+ {
195
+ "key": "remove_isPlatformWorkerUi",
196
+ "summary": "Supprimer isPlatformWorkerUi()",
197
+ "description": "La fonction isPlatformWorkerUi() n'est plus supportée car Web Workers UI ne sont plus maintenus dans Angular. Supprimer tout le code dépendant de cette détection de plateforme.",
198
+ "estimated_time_per_occurrence": 5,
199
+ "onFile": null,
200
+ "fileTypes": [
201
+ "*.ts"
202
+ ],
203
+ "regex": "(?<![\"\\'])\\bisPlatformWorkerUi\\s*\\(",
204
+ "astPattern": {
205
+ "nodeType": "CallExpression",
206
+ "functionName": "isPlatformWorkerUi",
207
+ "excludeContext": [
208
+ "StringLiteral",
209
+ "Comment"
210
+ ]
211
+ },
212
+ "category": "api",
213
+ "auto_fixable": false,
214
+ "migration_command": null,
215
+ "risk_level": "low",
216
+ "code_description": "// Avant:\nif (isPlatformWorkerUi(platformId)) { }\n\n// Après:\n// Supprimer - plus supporté",
217
+ "doc_url": "https://angular.dev/reference/migrations"
218
+ },
219
+ {
220
+ "key": "remove_testability_methods",
221
+ "summary": "Supprimer méthodes Testability.increasePendingRequestCount()",
222
+ "description": "Les méthodes increasePendingRequestCount et decreasePendingRequestCount de Testability sont supprimées car la gestion des requêtes en attente est maintenant automatique via ZoneJS. Retirer tous les appels manuels.",
223
+ "estimated_time_per_occurrence": 5,
224
+ "onFile": null,
225
+ "fileTypes": [
226
+ "*.ts"
227
+ ],
228
+ "regex": "testability\\.(increasePendingRequestCount|decreasePendingRequestCount)\\s*\\(",
229
+ "category": "api",
230
+ "auto_fixable": false,
231
+ "migration_command": null,
232
+ "risk_level": "low",
233
+ "code_description": "// Avant:\ntestability.increasePendingRequestCount();\n\n// Après:\n// Supprimer - géré automatiquement par ZoneJS",
234
+ "astPattern": {
235
+ "nodeType": "CallExpression",
236
+ "expression": {
237
+ "nodeType": "PropertyAccessExpression",
238
+ "propertyName": [
239
+ "increasePendingRequestCount",
240
+ "decreasePendingRequestCount"
241
+ ]
242
+ },
243
+ "excludeContext": [
244
+ "StringLiteral",
245
+ "Comment"
246
+ ]
247
+ },
248
+ "doc_url": "https://angular.dev/reference/migrations"
249
+ },
250
+ {
251
+ "key": "ngModel_no_assignment",
252
+ "summary": "Pas d'assignation dans [(ngModel)]",
253
+ "description": "Angular 18 interdit les expressions d'assignation directement dans la liaison [(ngModel)] pour éviter les effets de bord imprévus. Utiliser (ngModelChange) pour gérer les transformations de valeur.",
254
+ "estimated_time_per_occurrence": 5,
255
+ "onFile": null,
256
+ "fileTypes": [
257
+ "*.html"
258
+ ],
259
+ "regex": "\\[\\(ngModel\\)\\]\\s*=\\s*[\"'][^\"']*=",
260
+ "astPattern": {
261
+ "nodeType": "Attribute",
262
+ "name": "ngModel",
263
+ "valueMatches": ".*=.*"
264
+ },
265
+ "category": "template",
266
+ "auto_fixable": false,
267
+ "migration_command": null,
268
+ "risk_level": "medium",
269
+ "code_description": "// Avant:\n<input [(ngModel)]=\"user.name = process()\">\n\n// Après:\n<input [(ngModel)]=\"user.name\" (ngModelChange)=\"onChange($event)\">",
270
+ "doc_url": "https://angular.dev/reference/migrations"
271
+ },
272
+ {
273
+ "key": "providers_router_outlet",
274
+ "summary": "Déplacer providers de composant avec <router-outlet>",
275
+ "description": "Les providers définis dans un composant contenant un router-outlet ne sont plus disponibles dans les composants routés. Déplacer ces providers vers le bootstrap de l'application ou la configuration des routes pour assurer leur disponibilité.",
276
+ "estimated_time_per_occurrence": 10,
277
+ "onFile": null,
278
+ "fileTypes": [
279
+ "*.html"
280
+ ],
281
+ "regex": "<router-outlet[^>]*>",
282
+ "category": "architecture",
283
+ "auto_fixable": false,
284
+ "migration_command": null,
285
+ "risk_level": "high",
286
+ "code_description": "// Avant:\n@Component({\n template: `<router-outlet></router-outlet>`,\n providers: [MyService]\n})\n\n// Après:\nbootstrapApplication(App, {\n providers: [MyService]\n});",
287
+ "astPattern": {
288
+ "nodeType": "Decorator",
289
+ "name": "Component",
290
+ "properties": {
291
+ "providers": {
292
+ "exists": true
293
+ }
294
+ },
295
+ "template": {
296
+ "contains": "router-outlet"
297
+ }
298
+ },
299
+ "doc_url": "https://angular.dev/reference/migrations"
300
+ },
301
+ {
302
+ "key": "onpush_host_bindings",
303
+ "summary": "OnPush + host bindings nécessitent markForCheck()",
304
+ "description": "Avec OnPush change detection, les host bindings ne sont plus automatiquement mis à jour. Appeler manuellement markForCheck() après modification des propriétés utilisées dans les host bindings pour forcer la détection de changement.",
305
+ "estimated_time_per_occurrence": 8,
306
+ "onFile": null,
307
+ "fileTypes": [
308
+ "*.ts"
309
+ ],
310
+ "regex": "@Component[\\s\\S]*?(?:host\\s*:\\s*\\{[\\s\\S]*?[\\[\\(]|changeDetection\\s*:\\s*ChangeDetectionStrategy\\.OnPush)[\\s\\S]*?(?:host\\s*:\\s*\\{[\\s\\S]*?[\\[\\(]|changeDetection\\s*:\\s*ChangeDetectionStrategy\\.OnPush)",
311
+ "category": "component",
312
+ "auto_fixable": false,
313
+ "migration_command": null,
314
+ "risk_level": "high",
315
+ "code_description": "// Avant:\n@Component({\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: { '[class.active]': 'isActive' }\n})\ntoggle() { this.isActive = true; }\n\n// Après:\ntoggle() {\n this.isActive = true;\n this.cdr.markForCheck();\n}",
316
+ "astPattern": {
317
+ "nodeType": "Decorator",
318
+ "name": "Component",
319
+ "properties": {
320
+ "changeDetection": "ChangeDetectionStrategy.OnPush",
321
+ "host": {
322
+ "containsAny": [
323
+ {
324
+ "nodeType": "StringLiteral",
325
+ "valueMatches": "\\[.*\\]"
326
+ },
327
+ {
328
+ "nodeType": "StringLiteral",
329
+ "valueMatches": "\\(.*\\)"
330
+ }
331
+ ]
332
+ }
333
+ },
334
+ "excludeContext": [
335
+ "StringLiteral",
336
+ "Comment"
337
+ ]
338
+ },
339
+ "doc_url": "https://angular.dev/reference/migrations"
340
+ },
341
+ {
342
+ "key": "test_ignoreChangesOutsideZone",
343
+ "summary": "Tests: ajouter ignoreChangesOutsideZone si problèmes",
344
+ "description": "Si les tests avec fixture.autoDetect rencontrent des problèmes d'ordre ou de timing, ajouter ignoreChangesOutsideZone: true dans la configuration de ZoneChangeDetection pour ignorer les changements déclenchés hors de la zone Angular.",
345
+ "estimated_time_per_occurrence": 5,
346
+ "onFile": null,
347
+ "fileTypes": [
348
+ "*.spec.ts"
349
+ ],
350
+ "regex": "fixture\\.autoDetect\\s*=\\s*true",
351
+ "category": "test",
352
+ "auto_fixable": false,
353
+ "migration_command": null,
354
+ "risk_level": "medium",
355
+ "code_description": "// Si tests échouent avec auto-detect:\nTestBed.configureTestingModule({\n providers: [\n provideZoneChangeDetection({\n ignoreChangesOutsideZone: true\n })\n ]\n});",
356
+ "astPattern": {
357
+ "nodeType": "BinaryExpression",
358
+ "left": {
359
+ "nodeType": "PropertyAccessExpression",
360
+ "object": "fixture",
361
+ "property": "autoDetect"
362
+ },
363
+ "right": {
364
+ "value": true
365
+ },
366
+ "excludeContext": [
367
+ "StringLiteral",
368
+ "Comment"
369
+ ],
370
+ "operatorKind": "EqualsToken"
371
+ },
372
+ "doc_url": "https://angular.dev/reference/migrations"
373
+ }
374
+ ]
@@ -0,0 +1,188 @@
1
+ [
2
+ {
3
+ "key": "guards_RedirectCommand",
4
+ "summary": "Guards peuvent retourner RedirectCommand",
5
+ "description": "Les guards de routage peuvent maintenant retourner RedirectCommand pour des redirections plus explicites et typées, offrant un meilleur contrôle que les simples UrlTree. Mettre à jour les signatures de type des guards.",
6
+ "estimated_time_per_occurrence": 8,
7
+ "onFile": null,
8
+ "fileTypes": [
9
+ "*.ts"
10
+ ],
11
+ "regex": "canActivate.*:.*boolean\\s*\\|\\s*UrlTree",
12
+ "category": "routing",
13
+ "auto_fixable": false,
14
+ "migration_command": null,
15
+ "risk_level": "medium",
16
+ "code_description": "// Avant:\ncanActivate(): boolean | UrlTree\n\n// Après:\ncanActivate(): boolean | UrlTree | RedirectCommand {\n return new RedirectCommand('/login');\n}",
17
+ "astPattern": {
18
+ "nodeType": "MethodDeclaration",
19
+ "name": [
20
+ "canActivate",
21
+ "canActivateChild",
22
+ "canDeactivate",
23
+ "canMatch"
24
+ ],
25
+ "returnType": {
26
+ "union": {
27
+ "contains": [
28
+ "boolean",
29
+ "UrlTree"
30
+ ],
31
+ "missing": "RedirectCommand"
32
+ }
33
+ },
34
+ "excludeContext": [
35
+ "StringLiteral",
36
+ "Comment"
37
+ ]
38
+ },
39
+ "doc_url": "https://angular.dev/reference/migrations"
40
+ },
41
+ {
42
+ "key": "guards_RedirectCommand_fn",
43
+ "summary": "Guards fonctionnels peuvent retourner RedirectCommand",
44
+ "description": "Les guards fonctionnels (CanActivateFn, CanMatchFn...) peuvent maintenant retourner RedirectCommand pour une meilleure expressivité des redirections.",
45
+ "estimated_time_per_occurrence": 6,
46
+ "fileTypes": [
47
+ "*.ts"
48
+ ],
49
+ "regex": "\\bCan(?:Activate|Match|Deactivate|Load)Fn\\b[\\s\\S]*?boolean\\s*\\|\\s*UrlTree(?![\\s\\S]*RedirectCommand)",
50
+ "category": "routing",
51
+ "auto_fixable": false,
52
+ "risk_level": "medium",
53
+ "code_description": "// Avant:\nexport const authGuard: CanActivateFn = (route, state) => {\n return Authservice.isAuth() ? true : inject(Router).createUrlTree(['/login']);\n};\n\n// Après:\nexport const authGuard: CanActivateFn = (route, state) => {\n return Authservice.isAuth() ? true : new RedirectCommand('/login');\n};",
54
+ "astPattern": {
55
+ "nodeType": "VariableDeclaration",
56
+ "type": {
57
+ "containsAny": [
58
+ "CanActivateFn",
59
+ "CanMatchFn",
60
+ "CanDeactivateFn",
61
+ "CanLoadFn"
62
+ ]
63
+ },
64
+ "initializer": {
65
+ "nodeType": "ArrowFunction"
66
+ },
67
+ "returnType": {
68
+ "union": {
69
+ "contains": [
70
+ "boolean",
71
+ "UrlTree"
72
+ ],
73
+ "missing": "RedirectCommand"
74
+ }
75
+ }
76
+ },
77
+ "doc_url": "https://angular.dev/guide/router#redirectcommand"
78
+ },
79
+ {
80
+ "key": "ng_content_fallback",
81
+ "summary": "Utiliser fallback content dans ng-content",
82
+ "description": "Angular 18 permet de définir un contenu par défaut à l'intérieur de ng-content qui sera affiché si aucun contenu n'est projeté. Utile pour créer des composants avec des valeurs par défaut sans logique conditionnelle complexe.",
83
+ "estimated_time_per_occurrence": 3,
84
+ "onFile": null,
85
+ "fileTypes": [
86
+ "*.html",
87
+ "*.ts"
88
+ ],
89
+ "regex": "<ng-content[^>]*></ng-content>",
90
+ "astPattern": {
91
+ "nodeType": "Element",
92
+ "name": "ng-content",
93
+ "hasChildren": false,
94
+ "excludeContext": [
95
+ "Comment"
96
+ ]
97
+ },
98
+ "category": "template",
99
+ "auto_fixable": false,
100
+ "migration_command": null,
101
+ "risk_level": "low",
102
+ "code_description": "// Avant:\n<ng-content></ng-content>\n\n// Après:\n<ng-content>\n <div class=\"default\">Contenu par défaut</div>\n</ng-content>",
103
+ "doc_url": "https://angular.dev/reference/migrations"
104
+ },
105
+ {
106
+ "key": "http_cache_auth",
107
+ "summary": "Cache HTTP avec headers auth",
108
+ "description": "Par défaut, le cache HTTP de transfert d'état exclut les requêtes avec headers d'authentification. Activer includeRequestsWithAuthHeaders: true si votre application nécessite le cache de ces requêtes.",
109
+ "estimated_time_per_occurrence": 5,
110
+ "fileTypes": [
111
+ "*.ts"
112
+ ],
113
+ "category": "http",
114
+ "risk_level": "low",
115
+ "auto_fixable": false,
116
+ "regex": "provideHttpClient\\s*\\([^)]*withHttpTransferCache\\s*\\([^)]*\\)",
117
+ "code_description": "provideHttpClient(\n withHttpTransferCache({ \n includeRequestsWithAuthHeaders: true \n })\n)",
118
+ "astPattern": {
119
+ "nodeType": "CallExpression",
120
+ "functionName": "provideHttpClient",
121
+ "arguments": {
122
+ "containsCall": {
123
+ "functionName": "withHttpTransferCache",
124
+ "object": {
125
+ "properties": {
126
+ "includeRequestsWithAuthHeaders": {
127
+ "missing": true
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ },
134
+ "doc_url": "https://angular.dev/reference/migrations"
135
+ },
136
+ {
137
+ "key": "partial_hydration_defer",
138
+ "summary": "Hydratation partielle avec @defer SSR",
139
+ "description": "L'hydratation partielle avec @defer permet de rendre des composants côté serveur mais de différer leur hydratation côté client, réduisant le JavaScript initial et améliorant le TTI. Cette règle identifie les blocs @defer dont la configuration est sous-optimale (absence de déclencheur, de placeholder, ou usage non différé), afin d'améliorer la qualité du rendu progressif et la performance SSR.",
140
+ "estimated_time_per_occurrence": 15,
141
+ "fileTypes": [
142
+ "*.html",
143
+ "*.ts"
144
+ ],
145
+ "category": "ssr",
146
+ "risk_level": "medium",
147
+ "auto_fixable": false,
148
+ "regex": "(?<!<!--[^>]*?)@defer\\s*\\(",
149
+ "astPattern": {
150
+ "nodeType": "DeferredBlock",
151
+ "excludeContext": [
152
+ "Comment"
153
+ ]
154
+ },
155
+ "code_description": "@defer (on viewport) {\n <heavy-component />\n} @placeholder {\n <div>Chargement...</div>\n}",
156
+ "doc_url": "https://angular.dev/reference/migrations"
157
+ },
158
+ {
159
+ "key": "decouple_legacy_providers",
160
+ "summary": "Découpler les services fournis dans des modules ou composants",
161
+ "description": "Détecte les services Angular encore déclarés dans des tableaux `providers` d’un `@NgModule` ou d’un `@Component`. Depuis Angular standalone, il est recommandé que les services soient autonomes et marqués `providedIn: 'root'` pour être des singletons globaux. Les providers locaux créent des instances dupliquées et complexifient la gestion d’état.",
162
+ "estimated_time_per_occurrence": 25,
163
+ "onFile": null,
164
+ "fileTypes": ["*.ts"],
165
+ "regex": "@(?:NgModule|Component)\\s*\\([^)]*\\bproviders\\s*:\\s*\\[[^\\]]*\\]",
166
+ "category": "architecture",
167
+ "auto_fixable": false,
168
+ "migration_command": null,
169
+ "risk_level": "high",
170
+ "code_description": "// Avant (ancien modèle):\n@NgModule({\n providers: [UserService, AuthService]\n})\nexport class UserModule {}\n\n@Component({\n selector: 'app-profile',\n providers: [ProfileService]\n})\nexport class ProfileComponent {}\n\n// Après (standalone / moderne):\n@Injectable({ providedIn: 'root' })\nexport class UserService {}\n\n@Injectable({ providedIn: 'root' })\nexport class ProfileService {}\n\n// Puis retirer les providers des décorateurs.",
171
+ "astPattern": {
172
+ "nodeType": ["Identifier", "CallExpression"],
173
+ "context": "ProvidersArray",
174
+ "referTo": {
175
+ "decorator": "Injectable",
176
+ "elementNodeType": ["Identifier", "CallExpression"],
177
+ "propertyNotEqual": {
178
+ "key": "providedIn",
179
+ "value": "root"
180
+ }
181
+ },
182
+ "excludeContext": [
183
+ "StringLiteral",
184
+ "Comment"
185
+ ]
186
+ }
187
+ }
188
+ ]