@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,408 @@
|
|
|
1
|
+
# Guide Migration Angular 17→18 avec Exemples
|
|
2
|
+
|
|
3
|
+
## 🔴 RÈGLES OBLIGATOIRES (Breaking Changes)
|
|
4
|
+
|
|
5
|
+
### 1. Environnement
|
|
6
|
+
```bash
|
|
7
|
+
# ❌ Avant: Node v16, TypeScript 4.9
|
|
8
|
+
# ✅ Après:
|
|
9
|
+
node --version # v18.19.1+
|
|
10
|
+
npm install typescript@~5.4.0
|
|
11
|
+
ng update @angular/core@18 @angular/cli@18
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### 2. Imports à modifier
|
|
15
|
+
```typescript
|
|
16
|
+
// ❌ Avant
|
|
17
|
+
import { async } from '@angular/core';
|
|
18
|
+
import { StateKey, TransferState } from '@angular/platform-browser';
|
|
19
|
+
|
|
20
|
+
// ✅ Après
|
|
21
|
+
import { waitForAsync } from '@angular/core';
|
|
22
|
+
import { StateKey, TransferState } from '@angular/core';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### 3. APIs supprimées
|
|
26
|
+
```typescript
|
|
27
|
+
// ❌ Avant
|
|
28
|
+
animationDriver.matchesElement(element, selector);
|
|
29
|
+
if (isPlatformWorkerUi(platformId)) { }
|
|
30
|
+
testability.increasePendingRequestCount();
|
|
31
|
+
|
|
32
|
+
// ✅ Après
|
|
33
|
+
// Supprimer matchesElement - utiliser une autre approche
|
|
34
|
+
// Supprimer isPlatformWorkerUi - plus supporté
|
|
35
|
+
// Supprimer Testability methods - géré par ZoneJS
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 4. Platform Server
|
|
39
|
+
```typescript
|
|
40
|
+
// ❌ Avant
|
|
41
|
+
import { platformDynamicServer } from '@angular/platform-server';
|
|
42
|
+
import { ServerTransferStateModule } from '@angular/platform-server';
|
|
43
|
+
|
|
44
|
+
@NgModule({
|
|
45
|
+
imports: [ServerTransferStateModule]
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
// ✅ Après
|
|
49
|
+
import { platformServer } from '@angular/platform-server';
|
|
50
|
+
import '@angular/compiler';
|
|
51
|
+
// ServerTransferStateModule supprimé - plus nécessaire
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### 5. Routing
|
|
55
|
+
```typescript
|
|
56
|
+
// ❌ Avant
|
|
57
|
+
const route: Route = {
|
|
58
|
+
path: 'old',
|
|
59
|
+
redirectTo: '/new' // string uniquement
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// ✅ Après
|
|
63
|
+
const route: Route = {
|
|
64
|
+
path: 'old',
|
|
65
|
+
redirectTo: () => {
|
|
66
|
+
// Peut être une fonction
|
|
67
|
+
return '/new';
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// Guards peuvent retourner RedirectCommand
|
|
72
|
+
canActivate(): boolean | UrlTree | RedirectCommand {
|
|
73
|
+
return new RedirectCommand('/login');
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 6. Templates ngModel
|
|
78
|
+
```typescript
|
|
79
|
+
// ❌ Avant
|
|
80
|
+
template: `<input [(ngModel)]="user.name = processName(user.name)">`
|
|
81
|
+
|
|
82
|
+
// ✅ Après
|
|
83
|
+
template: `<input [(ngModel)]="user.name" (ngModelChange)="onNameChange($event)">`
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 7. Providers Environment
|
|
87
|
+
```typescript
|
|
88
|
+
// ❌ Avant
|
|
89
|
+
@Component({
|
|
90
|
+
template: `<router-outlet></router-outlet>`,
|
|
91
|
+
providers: [MyService] // Provider dans le composant avec RouterOutlet
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
// ✅ Après
|
|
95
|
+
bootstrapApplication(App, {
|
|
96
|
+
providers: [MyService] // Déplacer vers bootstrap
|
|
97
|
+
});
|
|
98
|
+
// OU dans la config de route
|
|
99
|
+
const routes: Routes = [{
|
|
100
|
+
path: 'feature',
|
|
101
|
+
providers: [MyService],
|
|
102
|
+
loadChildren: () => import('./feature')
|
|
103
|
+
}];
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 8. Tests Change Detection
|
|
107
|
+
```typescript
|
|
108
|
+
// ❌ Tests qui échouent avec multiples détections
|
|
109
|
+
beforeEach(() => {
|
|
110
|
+
fixture = TestBed.createComponent(Component);
|
|
111
|
+
fixture.autoDetect = true; // Peut causer des problèmes d'ordre
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ✅ Après - Si problèmes, ajouter:
|
|
115
|
+
TestBed.configureTestingModule({
|
|
116
|
+
providers: [
|
|
117
|
+
provideZoneChangeDetection({
|
|
118
|
+
ignoreChangesOutsideZone: true
|
|
119
|
+
})
|
|
120
|
+
]
|
|
121
|
+
});
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### 9. OnPush Components
|
|
125
|
+
```typescript
|
|
126
|
+
// ❌ Avant - Host bindings non mis à jour
|
|
127
|
+
@Component({
|
|
128
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
129
|
+
host: { '[class.active]': 'isActive' }
|
|
130
|
+
})
|
|
131
|
+
export class MyComponent {
|
|
132
|
+
isActive = false;
|
|
133
|
+
toggle() {
|
|
134
|
+
this.isActive = true; // Binding peut ne pas se mettre à jour
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ✅ Après
|
|
139
|
+
export class MyComponent {
|
|
140
|
+
constructor(private cdr: ChangeDetectorRef) {}
|
|
141
|
+
|
|
142
|
+
toggle() {
|
|
143
|
+
this.isActive = true;
|
|
144
|
+
this.cdr.markForCheck(); // Forcer la détection
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 🟡 RÈGLES RECOMMANDÉES
|
|
152
|
+
|
|
153
|
+
### 1. Mode Sans Zones
|
|
154
|
+
```typescript
|
|
155
|
+
// main.ts
|
|
156
|
+
// ❌ Ancien mode avec zone.js
|
|
157
|
+
bootstrapApplication(App);
|
|
158
|
+
|
|
159
|
+
// ✅ Nouveau mode expérimental
|
|
160
|
+
import { provideExperimentalZonelessChangeDetection } from '@angular/core';
|
|
161
|
+
|
|
162
|
+
bootstrapApplication(App, {
|
|
163
|
+
providers: [
|
|
164
|
+
provideExperimentalZonelessChangeDetection()
|
|
165
|
+
]
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// angular.json - retirer zone.js des polyfills
|
|
169
|
+
"polyfills": [
|
|
170
|
+
// "zone.js" ← Supprimer
|
|
171
|
+
]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### 2. Coalescence
|
|
175
|
+
```typescript
|
|
176
|
+
// ❌ Sans coalescence (multiples détections)
|
|
177
|
+
@Component({
|
|
178
|
+
template: `
|
|
179
|
+
<button (click)="onClick()">
|
|
180
|
+
<button (click)="onClick2()">
|
|
181
|
+
`
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
// ✅ Avec coalescence
|
|
185
|
+
bootstrapApplication(App, {
|
|
186
|
+
providers: [
|
|
187
|
+
provideZoneChangeDetection({ eventCoalescing: true })
|
|
188
|
+
]
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 3. Signaux
|
|
193
|
+
```typescript
|
|
194
|
+
// ❌ Avant
|
|
195
|
+
@Component({
|
|
196
|
+
template: `{{ count }}`
|
|
197
|
+
})
|
|
198
|
+
export class Counter {
|
|
199
|
+
count = 0;
|
|
200
|
+
increment() {
|
|
201
|
+
this.count++;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ✅ Après avec signaux
|
|
206
|
+
@Component({
|
|
207
|
+
template: `{{ count() }}`
|
|
208
|
+
})
|
|
209
|
+
export class Counter {
|
|
210
|
+
count = signal(0);
|
|
211
|
+
increment() {
|
|
212
|
+
this.count.update(v => v + 1);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 4. Event Replay (SSR)
|
|
218
|
+
```typescript
|
|
219
|
+
// main.server.ts
|
|
220
|
+
bootstrapApplication(App, {
|
|
221
|
+
providers: [
|
|
222
|
+
provideClientHydration(withEventReplay())
|
|
223
|
+
]
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 5. Forms Events
|
|
228
|
+
```typescript
|
|
229
|
+
// ❌ Avant
|
|
230
|
+
const control = new FormControl();
|
|
231
|
+
control.valueChanges.subscribe(v => {});
|
|
232
|
+
control.statusChanges.subscribe(s => {});
|
|
233
|
+
|
|
234
|
+
// ✅ Après
|
|
235
|
+
const control = new FormControl();
|
|
236
|
+
control.events.subscribe(event => {
|
|
237
|
+
if (event instanceof ValueChangeEvent) { }
|
|
238
|
+
if (event instanceof StatusChangeEvent) { }
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## 🟢 RÈGLES OPTIONNELLES
|
|
245
|
+
|
|
246
|
+
### 1. ng-content par défaut
|
|
247
|
+
```typescript
|
|
248
|
+
// ❌ Avant
|
|
249
|
+
@Component({
|
|
250
|
+
template: `<ng-content></ng-content>`
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
// ✅ Après
|
|
254
|
+
@Component({
|
|
255
|
+
template: `
|
|
256
|
+
<ng-content select=".header">
|
|
257
|
+
<div class="default-header">Titre par défaut</div>
|
|
258
|
+
</ng-content>
|
|
259
|
+
<ng-content>Contenu par défaut</ng-content>
|
|
260
|
+
`
|
|
261
|
+
})
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 2. HTTP Cache Auth
|
|
265
|
+
```typescript
|
|
266
|
+
// Pour apps avec auth
|
|
267
|
+
bootstrapApplication(App, {
|
|
268
|
+
providers: [
|
|
269
|
+
provideHttpClient(
|
|
270
|
+
withHttpTransferCache({
|
|
271
|
+
includeRequestsWithAuthHeaders: true
|
|
272
|
+
})
|
|
273
|
+
)
|
|
274
|
+
]
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### 3. Hydratation Partielle
|
|
279
|
+
```typescript
|
|
280
|
+
// Template avec defer
|
|
281
|
+
@Component({
|
|
282
|
+
template: `
|
|
283
|
+
@defer (render on server; on viewport) {
|
|
284
|
+
<heavy-component />
|
|
285
|
+
}
|
|
286
|
+
@placeholder {
|
|
287
|
+
<div>Chargement...</div>
|
|
288
|
+
}
|
|
289
|
+
`
|
|
290
|
+
})
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## 📊 Checklist Migration Complète
|
|
296
|
+
|
|
297
|
+
```typescript
|
|
298
|
+
// migration-check.ts
|
|
299
|
+
interface MigrationStatus {
|
|
300
|
+
obligatoire: {
|
|
301
|
+
node18: boolean; // node --version >= 18.19
|
|
302
|
+
typescript5: boolean; // tsc --version >= 5.4
|
|
303
|
+
imports: boolean; // waitForAsync, StateKey, TransferState
|
|
304
|
+
platformServer: boolean; // platformDynamicServer -> platformServer
|
|
305
|
+
routing: boolean; // RedirectCommand, redirectTo function
|
|
306
|
+
ngModelExpressions: boolean; // Pas d'assignation dans [(ngModel)]
|
|
307
|
+
testability: boolean; // Supprimer increasePendingRequestCount
|
|
308
|
+
resourceCache: boolean; // Supprimer RESOURCE_CACHE_PROVIDER
|
|
309
|
+
serverTransfer: boolean; // Supprimer ServerTransferStateModule
|
|
310
|
+
environmentProviders: boolean; // Déplacer de RouterOutlet
|
|
311
|
+
onPushDetection: boolean; // markForCheck() pour host bindings
|
|
312
|
+
testDetection: boolean; // ignoreChangesOutsideZone si nécessaire
|
|
313
|
+
};
|
|
314
|
+
recommandee: {
|
|
315
|
+
zoneless?: boolean; // provideExperimentalZonelessChangeDetection
|
|
316
|
+
coalescence: boolean; // eventCoalescing: true
|
|
317
|
+
signals?: boolean; // signal() usage
|
|
318
|
+
eventReplay?: boolean; // SSR withEventReplay
|
|
319
|
+
formsEvents?: boolean; // control.events au lieu de multiple subscribes
|
|
320
|
+
};
|
|
321
|
+
optionnelle: {
|
|
322
|
+
ngContent?: boolean; // default content
|
|
323
|
+
httpCache?: boolean; // includeRequestsWithAuthHeaders
|
|
324
|
+
partialHydration?: boolean; // @defer SSR
|
|
325
|
+
asyncAwait?: boolean; // natif sans zones
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## 🚀 Script Migration Automatisé
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
#!/bin/bash
|
|
334
|
+
# migration-v18.sh
|
|
335
|
+
|
|
336
|
+
echo "🔄 Angular 17 -> 18 Migration Starting..."
|
|
337
|
+
|
|
338
|
+
# 1. Backup
|
|
339
|
+
git checkout -b migration-angular-18
|
|
340
|
+
git add . && git commit -m "Pre-migration backup"
|
|
341
|
+
|
|
342
|
+
# 2. Update deps
|
|
343
|
+
echo "📦 Updating dependencies..."
|
|
344
|
+
npm install typescript@~5.4.0
|
|
345
|
+
ng update @angular/core@18 @angular/cli@18 --verbose
|
|
346
|
+
|
|
347
|
+
# 3. Fix imports automatiquement
|
|
348
|
+
echo "🔧 Fixing imports..."
|
|
349
|
+
find . -name "*.ts" -not -path "*/node_modules/*" | while read file; do
|
|
350
|
+
# async -> waitForAsync
|
|
351
|
+
sed -i "s/import { async }/import { waitForAsync }/g" "$file"
|
|
352
|
+
sed -i "s/async(/waitForAsync(/g" "$file"
|
|
353
|
+
|
|
354
|
+
# StateKey, TransferState
|
|
355
|
+
sed -i "s/@angular\/platform-browser'/@angular\/core'/g" "$file"
|
|
356
|
+
|
|
357
|
+
# platformDynamicServer -> platformServer
|
|
358
|
+
sed -i "s/platformDynamicServer/platformServer/g" "$file"
|
|
359
|
+
|
|
360
|
+
# Remove ServerTransferStateModule
|
|
361
|
+
sed -i "/ServerTransferStateModule/d" "$file"
|
|
362
|
+
done
|
|
363
|
+
|
|
364
|
+
# 4. Add compiler import where needed
|
|
365
|
+
echo "import '@angular/compiler';" >> src/main.server.ts
|
|
366
|
+
|
|
367
|
+
# 5. Verify & Test
|
|
368
|
+
echo "🧪 Running tests..."
|
|
369
|
+
ng test --no-watch --code-coverage
|
|
370
|
+
ng build --configuration production
|
|
371
|
+
|
|
372
|
+
echo "✅ Migration complete! Check git diff for review"
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
## ⚠️ Points d'Attention & Validation
|
|
376
|
+
|
|
377
|
+
| Catégorie | Risque | Solution | Vérification |
|
|
378
|
+
|-----------|--------|----------|--------------|
|
|
379
|
+
| Tests | `whenStable()` plus lent | `ignoreChangesOutsideZone: true` | `ng test` passe |
|
|
380
|
+
| OnPush | Host bindings non mis à jour | `markForCheck()` manuel | Vérifier les `@HostBinding` |
|
|
381
|
+
| SSR | Event loss avant hydratation | Activer Event Replay | Tester interactions précoces |
|
|
382
|
+
| Platform Server | URLs incorrectes | Pathname avec `/` final | Vérifier routes SSR |
|
|
383
|
+
| Guards | Redirections non appliquées | Utiliser `RedirectCommand` | Tester auth flows |
|
|
384
|
+
| Providers | Services non disponibles | Déplacer vers bootstrap | Vérifier injection |
|
|
385
|
+
|
|
386
|
+
## 📈 Validation Finale
|
|
387
|
+
|
|
388
|
+
```typescript
|
|
389
|
+
// validation.spec.ts
|
|
390
|
+
describe('Migration Angular 18 Validation', () => {
|
|
391
|
+
it('should verify all obligatory changes', () => {
|
|
392
|
+
// Node version
|
|
393
|
+
expect(process.version).toMatch(/^v(18\.19|[2-9]\d)/);
|
|
394
|
+
|
|
395
|
+
// TypeScript version
|
|
396
|
+
const ts = require('typescript');
|
|
397
|
+
expect(ts.version).toMatch(/^5\.[4-9]/);
|
|
398
|
+
|
|
399
|
+
// No deprecated imports
|
|
400
|
+
const hasAsync = /import.*async.*from.*@angular\/core/.test(code);
|
|
401
|
+
expect(hasAsync).toBe(false);
|
|
402
|
+
|
|
403
|
+
// No ServerTransferStateModule
|
|
404
|
+
const hasSTSM = /ServerTransferStateModule/.test(code);
|
|
405
|
+
expect(hasSTSM).toBe(false);
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
```
|