@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.
- package/LICENSE +96 -0
- package/README.fr.md +359 -0
- package/README.md +360 -0
- package/SECURITY.md +187 -0
- package/dist/client.bundle.js +357 -0
- package/dist/src/core/app-analyzer.js +134 -0
- package/dist/src/core/ast/matchers/html/html-attribute-matcher.js +86 -0
- package/dist/src/core/ast/matchers/html/html-component-matcher.js +40 -0
- package/dist/src/core/ast/matchers/html/html-element-matcher.js +54 -0
- package/dist/src/core/ast/matchers/html/html-parser.js +58 -0
- package/dist/src/core/ast/matchers/html/html-pipe-matcher.js +95 -0
- package/dist/src/core/ast/matchers/html/html-text-matcher.js +53 -0
- package/dist/src/core/ast/matchers/html/index.js +118 -0
- package/dist/src/core/ast/matchers/index.js +377 -0
- package/dist/src/core/ast/matchers/ts/collection-matcher.js +51 -0
- package/dist/src/core/ast/matchers/ts/context-matcher.js +275 -0
- package/dist/src/core/ast/matchers/ts/decorator-matcher.js +465 -0
- package/dist/src/core/ast/matchers/ts/expression-matcher.js +237 -0
- package/dist/src/core/ast/matchers/ts/file-matcher.js +97 -0
- package/dist/src/core/ast/matchers/ts/hierarchy-matcher.js +172 -0
- package/dist/src/core/ast/matchers/ts/import-matcher.js +39 -0
- package/dist/src/core/ast/matchers/ts/index.js +53 -0
- package/dist/src/core/ast/matchers/ts/node-matcher.js +156 -0
- package/dist/src/core/ast/matchers/ts/symbol-matcher.js +281 -0
- package/dist/src/core/ast/matchers/ts/type-matcher.js +207 -0
- package/dist/src/core/ast/matchers/utils/matcher-helpers.js +37 -0
- package/dist/src/core/ast/scanner-ast.js +444 -0
- package/dist/src/core/project-detector.js +196 -0
- package/dist/src/core/project-strategy/index.js +9 -0
- package/dist/src/core/project-strategy/nx-strategy.js +130 -0
- package/dist/src/core/project-strategy/project-strategy.interface.js +2 -0
- package/dist/src/core/project-strategy/standalone-strategy.js +74 -0
- package/dist/src/core/project-strategy/strategy-factory.js +15 -0
- package/dist/src/core/rules-loader.js +89 -0
- package/dist/src/core/scan-reporter.js +316 -0
- package/dist/src/core/scanner-delta.js +339 -0
- package/dist/src/core/scanner-orchestrator.js +266 -0
- package/dist/src/core/scanner-regex.js +298 -0
- package/dist/src/core/workload/calculator.js +82 -0
- package/dist/src/core/workload/constants.js +15 -0
- package/dist/src/core/workload/grouping.js +18 -0
- package/dist/src/core/workload/hierarchy-calculator.js +127 -0
- package/dist/src/core/workload/index.js +11 -0
- package/dist/src/core/workload/metadata.js +20 -0
- package/dist/src/core/workload/special-workload.js +101 -0
- package/dist/src/core/workload/target-resolver.js +34 -0
- package/dist/src/data/angular-migration-rules.json +2337 -0
- package/dist/src/data/markdown/angular-migration-17-18.md +408 -0
- package/dist/src/data/markdown/angular-migration-18-19.md +600 -0
- package/dist/src/data/markdown/angular-migration-19-20.md +521 -0
- package/dist/src/data/rules/rearchitecture/rearchitecture-rules.json +66 -0
- package/dist/src/data/rules/to18/rules-18-obligatoire.json +374 -0
- package/dist/src/data/rules/to18/rules-18-optionnelle.json +188 -0
- package/dist/src/data/rules/to18/rules-18-recommande.json +218 -0
- package/dist/src/data/rules/to19/rules-19-obligatoire.json +348 -0
- package/dist/src/data/rules/to19/rules-19-optionnelle.json +223 -0
- package/dist/src/data/rules/to19/rules-19-recommande.json +200 -0
- package/dist/src/data/rules/to20/rules-20-obligatoire.json +556 -0
- package/dist/src/data/rules/to20/rules-20-optionnelle.json +190 -0
- package/dist/src/data/rules/to20/rules-20-recommande.json +151 -0
- package/dist/src/index.js +161 -0
- package/dist/src/models/chip-config.js +45 -0
- package/dist/src/models/interfaces/app-details.interface.js +2 -0
- package/dist/src/models/interfaces/ast-interfaces.js +5 -0
- package/dist/src/models/interfaces/ast-pattern.interface.js +2 -0
- package/dist/src/models/interfaces/client-interfaces.js +6 -0
- package/dist/src/models/interfaces/detection-stats.interface.js +2 -0
- package/dist/src/models/interfaces/html-match.interface.js +2 -0
- package/dist/src/models/interfaces/html-report-data.interface.js +2 -0
- package/dist/src/models/interfaces/lib-details.interface.js +2 -0
- package/dist/src/models/interfaces/migration-rules.interface.js +2 -0
- package/dist/src/models/interfaces/parsed-args.interface.js +2 -0
- package/dist/src/models/interfaces/project-info.interface.js +2 -0
- package/dist/src/models/interfaces/project-overview-data.interface.js +2 -0
- package/dist/src/models/interfaces/rule-match.interface.js +2 -0
- package/dist/src/models/interfaces/rule.interface.js +2 -0
- package/dist/src/models/interfaces/rules-by-priority.interface.js +2 -0
- package/dist/src/models/interfaces/scanner-comparison.interface.js +2 -0
- package/dist/src/models/interfaces/special-workload.interface.js +2 -0
- package/dist/src/models/interfaces/workload-report.interface.js +2 -0
- package/dist/src/models/types/build-block-blob.type.js +2 -0
- package/dist/src/models/types/migration-version.type.js +2 -0
- package/dist/src/models/types/project-type.type.js +2 -0
- package/dist/src/models/types/risk-level.type.js +2 -0
- package/dist/src/models/types/rule-category.type.js +2 -0
- package/dist/src/models/types/rule-priority.type.js +2 -0
- package/dist/src/models/types/rule-workload-type.type.js +2 -0
- package/dist/src/templates/landing/applications-analyzed.template.js +18 -0
- package/dist/src/templates/landing/card-app-info.template.js +63 -0
- package/dist/src/templates/landing/card-lib-info.template.js +67 -0
- package/dist/src/templates/landing/libs-analyzed.template.js +22 -0
- package/dist/src/templates/landing/nx-summary.template.js +115 -0
- package/dist/src/templates/landing/project-overview.template.js +27 -0
- package/dist/src/templates/page/index-page.template.js +95 -0
- package/dist/src/templates/page/main.template.js +83 -0
- package/dist/src/templates/page/migration-guide.template.js +175 -0
- package/dist/src/templates/page/workload-report.template.js +53 -0
- package/dist/src/templates/workload/dashboard.template.js +184 -0
- package/dist/src/templates/workload/filters-panel.template.js +215 -0
- package/dist/src/templates/workload/guide-rule-card.template.js +107 -0
- package/dist/src/templates/workload/hierarchy-nx.template.js +104 -0
- package/dist/src/templates/workload/hierarchy-shared.js +163 -0
- package/dist/src/templates/workload/hierarchy-standalone.template.js +36 -0
- package/dist/src/templates/workload/hierarchy.template.js +35 -0
- package/dist/src/templates/workload/rule-modal.template.js +280 -0
- package/dist/src/utils/core/args-parser.js +123 -0
- package/dist/src/utils/core/array-helpers.js +18 -0
- package/dist/src/utils/core/ast-helpers.js +99 -0
- package/dist/src/utils/core/file-helpers.js +109 -0
- package/dist/src/utils/core/html-helpers.js +36 -0
- package/dist/src/utils/core/index.js +28 -0
- package/dist/src/utils/core/logger.js +38 -0
- package/dist/src/utils/core/rule-helpers.js +15 -0
- package/dist/src/utils/core/workload-formatter.js +6 -0
- package/dist/src/utils/shared/array-helpers.js +25 -0
- package/dist/src/utils/shared/date-helpers.js +109 -0
- package/dist/src/utils/shared/html-helpers.js +37 -0
- package/dist/src/utils/shared/index.js +25 -0
- package/dist/src/utils/shared/rule-helpers.js +20 -0
- package/dist/src/utils/shared/time-formatters.js +76 -0
- package/dist/styles.css +2 -0
- package/package.json +107 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"key": "redirectTo_function",
|
|
4
|
+
"summary": "redirectTo peut maintenant être une fonction",
|
|
5
|
+
"description": "La propriété redirectTo dans les routes Angular peut maintenant accepter une fonction en plus des strings, permettant des redirections dynamiques basées sur l'état de l'application. Cette fonctionnalité est optionnelle mais recommandée pour plus de flexibilité.",
|
|
6
|
+
"estimated_time_per_occurrence": 5,
|
|
7
|
+
"onFile": null,
|
|
8
|
+
"fileTypes": [
|
|
9
|
+
"*.ts"
|
|
10
|
+
],
|
|
11
|
+
"regex": "redirectTo\\s*:\\s*['\"]",
|
|
12
|
+
"category": "routing",
|
|
13
|
+
"auto_fixable": false,
|
|
14
|
+
"migration_command": null,
|
|
15
|
+
"risk_level": "low",
|
|
16
|
+
"code_description": "// Avant:\nredirectTo: '/new'\n\n// Après (optionnel):\nredirectTo: () => '/new'",
|
|
17
|
+
"astPattern": {
|
|
18
|
+
"nodeType": "PropertyAssignment",
|
|
19
|
+
"name": "redirectTo",
|
|
20
|
+
"initializer": {
|
|
21
|
+
"nodeType": "StringLiteral"
|
|
22
|
+
},
|
|
23
|
+
"excludeContext": [
|
|
24
|
+
"StringLiteral",
|
|
25
|
+
"Comment"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"key": "zoneless_ts_provider",
|
|
32
|
+
"summary": "Activer le mode zoneless via provider (main.ts)",
|
|
33
|
+
"description": "Active le mode Zoneless en ajoutant le provider `provideZonelessChangeDetection()` dans le bootstrap (`main.ts`). Cette approche supprime la dépendance à ZoneJS et améliore la performance de détection de changements.",
|
|
34
|
+
"estimated_time_per_occurrence": 30,
|
|
35
|
+
"onFile": null,
|
|
36
|
+
"fileTypes": [
|
|
37
|
+
"*.ts"
|
|
38
|
+
],
|
|
39
|
+
"regex": "\\bbootstrapApplication\\s*\\(",
|
|
40
|
+
"category": "architecture",
|
|
41
|
+
"auto_fixable": false,
|
|
42
|
+
"migration_command": null,
|
|
43
|
+
"risk_level": "high",
|
|
44
|
+
"code_description": "// Avant (exemple):\nbootstrapApplication(AppComponent, { providers: [] });\n\n// Après:\nbootstrapApplication(AppComponent, {\n providers: [provideZonelessChangeDetection()]\n});",
|
|
45
|
+
"astPattern": {
|
|
46
|
+
"nodeType": "CallExpression",
|
|
47
|
+
"functionName": "bootstrapApplication",
|
|
48
|
+
"excludeContext": [
|
|
49
|
+
"StringLiteral",
|
|
50
|
+
"Comment"
|
|
51
|
+
],
|
|
52
|
+
"arguments": {
|
|
53
|
+
"containsAny": [
|
|
54
|
+
{
|
|
55
|
+
"nodeType": "ObjectLiteralExpression",
|
|
56
|
+
"properties": {
|
|
57
|
+
"providers": {
|
|
58
|
+
"exists": true
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"nodeType": "ObjectLiteralExpression",
|
|
64
|
+
"properties": {}
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"doc_url": "https://angular.dev/guide/zoneless"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"key": "zoneless_remove_zone_polyfills",
|
|
73
|
+
"summary": "Zoneless: retirer zone.js des polyfills (build & test)",
|
|
74
|
+
"description": "Supprime `zone.js` et `zone.js/testing` des polyfills définis dans `angular.json`. Cette étape est nécessaire pour les applications utilisant le mode Zoneless (Angular 20).",
|
|
75
|
+
"estimated_time_per_occurrence": 30,
|
|
76
|
+
"onFile": null,
|
|
77
|
+
"fileTypes": [
|
|
78
|
+
"angular.json"
|
|
79
|
+
],
|
|
80
|
+
"regex": null,
|
|
81
|
+
"category": "architecture",
|
|
82
|
+
"auto_fixable": false,
|
|
83
|
+
"migration_command": null,
|
|
84
|
+
"risk_level": "high",
|
|
85
|
+
"code_description": "// Avant (angular.json):\n\"polyfills\": [\"zone.js\"],\n\"polyfills\": [\"zone.js/testing\"],\n\n// Après:\n\"polyfills\": [],\n// (ou supprimer les entrées liées à zone.js / zone.js/testing)",
|
|
86
|
+
"doc_url": "https://angular.dev/guide/zoneless"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"key": "event_coalescing",
|
|
90
|
+
"summary": "Activer event coalescing pour optimiser détection",
|
|
91
|
+
"description": "Event coalescing regroupe plusieurs événements déclenchés simultanément en un seul cycle de détection de changement, réduisant ainsi le nombre d'exécutions de change detection et améliorant les performances lors d'interactions utilisateur intensives.",
|
|
92
|
+
"estimated_time_per_occurrence": 5,
|
|
93
|
+
"onFile": null,
|
|
94
|
+
"fileTypes": [
|
|
95
|
+
"*.ts"
|
|
96
|
+
],
|
|
97
|
+
"regex": "provideZoneChangeDetection\\s*\\(",
|
|
98
|
+
"category": "performance",
|
|
99
|
+
"auto_fixable": false,
|
|
100
|
+
"migration_command": null,
|
|
101
|
+
"risk_level": "low",
|
|
102
|
+
"code_description": "bootstrapApplication(App, {\n providers: [\n provideZoneChangeDetection({ eventCoalescing: true })\n ]\n});",
|
|
103
|
+
"astPattern": {
|
|
104
|
+
"nodeType": "CallExpression",
|
|
105
|
+
"functionName": "provideZoneChangeDetection",
|
|
106
|
+
"arguments": {
|
|
107
|
+
"properties": {
|
|
108
|
+
"eventCoalescing": {
|
|
109
|
+
"missing": true
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"excludeContext": [
|
|
114
|
+
"StringLiteral",
|
|
115
|
+
"Comment"
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"key": "adopt_signals",
|
|
122
|
+
"summary": "Adopter les signaux pour réactivité optimisée",
|
|
123
|
+
"description": "Remplace les propriétés réactives classiques par l'API `signal()` d'Angular 18. Cette migration améliore la granularité de la réactivité et réduit la dépendance à la détection de changements globale. Applicable aux composants, directives ET services pour simplifier la gestion d'état.",
|
|
124
|
+
"estimated_time_per_occurrence": 10,
|
|
125
|
+
"onFile": null,
|
|
126
|
+
"fileTypes": [
|
|
127
|
+
"*.ts"
|
|
128
|
+
],
|
|
129
|
+
"regex": "(?<!signal\\s*\\()\\b(?:public|private|protected|readonly|static\\s+)*#?[a-zA-Z_]\\w*\\s*(?:!|\\?)?\\s*(?::[^=;]+)?=\\s*(\\d+|['\"][^'\"]*['\"]|\\[[\\s\\S]*?\\])",
|
|
130
|
+
"category": "architecture",
|
|
131
|
+
"auto_fixable": false,
|
|
132
|
+
"migration_command": null,
|
|
133
|
+
"risk_level": "high",
|
|
134
|
+
"code_description": "// Avant (Component):\ncount: number = 0;\nincrement() { this.count++; }\n\n// Après (Component):\ncount = signal(0);\nincrement() { this.count.update(v => v + 1); }\n\n// Avant (Service):\nprivate _user = new BehaviorSubject<User | null>(null);\n\n// Après (Service):\nuser = signal<User | null>(null);",
|
|
135
|
+
"astPattern": {
|
|
136
|
+
"nodeType": "PropertyDeclaration",
|
|
137
|
+
"initializer": {
|
|
138
|
+
"nodeType": [
|
|
139
|
+
"NumericLiteral",
|
|
140
|
+
"StringLiteral",
|
|
141
|
+
"ArrayLiteralExpression",
|
|
142
|
+
"ObjectLiteralExpression",
|
|
143
|
+
"TrueKeyword",
|
|
144
|
+
"FalseKeyword"
|
|
145
|
+
],
|
|
146
|
+
"notWrappedIn": ["signal", "inject", "computed", "effect"]
|
|
147
|
+
},
|
|
148
|
+
"inClass": {
|
|
149
|
+
"hasDecorator": [
|
|
150
|
+
"Component",
|
|
151
|
+
"Directive",
|
|
152
|
+
"Injectable"
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
"excludeContext": [
|
|
156
|
+
"StringLiteral",
|
|
157
|
+
"Comment"
|
|
158
|
+
]
|
|
159
|
+
},
|
|
160
|
+
"doc_url": "https://angular.dev/guide/signals"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"key": "event_replay_ssr",
|
|
164
|
+
"summary": "Activer Event Replay pour SSR",
|
|
165
|
+
"description": "Ajoute `provideClientHydration(withEventReplay())` pour activer la relecture des événements utilisateur après la réhydratation du DOM côté client (SSR Angular 19).",
|
|
166
|
+
"estimated_time_per_occurrence": 10,
|
|
167
|
+
"onFile": null,
|
|
168
|
+
"fileTypes": [
|
|
169
|
+
"*.ts"
|
|
170
|
+
],
|
|
171
|
+
"regex": "(?<![\"\\'])\\bprovideClientHydration\\s*\\(",
|
|
172
|
+
"category": "ssr",
|
|
173
|
+
"auto_fixable": false,
|
|
174
|
+
"migration_command": null,
|
|
175
|
+
"risk_level": "medium",
|
|
176
|
+
"code_description": "// main.server.ts\nbootstrapApplication(App, {\n providers: [\n provideClientHydration(withEventReplay())\n ]\n});",
|
|
177
|
+
"astPattern": {
|
|
178
|
+
"nodeType": "CallExpression",
|
|
179
|
+
"functionName": "provideClientHydration",
|
|
180
|
+
"arguments": {
|
|
181
|
+
"missing": "withEventReplay"
|
|
182
|
+
},
|
|
183
|
+
"excludeContext": [
|
|
184
|
+
"StringLiteral",
|
|
185
|
+
"Comment"
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
"doc_url": "https://angular.dev/guide/ssr#hydration"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"key": "forms_events_unified",
|
|
192
|
+
"summary": "Utiliser control.events unifié",
|
|
193
|
+
"description": "L'API control.events unifie valueChanges et statusChanges en un seul stream d'événements typés, simplifiant la gestion des changements de formulaires et offrant plus de types d'événements (PristineChangeEvent, TouchedChangeEvent, etc.).",
|
|
194
|
+
"estimated_time_per_occurrence": 5,
|
|
195
|
+
"onFile": null,
|
|
196
|
+
"fileTypes": [
|
|
197
|
+
"*.ts"
|
|
198
|
+
],
|
|
199
|
+
"regex": "\\.(valueChanges|statusChanges)[!?]?\\s*(?:\\.[\\s\\S]*?pipe\\([^)]*\\))?\\s*[\\n\\r\\s]*\\.?subscribe",
|
|
200
|
+
"category": "forms",
|
|
201
|
+
"auto_fixable": false,
|
|
202
|
+
"migration_command": null,
|
|
203
|
+
"risk_level": "low",
|
|
204
|
+
"code_description": "// Avant:\ncontrol.valueChanges.subscribe(v => {});\ncontrol.statusChanges.subscribe(s => {});\n\n// Après:\ncontrol.events.subscribe(event => {\n if (event instanceof ValueChangeEvent) { }\n if (event instanceof StatusChangeEvent) { }\n});",
|
|
205
|
+
"astPattern": {
|
|
206
|
+
"nodeType": "PropertyAccessExpression",
|
|
207
|
+
"propertyName": [
|
|
208
|
+
"valueChanges",
|
|
209
|
+
"statusChanges"
|
|
210
|
+
],
|
|
211
|
+
"excludeContext": [
|
|
212
|
+
"StringLiteral",
|
|
213
|
+
"Comment"
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
217
|
+
}
|
|
218
|
+
]
|
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"key": "angular_19_environment",
|
|
4
|
+
"summary": "Mise à jour environnement Angular 19 (Node 20.18.1+, TypeScript 5.5+)",
|
|
5
|
+
"description": "Angular 19 requiert Node.js 20.18.1 ou supérieur et TypeScript 5.5+. Cette version introduit les linked signals, le support amélioré du zoneless, et un nouveau système de schematics. Les versions antérieures ne sont plus compatibles.",
|
|
6
|
+
"estimated_time_per_occurrence": 20,
|
|
7
|
+
"onFile": "package.json",
|
|
8
|
+
"fileTypes": ["package.json"],
|
|
9
|
+
"regex": "\"@angular/(core|cli)\"\\s*:\\s*\"(?:(?:\\^|~)?1[0-8](?:\\.\\d+){0,2})\"",
|
|
10
|
+
"category": "environment",
|
|
11
|
+
"auto_fixable": false,
|
|
12
|
+
"migration_command": "npx ng update @angular/core@19 @angular/cli@19",
|
|
13
|
+
"risk_level": "high",
|
|
14
|
+
"code_description": "// Migration Angular 19\n// Node : >= 20.18.1\n// TypeScript : ~5.5.0\n// Commande :\n// nvm install 20.18.1\n// npm i typescript@~5.5.0\n// npx ng update @angular/core@19 @angular/cli@19",
|
|
15
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"key": "node_version_20",
|
|
19
|
+
"summary": "Mise à jour Node.js vers 20.18.1+",
|
|
20
|
+
"description": "Angular 18 nécessite Node.js version 20.18.1 ou supérieure pour supporter les nouvelles fonctionnalités TypeScript 5.5 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-9]|20\\.(?:[0-9]|1[0-7])(?:\\.[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 v20.18.1+\n// Commande: node --version",
|
|
32
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"key": "typescript_5_5",
|
|
36
|
+
"summary": "Mise à jour TypeScript vers 5.5+",
|
|
37
|
+
"description": "TypeScript 5.5 est requis pour Angular 19 car il inclut des améliorations critiques pour les inferred type predicates et le narrowing de types nécessaires aux nouvelles APIs de signaux. TypeScript 5.4 n'est plus supporté.",
|
|
38
|
+
"estimated_time_per_occurrence": 10,
|
|
39
|
+
"onFile": "package.json",
|
|
40
|
+
"fileTypes": [
|
|
41
|
+
"package.json"
|
|
42
|
+
],
|
|
43
|
+
"regex": "^(?![\\s\\S]*\"typescript\"[\\s\\S]*\"[<>=~^]*(?:5\\.[5-9]|[6-9]\\d*)\\.)[\\s\\S]+",
|
|
44
|
+
"category": "environment",
|
|
45
|
+
"auto_fixable": true,
|
|
46
|
+
"migration_command": "npm install typescript@~5.5.0",
|
|
47
|
+
"risk_level": "medium",
|
|
48
|
+
"code_description": "// package.json\n// Avant: \"typescript\": \"~5.4.0\"\n// Après: \"typescript\": \"~5.5.0\"",
|
|
49
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"key": "standalone_default",
|
|
53
|
+
"summary": "Angular 19 : standalone est maintenant true par défaut – ajoutez standalone: false ou migrez",
|
|
54
|
+
"description": "BREAKING CHANGE MAJEUR : Angular 19 définit `standalone: true` comme valeur par défaut. Les composants/directives/pipes déclarés dans un NgModule (via la propriété 'declarations') causeront une erreur de build : 'Component X is standalone, and cannot be declared in an NgModule'. Solution : ajouter explicitement `standalone: false` à chaque composant déclaré OU migrer vers l'architecture standalone via les schematics officiels Angular.",
|
|
55
|
+
"estimated_time_per_occurrence": 1,
|
|
56
|
+
"fileTypes": [
|
|
57
|
+
"*.ts"
|
|
58
|
+
],
|
|
59
|
+
"regex": "declarations:\\s*\\[",
|
|
60
|
+
"category": "architecture",
|
|
61
|
+
"auto_fixable": false,
|
|
62
|
+
"migration_command": "ng g @angular/core:convert-to-standalone && ng g @angular/core:remove-ng-modules && ng g @angular/core:bootstrap-standalone",
|
|
63
|
+
"risk_level": "critical",
|
|
64
|
+
"code_description": "// ⚠️ BREAKING : standalone est true par défaut à partir de v19\n// Les composants déclarés dans un NgModule causent une erreur de build\n\n// Avant (Angular ≤18) - Fonctionne :\n@NgModule({\n declarations: [AppComponent, UserComponent],\n imports: [CommonModule]\n})\nexport class AppModule {}\n\n@Component({ selector: 'app-root' })\nexport class AppComponent {} // Implicitement standalone: false\n\n// Angular 19 - ERREUR : \"Component AppComponent is standalone, and cannot be declared in an NgModule\"\n\n// Option 1 : Ajout explicite standalone: false (fix temporaire)\n@Component({\n selector: 'app-root',\n standalone: false // ✅ Explicite\n})\nexport class AppComponent {}\n\n// Option 2 : Migration complète vers standalone (recommandée)\n// ng g @angular/core:convert-to-standalone\n// ng g @angular/core:remove-ng-modules\n// ng g @angular/core:bootstrap-standalone",
|
|
65
|
+
"astPattern": {
|
|
66
|
+
"nodeType": "Decorator",
|
|
67
|
+
"name": "NgModule",
|
|
68
|
+
"properties": {
|
|
69
|
+
"declarations": {
|
|
70
|
+
"nodeType": "ArrayLiteralExpression",
|
|
71
|
+
"elements": {
|
|
72
|
+
"notEmpty": true
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"excludeContext": [
|
|
77
|
+
"StringLiteral",
|
|
78
|
+
"Comment"
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
"special_workload": {
|
|
82
|
+
"bb_fileTypes": ["*.module.ts"],
|
|
83
|
+
"bb_time_by_occurrence": 25
|
|
84
|
+
},
|
|
85
|
+
"doc_url": "https://angular.dev/reference/migrations/standalone"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"key": "template_refs_no_this",
|
|
89
|
+
"summary": "Supprimer 'this.' devant les template refs",
|
|
90
|
+
"description": "Angular 19 interdit l'utilisation du préfixe 'this.' devant les références de template (#ref) car elles ne sont pas des propriétés de classe mais des variables de template locales. Cette restriction améliore la clarté et évite les confusions.",
|
|
91
|
+
"estimated_time_per_occurrence": 2,
|
|
92
|
+
"onFile": null,
|
|
93
|
+
"fileTypes": [
|
|
94
|
+
"*.html"
|
|
95
|
+
],
|
|
96
|
+
"regex": "\\{\\{[^}]*\\bthis\\.",
|
|
97
|
+
"astPattern": {
|
|
98
|
+
"nodeType": "BoundText",
|
|
99
|
+
"textMatches": "\\bthis\\."
|
|
100
|
+
},
|
|
101
|
+
"category": "template",
|
|
102
|
+
"auto_fixable": true,
|
|
103
|
+
"migration_command": null,
|
|
104
|
+
"risk_level": "medium",
|
|
105
|
+
"code_description": "// Avant:\n<div #myDiv></div>\n{{ this.myDiv.textContent }}\n\n// Après:\n<div #myDiv></div>\n{{ myDiv.textContent }}",
|
|
106
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"key": "browserModule_withServerTransition",
|
|
110
|
+
"summary": "BrowserModule.withServerTransition → APP_ID token",
|
|
111
|
+
"description": "BrowserModule.withServerTransition est obsolète dans l'architecture standalone. Utiliser le token APP_ID directement dans les providers du bootstrap pour identifier l'application dans un contexte SSR multi-apps.",
|
|
112
|
+
"estimated_time_per_occurrence": 10,
|
|
113
|
+
"onFile": null,
|
|
114
|
+
"fileTypes": [
|
|
115
|
+
"*.ts"
|
|
116
|
+
],
|
|
117
|
+
"regex": "BrowserModule\\.withServerTransition",
|
|
118
|
+
"category": "imports",
|
|
119
|
+
"auto_fixable": false,
|
|
120
|
+
"migration_command": null,
|
|
121
|
+
"risk_level": "medium",
|
|
122
|
+
"code_description": "// Avant:\nBrowserModule.withServerTransition({ appId: 'my-app' })\n\n// Après:\nimport { APP_ID } from '@angular/core';\nbootstrapApplication(App, {\n providers: [{ provide: APP_ID, useValue: 'my-app' }]\n});",
|
|
123
|
+
"astPattern": {
|
|
124
|
+
"nodeType": "CallExpression",
|
|
125
|
+
"expression": {
|
|
126
|
+
"nodeType": "PropertyAccessExpression",
|
|
127
|
+
"expression": {
|
|
128
|
+
"nodeType": "Identifier",
|
|
129
|
+
"name": "BrowserModule"
|
|
130
|
+
},
|
|
131
|
+
"name": "withServerTransition"
|
|
132
|
+
},
|
|
133
|
+
"excludeContext": [
|
|
134
|
+
"StringLiteral",
|
|
135
|
+
"Comment"
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"key": "keyValueDiffers_factories",
|
|
142
|
+
"summary": "KeyValueDiffers.factories propriété supprimée",
|
|
143
|
+
"description": "La propriété factories de KeyValueDiffers est supprimée car elle exposait des détails d'implémentation internes. Utiliser directement les méthodes find() et create() qui offrent une API plus simple et plus stable.",
|
|
144
|
+
"estimated_time_per_occurrence": 5,
|
|
145
|
+
"onFile": null,
|
|
146
|
+
"fileTypes": [
|
|
147
|
+
"*.ts"
|
|
148
|
+
],
|
|
149
|
+
"regex": "\\.factories\\b",
|
|
150
|
+
"category": "api",
|
|
151
|
+
"auto_fixable": false,
|
|
152
|
+
"migration_command": null,
|
|
153
|
+
"risk_level": "low",
|
|
154
|
+
"code_description": "// Avant:\nconst factories = differs.factories;\n\n// Après:\n// Utiliser directement find() et create()\nconst differ = differs.find({}).create();",
|
|
155
|
+
"astPattern": {
|
|
156
|
+
"nodeType": "PropertyAccessExpression",
|
|
157
|
+
"propertyName": "factories",
|
|
158
|
+
"excludeContext": [
|
|
159
|
+
"StringLiteral",
|
|
160
|
+
"Comment"
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"key": "experimentalPendingTasks_to_pendingTasks",
|
|
167
|
+
"summary": "ExperimentalPendingTasks → PendingTasks",
|
|
168
|
+
"description": "L'API PendingTasks est maintenant stable et sort de sa phase expérimentale. Remplacer tous les imports et usages de ExperimentalPendingTasks par PendingTasks, l'API et le comportement restent identiques.",
|
|
169
|
+
"estimated_time_per_occurrence": 3,
|
|
170
|
+
"onFile": null,
|
|
171
|
+
"fileTypes": [
|
|
172
|
+
"*.ts"
|
|
173
|
+
],
|
|
174
|
+
"regex": "\\bExperimentalPendingTasks\\b",
|
|
175
|
+
"category": "api",
|
|
176
|
+
"auto_fixable": true,
|
|
177
|
+
"migration_command": null,
|
|
178
|
+
"risk_level": "low",
|
|
179
|
+
"code_description": "// Avant:\nimport { ExperimentalPendingTasks } from '@angular/core';\n\n// Après:\nimport { PendingTasks } from '@angular/core';",
|
|
180
|
+
"astPattern": {
|
|
181
|
+
"nodeType": "Identifier",
|
|
182
|
+
"name": "ExperimentalPendingTasks",
|
|
183
|
+
"excludeContext": [
|
|
184
|
+
"Comment",
|
|
185
|
+
"StringLiteral"
|
|
186
|
+
]
|
|
187
|
+
},
|
|
188
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"key": "router_errorHandler_migration",
|
|
192
|
+
"summary": "Router.errorHandler → withNavigationErrorHandler",
|
|
193
|
+
"description": "L'assignation directe de router.errorHandler est dépréciée au profit de withNavigationErrorHandler dans la configuration du router, offrant une meilleure intégration avec l'architecture standalone et permettant un tree-shaking plus efficace.",
|
|
194
|
+
"estimated_time_per_occurrence": 10,
|
|
195
|
+
"onFile": null,
|
|
196
|
+
"fileTypes": [
|
|
197
|
+
"*.ts"
|
|
198
|
+
],
|
|
199
|
+
"regex": "router\\.errorHandler\\s*=",
|
|
200
|
+
"category": "routing",
|
|
201
|
+
"auto_fixable": false,
|
|
202
|
+
"migration_command": null,
|
|
203
|
+
"risk_level": "medium",
|
|
204
|
+
"code_description": "// Avant:\nthis.router.errorHandler = (error) => { };\n\n// Après:\nprovideRouter(routes,\n withNavigationErrorHandler((error) => { })\n)",
|
|
205
|
+
"astPattern": {
|
|
206
|
+
"nodeType": "BinaryExpression",
|
|
207
|
+
"left": {
|
|
208
|
+
"nodeType": "PropertyAccessExpression",
|
|
209
|
+
"propertyName": "errorHandler"
|
|
210
|
+
},
|
|
211
|
+
"excludeContext": [
|
|
212
|
+
"StringLiteral",
|
|
213
|
+
"Comment"
|
|
214
|
+
],
|
|
215
|
+
"operatorKind": "EqualsToken"
|
|
216
|
+
},
|
|
217
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"key": "resolve_redirectCommand",
|
|
221
|
+
"summary": "Resolve peut retourner RedirectCommand",
|
|
222
|
+
"description": "Les resolvers peuvent maintenant retourner RedirectCommand pour gérer les redirections de manière plus explicite et typée. Mettre à jour les signatures de type pour inclure RedirectCommand dans les valeurs de retour possibles des resolvers.",
|
|
223
|
+
"estimated_time_per_occurrence": 8,
|
|
224
|
+
"onFile": null,
|
|
225
|
+
"fileTypes": [
|
|
226
|
+
"*.ts"
|
|
227
|
+
],
|
|
228
|
+
"regex": "implements\\s+Resolve<(?!.*RedirectCommand)",
|
|
229
|
+
"category": "routing",
|
|
230
|
+
"auto_fixable": false,
|
|
231
|
+
"migration_command": null,
|
|
232
|
+
"risk_level": "medium",
|
|
233
|
+
"code_description": "// Avant:\nResolve<User>\n\n// Après:\nResolve<User | RedirectCommand> {\n return this.service.get().pipe(\n catchError(() => of(new RedirectCommand('/error')))\n );\n}",
|
|
234
|
+
"astPattern": {
|
|
235
|
+
"nodeType": "ClassDeclaration",
|
|
236
|
+
"implements": "Resolve",
|
|
237
|
+
"implementsGeneric": {
|
|
238
|
+
"missing": "RedirectCommand"
|
|
239
|
+
},
|
|
240
|
+
"excludeContext": [
|
|
241
|
+
"StringLiteral",
|
|
242
|
+
"Comment"
|
|
243
|
+
]
|
|
244
|
+
},
|
|
245
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"key": "tests_effects_timing",
|
|
249
|
+
"summary": "Tests effects: ajouter await fixture.whenStable()",
|
|
250
|
+
"description": "Les effects Angular 19 s'exécutent de manière asynchrone et ne sont plus automatiquement flush dans les tests. Ajouter await fixture.whenStable() ou fixture.detectChanges() après avoir déclenché un effect pour s'assurer que toutes les mises à jour sont appliquées avant les assertions.",
|
|
251
|
+
"estimated_time_per_occurrence": 3,
|
|
252
|
+
"onFile": null,
|
|
253
|
+
"fileTypes": [
|
|
254
|
+
"*.spec.ts"
|
|
255
|
+
],
|
|
256
|
+
"regex": "triggerEffect|effect\\(\\s*\\(\\)",
|
|
257
|
+
"category": "test",
|
|
258
|
+
"auto_fixable": false,
|
|
259
|
+
"migration_command": null,
|
|
260
|
+
"risk_level": "medium",
|
|
261
|
+
"code_description": "// Avant:\ncomponent.triggerEffect();\nexpect(value).toBe('updated');\n\n// Après:\ncomponent.triggerEffect();\nawait fixture.whenStable();\nexpect(value).toBe('updated');",
|
|
262
|
+
"astPattern": {
|
|
263
|
+
"nodeType": "CallExpression",
|
|
264
|
+
"functionName": [
|
|
265
|
+
"effect",
|
|
266
|
+
"triggerEffect"
|
|
267
|
+
],
|
|
268
|
+
"inFile": "*.spec.ts",
|
|
269
|
+
"nextStatement": {
|
|
270
|
+
"notContains": [
|
|
271
|
+
"fixture.whenStable",
|
|
272
|
+
"fixture.detectChanges"
|
|
273
|
+
]
|
|
274
|
+
},
|
|
275
|
+
"excludeContext": [
|
|
276
|
+
"StringLiteral",
|
|
277
|
+
"Comment"
|
|
278
|
+
]
|
|
279
|
+
},
|
|
280
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"key": "fakeAsync_flush_default",
|
|
284
|
+
"summary": "fakeAsync flush automatique par défaut",
|
|
285
|
+
"description": "En Angular 19, fakeAsync flush automatiquement tous les timers en attente à la fin du test par défaut. Si l'ancien comportement est nécessaire (pas de flush automatique), passer l'option {flush: false} au wrapper fakeAsync.",
|
|
286
|
+
"estimated_time_per_occurrence": 5,
|
|
287
|
+
"onFile": null,
|
|
288
|
+
"fileTypes": [
|
|
289
|
+
"*.spec.ts"
|
|
290
|
+
],
|
|
291
|
+
"regex": "fakeAsync\\s*\\(",
|
|
292
|
+
"category": "test",
|
|
293
|
+
"auto_fixable": false,
|
|
294
|
+
"migration_command": null,
|
|
295
|
+
"risk_level": "low",
|
|
296
|
+
"code_description": "// En v19: flush automatique des timers\n// Pour ancien comportement:\nfakeAsync(() => {\n // ...\n}, { flush: false })",
|
|
297
|
+
"astPattern": {
|
|
298
|
+
"nodeType": "CallExpression",
|
|
299
|
+
"functionName": "fakeAsync",
|
|
300
|
+
"arguments": {
|
|
301
|
+
"count": 1,
|
|
302
|
+
"secondArgument": {
|
|
303
|
+
"missing": true
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
"excludeContext": [
|
|
307
|
+
"StringLiteral",
|
|
308
|
+
"Comment"
|
|
309
|
+
]
|
|
310
|
+
},
|
|
311
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
"key": "createComponent_projectableNodes",
|
|
315
|
+
"summary": "createComponent: passer projectableNodes vide pour éviter fallback",
|
|
316
|
+
"description": "createComponent affiche maintenant le contenu fallback par défaut si aucun projectableNodes n'est fourni. Pour éviter ce comportement et garder ng-content vide, passer explicitement projectableNodes avec un tableau contenant un nœud texte vide.",
|
|
317
|
+
"estimated_time_per_occurrence": 3,
|
|
318
|
+
"onFile": null,
|
|
319
|
+
"fileTypes": [
|
|
320
|
+
"*.ts"
|
|
321
|
+
],
|
|
322
|
+
"regex": "createComponent\\s*\\(",
|
|
323
|
+
"category": "api",
|
|
324
|
+
"auto_fixable": false,
|
|
325
|
+
"migration_command": null,
|
|
326
|
+
"risk_level": "low",
|
|
327
|
+
"code_description": "// Pour éviter fallback par défaut:\ncreateComponent(MyComponent, {\n projectableNodes: [[document.createTextNode('')]]\n});",
|
|
328
|
+
"astPattern": {
|
|
329
|
+
"nodeType": "CallExpression",
|
|
330
|
+
"functionName": "createComponent",
|
|
331
|
+
"arguments": {
|
|
332
|
+
"properties": {
|
|
333
|
+
"projectableNodes": {
|
|
334
|
+
"missing": true
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
"excludeContext": [
|
|
339
|
+
"StringLiteral",
|
|
340
|
+
"Comment"
|
|
341
|
+
],
|
|
342
|
+
"inFile": {
|
|
343
|
+
"exclude": "*.spec.ts"
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
"doc_url": "https://angular.dev/reference/migrations"
|
|
347
|
+
}
|
|
348
|
+
]
|