@craft-ng/dev-tools 0.5.0-beta.4 → 0.5.1-beta.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 (67) hide show
  1. package/README.md +132 -23
  2. package/package.json +6 -2
  3. package/src/bin/craft-migrate-primitives.d.ts +2 -0
  4. package/src/bin/craft-migrate-primitives.js +71 -0
  5. package/src/bin/craft-migrate-primitives.js.map +1 -0
  6. package/src/bin/craft-migrate-routes.d.ts +2 -0
  7. package/src/bin/craft-migrate-routes.js +77 -0
  8. package/src/bin/craft-migrate-routes.js.map +1 -0
  9. package/src/bin/craft-migrate-services.d.ts +2 -0
  10. package/src/bin/craft-migrate-services.js +75 -0
  11. package/src/bin/craft-migrate-services.js.map +1 -0
  12. package/src/bin/craft-migrate.d.ts +2 -0
  13. package/src/bin/craft-migrate.js +90 -0
  14. package/src/bin/craft-migrate.js.map +1 -0
  15. package/src/eslint-rules/global-exception-registry-match.cjs +4 -4
  16. package/src/eslint-rules/index.cjs +6 -0
  17. package/src/eslint-rules/require-craft-exception-handler.cjs +142 -0
  18. package/src/eslint-rules/require-exception-component-di-check.cjs +314 -0
  19. package/src/eslint-rules/require-lazy-load-with-retry.cjs +148 -0
  20. package/src/eslint-rules/require-pending-component-di-check.cjs +3 -3
  21. package/src/index.d.ts +8 -0
  22. package/src/index.js +8 -0
  23. package/src/index.js.map +1 -1
  24. package/src/scripts/angular-brand-codemod.d.ts +17 -0
  25. package/src/scripts/angular-brand-codemod.js +44 -8
  26. package/src/scripts/angular-brand-codemod.js.map +1 -1
  27. package/src/scripts/angular-brand-codemod.spec.ts +3 -3
  28. package/src/scripts/angular-brand-codemod.ts +78 -7
  29. package/src/scripts/migrate.d.ts +32 -0
  30. package/src/scripts/migrate.js +67 -0
  31. package/src/scripts/migrate.js.map +1 -0
  32. package/src/scripts/migrate.ts +128 -0
  33. package/src/scripts/migration-workspace.d.ts +2 -0
  34. package/src/scripts/migration-workspace.js +72 -0
  35. package/src/scripts/migration-workspace.js.map +1 -0
  36. package/src/scripts/migration-workspace.ts +93 -0
  37. package/src/scripts/primitives/migrate-primitives.d.ts +27 -0
  38. package/src/scripts/primitives/migrate-primitives.js +354 -0
  39. package/src/scripts/primitives/migrate-primitives.js.map +1 -0
  40. package/src/scripts/primitives/migrate-primitives.spec.ts +279 -0
  41. package/src/scripts/primitives/migrate-primitives.ts +543 -0
  42. package/src/scripts/primitives/migration-diagnostic.d.ts +8 -0
  43. package/src/scripts/primitives/migration-diagnostic.js +2 -0
  44. package/src/scripts/primitives/migration-diagnostic.js.map +1 -0
  45. package/src/scripts/primitives/migration-diagnostic.ts +13 -0
  46. package/src/scripts/routes/migrate-routes.d.ts +34 -0
  47. package/src/scripts/routes/migrate-routes.js +669 -0
  48. package/src/scripts/routes/migrate-routes.js.map +1 -0
  49. package/src/scripts/routes/migrate-routes.spec.ts +264 -0
  50. package/src/scripts/routes/migrate-routes.ts +897 -0
  51. package/src/scripts/routes/migration-diagnostic.d.ts +16 -0
  52. package/src/scripts/routes/migration-diagnostic.js +2 -0
  53. package/src/scripts/routes/migration-diagnostic.js.map +1 -0
  54. package/src/scripts/routes/migration-diagnostic.ts +25 -0
  55. package/src/scripts/services/config.d.ts +2 -0
  56. package/src/scripts/services/config.js +39 -0
  57. package/src/scripts/services/config.js.map +1 -0
  58. package/src/scripts/services/config.ts +60 -0
  59. package/src/scripts/services/migrate-services.d.ts +29 -0
  60. package/src/scripts/services/migrate-services.js +895 -0
  61. package/src/scripts/services/migrate-services.js.map +1 -0
  62. package/src/scripts/services/migrate-services.spec.ts +719 -0
  63. package/src/scripts/services/migrate-services.ts +1282 -0
  64. package/src/scripts/services/migration-diagnostic.d.ts +8 -0
  65. package/src/scripts/services/migration-diagnostic.js +2 -0
  66. package/src/scripts/services/migration-diagnostic.js.map +1 -0
  67. package/src/scripts/services/migration-diagnostic.ts +27 -0
@@ -0,0 +1,354 @@
1
+ import { __awaiter } from "tslib";
2
+ import { execFile } from 'node:child_process';
3
+ import { existsSync } from 'node:fs';
4
+ import { mkdir, writeFile } from 'node:fs/promises';
5
+ import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
6
+ import { promisify } from 'node:util';
7
+ import { Node, Project, QuoteKind, SyntaxKind, } from 'ts-morph';
8
+ const execFileAsync = promisify(execFile);
9
+ export function runPrimitivesMigration() {
10
+ return __awaiter(this, arguments, void 0, function* (options = {}) {
11
+ var _a, _b, _c;
12
+ const rootDir = resolve((_a = options.rootDir) !== null && _a !== void 0 ? _a : process.cwd());
13
+ const tsConfigFilePath = options.tsConfigFilePath
14
+ ? resolve(options.tsConfigFilePath)
15
+ : defaultTsConfig(rootDir);
16
+ const project = new Project(Object.assign(Object.assign({}, (existsSync(tsConfigFilePath) ? { tsConfigFilePath } : {})), { manipulationSettings: { quoteKind: QuoteKind.Single }, skipAddingFilesFromTsConfig: false }));
17
+ project.addSourceFilesAtPaths([
18
+ join(rootDir, '**/*.ts'),
19
+ `!${join(rootDir, '**/node_modules/**')}`,
20
+ `!${join(rootDir, '**/dist/**')}`,
21
+ `!${join(rootDir, '**/.angular/**')}`,
22
+ `!${join(rootDir, '**/*.d.ts')}`,
23
+ ]);
24
+ const selected = ((_b = options.files) === null || _b === void 0 ? void 0 : _b.length)
25
+ ? new Set(options.files.map((file) => resolve(rootDir, file)))
26
+ : undefined;
27
+ const sourceFiles = project.getSourceFiles().filter((file) => {
28
+ const path = resolve(file.getFilePath());
29
+ return isInside(path, rootDir) && (!selected || selected.has(path));
30
+ });
31
+ const files = new Map();
32
+ const touched = new Set();
33
+ const diagnostics = [];
34
+ for (const sourceFile of sourceFiles) {
35
+ const changedSignals = migrateSignalsToState(sourceFile);
36
+ const changedResources = migrateSingleEmissionRxResources(sourceFile, diagnostics);
37
+ const changedWorkflows = annotateImperativeWorkflows(sourceFile, diagnostics);
38
+ diagnoseSignalForms(sourceFile, diagnostics);
39
+ if (changedSignals || changedResources || changedWorkflows)
40
+ touched.add(sourceFile);
41
+ if (changedSignals || changedResources || changedWorkflows)
42
+ getFileReport(files, sourceFile.getFilePath()).changed = true;
43
+ }
44
+ for (const file of touched)
45
+ file.organizeImports();
46
+ if (options.write) {
47
+ yield Promise.all([...touched].map((file) => file.save()));
48
+ }
49
+ let eslintRan = false;
50
+ if (options.write && options.eslint !== false && touched.size > 0) {
51
+ yield runEslint([...touched].map((file) => file.getFilePath()), rootDir);
52
+ eslintRan = true;
53
+ }
54
+ const remainingAngularSignals = countAngularSignalImports(project, rootDir);
55
+ const remainingSignalForms = countSignalFormImports(project, rootDir);
56
+ const result = {
57
+ changedFiles: [...touched].map((file) => file.getFilePath()),
58
+ files: [...files.values()],
59
+ diagnostics,
60
+ remainingAngularSignals,
61
+ remainingSignalForms,
62
+ eslintRan,
63
+ exitCode: (options.check &&
64
+ (remainingAngularSignals > 0 || remainingSignalForms > 0)) ||
65
+ (options.failOnManual && diagnostics.length > 0)
66
+ ? 1
67
+ : 0,
68
+ };
69
+ if (options.jsonFilePath) {
70
+ const path = resolve(options.jsonFilePath);
71
+ yield mkdir(dirname(path), { recursive: true });
72
+ yield writeFile(path, `${JSON.stringify(result, null, 2)}\n`, 'utf8');
73
+ }
74
+ const log = (_c = options.log) !== null && _c !== void 0 ? _c : console.log;
75
+ if (options.json)
76
+ log(JSON.stringify(result, null, 2));
77
+ else
78
+ logSummary(result, log, options.write === true);
79
+ return result;
80
+ });
81
+ }
82
+ function migrateSignalsToState(sourceFile) {
83
+ const angularCore = sourceFile.getImportDeclaration('@angular/core');
84
+ const signalImport = angularCore === null || angularCore === void 0 ? void 0 : angularCore.getNamedImports().find((item) => item.getName() === 'signal');
85
+ if (!signalImport)
86
+ return false;
87
+ let changed = false;
88
+ const declarationsToAnnotate = new Set();
89
+ for (const call of [
90
+ ...sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression),
91
+ ]) {
92
+ if (call.wasForgotten())
93
+ continue;
94
+ if (call.getExpression().getText() !== 'signal')
95
+ continue;
96
+ const typeArgument = call.getTypeArguments()[0];
97
+ const initialValue = call.getArguments()[0];
98
+ if (!initialValue)
99
+ continue;
100
+ const value = typeArgument
101
+ ? `${initialValue.getText()} as ${typeArgument.getText()} satisfies ${typeArgument.getText()}`
102
+ : initialValue.getText();
103
+ const declaration = findImperativeStateDeclaration(call);
104
+ if (declaration)
105
+ declarationsToAnnotate.add(declaration);
106
+ call.replaceWithText(`state(${value}, ({ set, update }) => ({ set, update }))`);
107
+ changed = true;
108
+ }
109
+ for (const declaration of [...declarationsToAnnotate].sort((left, right) => right.getStart() - left.getStart())) {
110
+ if (declaration.wasForgotten())
111
+ continue;
112
+ declaration.replaceWithText(`${IMPERATIVE_STATE_COMMENT}\n${declaration.getText()}`);
113
+ }
114
+ if (!changed)
115
+ return false;
116
+ signalImport.remove();
117
+ if (angularCore &&
118
+ !angularCore.getDefaultImport() &&
119
+ !angularCore.getNamespaceImport() &&
120
+ angularCore.getNamedImports().length === 0)
121
+ angularCore.remove();
122
+ ensureCoreImports(sourceFile, ['state']);
123
+ return true;
124
+ }
125
+ const IMPERATIVE_STATE_COMMENT = '// CRAFT_IMPERATIVE_CODE_DETECTED: imperative code detected, prefer a declarative approach.';
126
+ function findImperativeStateDeclaration(call) {
127
+ const declaration = call.getFirstAncestor((ancestor) => Node.isPropertyDeclaration(ancestor) ||
128
+ Node.isVariableStatement(ancestor));
129
+ if (!declaration ||
130
+ declaration.getFullText().includes('CRAFT_IMPERATIVE_CODE_DETECTED'))
131
+ return undefined;
132
+ return declaration;
133
+ }
134
+ const REACTIVE_WORKFLOW_COMMENT = '// CRAFT_REACTIVE_WORKFLOW_RECOMMENDED: workflow impératif détecté...';
135
+ const FIRST_VALUE_FROM_REVIEW_COMMENT = '// CRAFT_FIRST_VALUE_FROM_REVIEW: firstValueFrom bridges an Observable temporarily; prefer a Promise-native Craft API when possible.';
136
+ function migrateSingleEmissionRxResources(sourceFile, diagnostics) {
137
+ var _a, _b;
138
+ const rxInterop = sourceFile.getImportDeclaration('@angular/core/rxjs-interop');
139
+ if (!(rxInterop === null || rxInterop === void 0 ? void 0 : rxInterop.getNamedImports().some((item) => item.getName() === 'rxResource')))
140
+ return false;
141
+ let changed = false;
142
+ for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
143
+ if (call.wasForgotten() || call.getExpression().getText() !== 'rxResource')
144
+ continue;
145
+ const config = call.getArguments()[0];
146
+ if (!config || !Node.isObjectLiteralExpression(config))
147
+ continue;
148
+ const stream = config.getProperty('stream');
149
+ if (!stream || !Node.isPropertyAssignment(stream))
150
+ continue;
151
+ const converted = convertSingleEmissionStream((_b = (_a = stream.getInitializer()) === null || _a === void 0 ? void 0 : _a.getText()) !== null && _b !== void 0 ? _b : '');
152
+ if (!converted)
153
+ continue;
154
+ call.getExpression().replaceWithText('query');
155
+ stream.replaceWithText(`loader: ${converted}`);
156
+ changed = true;
157
+ }
158
+ if (!changed)
159
+ return false;
160
+ ensureCoreImports(sourceFile, ['query']);
161
+ ensureNamedImport(sourceFile, 'rxjs', 'firstValueFrom');
162
+ removeNamedImportIfUnused(sourceFile, '@angular/core/rxjs-interop', 'rxResource');
163
+ removeNamedImportIfUnused(sourceFile, 'rxjs', 'from');
164
+ removeNamedImportIfUnused(sourceFile, 'rxjs', 'of');
165
+ removeNamedImportIfUnused(sourceFile, 'rxjs/operators', 'switchMap');
166
+ if (!sourceFile
167
+ .getDescendantsOfKind(SyntaxKind.CallExpression)
168
+ .some((call) => call.getExpression().getText() === 'rxResource')) {
169
+ removeDiagnostic(diagnostics, sourceFile, 'RX_RESOURCE_REQUIRES_QUERY');
170
+ }
171
+ return true;
172
+ }
173
+ function convertSingleEmissionStream(initializer) {
174
+ const match = initializer.match(/^\s*\(([^)]*)\)\s*=>\s*\{([\s\S]*)\}\s*$/);
175
+ if (!match)
176
+ return undefined;
177
+ let body = match[2];
178
+ const bridge = body.match(/return\s+from\(([\s\S]*?)\)\.pipe\(\s*switchMap\(\s*\((\w+)\)\s*=>\s*([\s\S]*?)\s*\)\s*\)\s*;/);
179
+ if (!bridge)
180
+ return undefined;
181
+ body = body.replace(/return\s+of\(([\s\S]*?)\)\s*;/g, 'return $1;');
182
+ body = body.replace(bridge[0], `${FIRST_VALUE_FROM_REVIEW_COMMENT}\nreturn firstValueFrom((await ${bridge[1]}).${stripReceiver(bridge[3], bridge[2])});`);
183
+ return `async (${match[1]}) => {${body}}`;
184
+ }
185
+ function stripReceiver(expression, receiver) {
186
+ const trimmed = expression.trim();
187
+ const prefix = `${receiver}.`;
188
+ return trimmed.startsWith(prefix) ? trimmed.slice(prefix.length) : trimmed;
189
+ }
190
+ function ensureNamedImport(sourceFile, moduleSpecifier, name) {
191
+ let declaration = sourceFile.getImportDeclaration(moduleSpecifier);
192
+ if (!declaration)
193
+ declaration = sourceFile.addImportDeclaration({ moduleSpecifier });
194
+ if (!declaration
195
+ .getNamedImports()
196
+ .some((namedImport) => namedImport.getName() === name))
197
+ declaration.addNamedImport(name);
198
+ }
199
+ function removeNamedImportIfUnused(sourceFile, moduleSpecifier, name) {
200
+ const declaration = sourceFile.getImportDeclaration(moduleSpecifier);
201
+ const namedImport = declaration === null || declaration === void 0 ? void 0 : declaration.getNamedImports().find((item) => item.getName() === name);
202
+ if (!namedImport)
203
+ return;
204
+ const stillUsed = sourceFile
205
+ .getDescendantsOfKind(SyntaxKind.Identifier)
206
+ .some((identifier) => identifier.getText() === name &&
207
+ identifier.getFirstAncestorByKind(SyntaxKind.ImportDeclaration) !==
208
+ declaration);
209
+ if (stillUsed)
210
+ return;
211
+ namedImport.remove();
212
+ if (declaration &&
213
+ !declaration.getDefaultImport() &&
214
+ !declaration.getNamespaceImport() &&
215
+ declaration.getNamedImports().length === 0)
216
+ declaration.remove();
217
+ }
218
+ function removeDiagnostic(diagnostics, sourceFile, code) {
219
+ const index = diagnostics.findIndex((diagnostic) => diagnostic.code === code &&
220
+ diagnostic.filePath === sourceFile.getFilePath());
221
+ if (index >= 0)
222
+ diagnostics.splice(index, 1);
223
+ }
224
+ function annotateImperativeWorkflows(sourceFile, diagnostics) {
225
+ let changed = false;
226
+ const functions = [
227
+ ...sourceFile.getDescendantsOfKind(SyntaxKind.FunctionDeclaration),
228
+ ...sourceFile.getDescendantsOfKind(SyntaxKind.MethodDeclaration),
229
+ ];
230
+ for (const functionLike of functions) {
231
+ if (functionLike.getFullText().includes('CRAFT_REACTIVE_WORKFLOW_RECOMMENDED'))
232
+ continue;
233
+ const calls = functionLike.getDescendantsOfKind(SyntaxKind.CallExpression);
234
+ const hasSubmit = calls.some((call) => {
235
+ const expression = call.getExpression();
236
+ return (expression.getText() === 'submit' ||
237
+ (Node.isPropertyAccessExpression(expression) &&
238
+ expression.getName() === 'submit'));
239
+ });
240
+ if (!hasSubmit)
241
+ continue;
242
+ const stateWrites = calls.filter((call) => {
243
+ const expression = call.getExpression();
244
+ return (Node.isPropertyAccessExpression(expression) &&
245
+ ['set', 'update'].includes(expression.getName()));
246
+ }).length;
247
+ const hasNavigation = calls.some((call) => {
248
+ const expression = call.getExpression();
249
+ return (Node.isPropertyAccessExpression(expression) &&
250
+ ['navigate', 'navigateByUrl'].includes(expression.getName()));
251
+ });
252
+ if (stateWrites < 2 && !(stateWrites >= 1 && hasNavigation))
253
+ continue;
254
+ functionLike.replaceWithText(`${REACTIVE_WORKFLOW_COMMENT}\n${functionLike.getText()}`);
255
+ diagnose(diagnostics, 'IMPERATIVE_WORKFLOW_REQUIRES_REVIEW', sourceFile, 'Workflow impératif détecté: préférer insertFormSubmit avec une réaction au statut du formulaire, ou source$ avec on$/effect.');
256
+ changed = true;
257
+ }
258
+ return changed;
259
+ }
260
+ function diagnoseSignalForms(sourceFile, diagnostics) {
261
+ var _a;
262
+ const formsImport = sourceFile.getImportDeclaration('@angular/forms/signals');
263
+ if (!formsImport)
264
+ return;
265
+ const names = new Set(formsImport.getNamedImports().map((item) => item.getName()));
266
+ if (names.has('form')) {
267
+ diagnose(diagnostics, 'SIGNAL_FORM_REQUIRES_INSERT_FORM', sourceFile, 'Angular signal form `form(...)` doit être migré vers `state(..., insertForm(...))`; les chemins de champs doivent être remappés vers le form tree craft.');
268
+ }
269
+ if (names.has('validateAsync')) {
270
+ for (const call of sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)) {
271
+ if (!isValidateAsyncRxResourceCall(call))
272
+ continue;
273
+ diagnose(diagnostics, 'ASYNC_VALIDATOR_REQUIRES_QUERY', sourceFile, '`validateAsync(...)` basé sur `rxResource(...)` doit devenir une `query(...)` locale déclenchée par la valeur du champ, puis `cAsyncValidate(queryRef, ...)`. Dans un craftService, créer la query avec `yield* track(query(...))`.');
274
+ }
275
+ }
276
+ if ((_a = sourceFile.getImportDeclaration('@angular/core/rxjs-interop')) === null || _a === void 0 ? void 0 : _a.getNamedImports().some((item) => item.getName() === 'rxResource')) {
277
+ diagnose(diagnostics, 'RX_RESOURCE_REQUIRES_QUERY', sourceFile, '`rxResource(...)` doit être remplacé par `query(...)` ou `mutation(...)` selon l’intention; dans un validateur async, préférer `query(...) + cAsyncValidate(...)`. Dans un craftService, englober toute primitive dépendante avec `yield* track(...)`.');
278
+ }
279
+ }
280
+ function isValidateAsyncRxResourceCall(call) {
281
+ if (call.getExpression().getText() !== 'validateAsync')
282
+ return false;
283
+ return call
284
+ .getDescendantsOfKind(SyntaxKind.CallExpression)
285
+ .some((inner) => inner.getExpression().getText() === 'rxResource');
286
+ }
287
+ function ensureCoreImports(file, names) {
288
+ let declaration = file.getImportDeclaration('@craft-ng/core');
289
+ if (!declaration)
290
+ declaration = file.addImportDeclaration({
291
+ moduleSpecifier: '@craft-ng/core',
292
+ });
293
+ const existing = new Set(declaration.getNamedImports().map((item) => item.getName()));
294
+ declaration.addNamedImports(names.filter((name) => !existing.has(name)));
295
+ }
296
+ function diagnose(diagnostics, code, sourceFile, message) {
297
+ if (diagnostics.some((item) => item.code === code && item.filePath === sourceFile.getFilePath()))
298
+ return;
299
+ diagnostics.push({
300
+ code,
301
+ filePath: sourceFile.getFilePath(),
302
+ message,
303
+ manual: true,
304
+ });
305
+ }
306
+ function countAngularSignalImports(project, rootDir) {
307
+ return project
308
+ .getSourceFiles()
309
+ .filter((file) => isInside(resolve(file.getFilePath()), rootDir))
310
+ .filter((file) => {
311
+ var _a;
312
+ return (_a = file
313
+ .getImportDeclaration('@angular/core')) === null || _a === void 0 ? void 0 : _a.getNamedImports().some((item) => item.getName() === 'signal');
314
+ }).length;
315
+ }
316
+ function countSignalFormImports(project, rootDir) {
317
+ return project
318
+ .getSourceFiles()
319
+ .filter((file) => isInside(resolve(file.getFilePath()), rootDir))
320
+ .filter((file) => Boolean(file.getImportDeclaration('@angular/forms/signals')))
321
+ .length;
322
+ }
323
+ function getFileReport(map, filePath) {
324
+ let report = map.get(filePath);
325
+ if (!report) {
326
+ report = { filePath, changed: false };
327
+ map.set(filePath, report);
328
+ }
329
+ return report;
330
+ }
331
+ function isInside(filePath, rootDir) {
332
+ const path = relative(rootDir, filePath);
333
+ return path === '' || (!path.startsWith('..') && !isAbsolute(path));
334
+ }
335
+ function defaultTsConfig(rootDir) {
336
+ for (const name of ['tsconfig.app.json', 'tsconfig.json']) {
337
+ const candidate = join(rootDir, name);
338
+ if (existsSync(candidate))
339
+ return candidate;
340
+ }
341
+ return join(rootDir, 'tsconfig.json');
342
+ }
343
+ function runEslint(files, cwd) {
344
+ return __awaiter(this, void 0, void 0, function* () {
345
+ const local = join(cwd, 'node_modules', '.bin', 'eslint');
346
+ yield execFileAsync(existsSync(local) ? local : 'eslint', ['--fix', ...files], { cwd });
347
+ });
348
+ }
349
+ function logSummary(result, log, wrote) {
350
+ log(`${wrote ? 'Migrated' : 'Would migrate'} ${result.changedFiles.length} file(s); ${result.diagnostics.length} manual diagnostic(s).`);
351
+ for (const diagnostic of result.diagnostics)
352
+ log(`[${diagnostic.code}] ${diagnostic.filePath}: ${diagnostic.message}`);
353
+ }
354
+ //# sourceMappingURL=migrate-primitives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-primitives.js","sourceRoot":"","sources":["../../../../../../libs/dev-tools/src/scripts/primitives/migrate-primitives.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,279 @@
1
+ import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { afterEach, describe, expect, it } from 'vitest';
5
+ import { runPrimitivesMigration } from './migrate-primitives';
6
+
7
+ const temporaryDirectories: string[] = [];
8
+
9
+ afterEach(async () => {
10
+ await Promise.all(
11
+ temporaryDirectories
12
+ .splice(0)
13
+ .map((directory) => rm(directory, { recursive: true, force: true })),
14
+ );
15
+ });
16
+
17
+ async function fixture(files: Record<string, string>): Promise<string> {
18
+ const root = await mkdtemp(join(tmpdir(), 'craft-primitives-'));
19
+ temporaryDirectories.push(root);
20
+ await Promise.all(
21
+ Object.entries(files).map(async ([path, contents]) => {
22
+ const fullPath = join(root, path);
23
+ const { mkdir } = await import('node:fs/promises');
24
+ await mkdir(join(fullPath, '..'), { recursive: true });
25
+ await writeFile(fullPath, contents, 'utf8');
26
+ }),
27
+ );
28
+ return root;
29
+ }
30
+
31
+ describe('primitives migration', () => {
32
+ it('converts Angular signal calls to craft state', async () => {
33
+ const root = await fixture({
34
+ 'tsconfig.json': JSON.stringify({
35
+ compilerOptions: { experimentalDecorators: true },
36
+ }),
37
+ 'wizard.ts': `
38
+ import { computed, signal } from '@angular/core';
39
+ export class Wizard {
40
+ readonly activeStep = signal('delivery');
41
+ readonly total = computed(() => this.activeStep());
42
+ }
43
+ `,
44
+ });
45
+
46
+ const result = await runPrimitivesMigration({
47
+ rootDir: root,
48
+ write: true,
49
+ eslint: false,
50
+ log: () => undefined,
51
+ });
52
+
53
+ const output = await readFile(join(root, 'wizard.ts'), 'utf8');
54
+ expect(result.diagnostics).toEqual([]);
55
+ expect(output).toContain("import { computed } from '@angular/core'");
56
+ expect(output).toContain("import { state } from '@craft-ng/core'");
57
+ expect(output).toContain(
58
+ "activeStep = state('delivery', ({ set, update }) => ({ set, update }))",
59
+ );
60
+ expect(output).toContain(
61
+ '// CRAFT_IMPERATIVE_CODE_DETECTED: imperative code detected, prefer a declarative approach.',
62
+ );
63
+ expect(output).not.toContain('signal(');
64
+ });
65
+
66
+ it('replaces explicit signal generics with satisfies on the state value', async () => {
67
+ const root = await fixture({
68
+ 'tsconfig.json': '{}',
69
+ 'wizard.ts': `
70
+ import { signal } from '@angular/core';
71
+ type WizardStep = 'delivery' | 'schedule' | 'review';
72
+ export const activeStep = signal<WizardStep>('delivery');
73
+ export const stepStatus = signal<Record<WizardStep, 'success' | 'error' | null>>({
74
+ delivery: null,
75
+ schedule: null,
76
+ review: null,
77
+ });
78
+ `,
79
+ });
80
+
81
+ await runPrimitivesMigration({
82
+ rootDir: root,
83
+ write: true,
84
+ eslint: false,
85
+ log: () => undefined,
86
+ });
87
+
88
+ const output = await readFile(join(root, 'wizard.ts'), 'utf8');
89
+ expect(output).toContain(
90
+ "state('delivery' as WizardStep satisfies WizardStep, ({ set, update }) => ({ set, update }))",
91
+ );
92
+ expect(output).toContain(
93
+ "} as Record<WizardStep, 'success' | 'error' | null> satisfies Record<WizardStep, 'success' | 'error' | null>, ({ set, update }) => ({ set, update }))",
94
+ );
95
+ expect(output).not.toContain('state<WizardStep>');
96
+ expect(output).not.toContain('state<Record<');
97
+ expect(
98
+ output.match(/CRAFT_IMPERATIVE_CODE_DETECTED/g),
99
+ ).toHaveLength(2);
100
+ });
101
+
102
+ it('annotates an imperative workflow in an already migrated craftService', async () => {
103
+ const root = await fixture({
104
+ 'tsconfig.json': '{}',
105
+ 'wizard.ts': `
106
+ import { craftService, state } from '@craft-ng/core';
107
+ export const { injectWizard } = craftService(
108
+ { name: 'Wizard', scope: 'function' },
109
+ () => {
110
+ const activeStep = state('delivery');
111
+ const stepStatus = state({ delivery: null });
112
+ const checkoutForm = { form: { delivery: { submit: async () => true } } };
113
+ const router = { navigate: async (_commands: unknown[]) => true };
114
+
115
+ async function validateStep(step: 'delivery') {
116
+ const success = await checkoutForm.form[step].submit();
117
+ if (!success) return;
118
+ stepStatus.update((status) => ({ ...status, [step]: 'success' }));
119
+ activeStep.set(step);
120
+ await router.navigate(['/checkout', step]);
121
+ }
122
+ return { validateStep };
123
+ },
124
+ );
125
+ `,
126
+ });
127
+
128
+ const first = await runPrimitivesMigration({
129
+ rootDir: root,
130
+ write: true,
131
+ eslint: false,
132
+ log: () => undefined,
133
+ });
134
+ const output = await readFile(join(root, 'wizard.ts'), 'utf8');
135
+ expect(output).toContain(
136
+ '// CRAFT_REACTIVE_WORKFLOW_RECOMMENDED: workflow impératif détecté...',
137
+ );
138
+ expect(first.diagnostics.map((diagnostic) => diagnostic.code)).toContain(
139
+ 'IMPERATIVE_WORKFLOW_REQUIRES_REVIEW',
140
+ );
141
+
142
+ await runPrimitivesMigration({
143
+ rootDir: root,
144
+ write: true,
145
+ eslint: false,
146
+ log: () => undefined,
147
+ });
148
+ const secondOutput = await readFile(join(root, 'wizard.ts'), 'utf8');
149
+ expect(
150
+ secondOutput.match(/CRAFT_REACTIVE_WORKFLOW_RECOMMENDED/g),
151
+ ).toHaveLength(1);
152
+ });
153
+
154
+ it('reports signal forms and rxResource async validators for insertForm rewrite', async () => {
155
+ const root = await fixture({
156
+ 'tsconfig.json': JSON.stringify({
157
+ compilerOptions: { experimentalDecorators: true },
158
+ }),
159
+ 'checkout-wizard.ts': `
160
+ import { signal } from '@angular/core';
161
+ import { rxResource } from '@angular/core/rxjs-interop';
162
+ import { form, required, validateAsync } from '@angular/forms/signals';
163
+ export class CheckoutWizard {
164
+ private readonly discount = signal(0);
165
+ readonly checkoutForm = form(signal({ coupon: { code: '' } }), (schema) => {
166
+ required(schema.coupon.code);
167
+ validateAsync(schema.coupon.code, {
168
+ params: ({ fieldTreeOf }) => ({ fieldTreeOf }),
169
+ factory: (params) => rxResource({
170
+ params,
171
+ stream: ({ params }) => params.fieldTreeOf(schema.coupon.code)().value(),
172
+ }),
173
+ });
174
+ });
175
+ }
176
+ `,
177
+ });
178
+
179
+ const result = await runPrimitivesMigration({
180
+ rootDir: root,
181
+ write: true,
182
+ eslint: false,
183
+ log: () => undefined,
184
+ });
185
+
186
+ const output = await readFile(join(root, 'checkout-wizard.ts'), 'utf8');
187
+ expect(output).toContain(
188
+ 'state(0, ({ set, update }) => ({ set, update }))',
189
+ );
190
+ expect(output).toContain(
191
+ 'state({ coupon: { code:',
192
+ );
193
+ expect(result.diagnostics.map((diagnostic) => diagnostic.code)).toEqual([
194
+ 'SIGNAL_FORM_REQUIRES_INSERT_FORM',
195
+ 'ASYNC_VALIDATOR_REQUIRES_QUERY',
196
+ 'RX_RESOURCE_REQUIRES_QUERY',
197
+ ]);
198
+ });
199
+
200
+ it('converts a debounced single-emission rxResource to query', async () => {
201
+ const root = await fixture({
202
+ 'tsconfig.json': '{}',
203
+ 'location-field.ts': `
204
+ import { signal } from '@angular/core';
205
+ import { rxResource, toObservable, toSignal } from '@angular/core/rxjs-interop';
206
+ import { debounceTime, distinctUntilChanged, from, map, of } from 'rxjs';
207
+ import { switchMap } from 'rxjs/operators';
208
+
209
+ export class LocationField {
210
+ private readonly api = Promise.resolve({
211
+ search: (params: { q: string }) => of([{ label: params.q }]),
212
+ });
213
+ private readonly searchInput = signal('');
214
+ private readonly debouncedSearch = toSignal(
215
+ toObservable(this.searchInput).pipe(
216
+ debounceTime(280),
217
+ map((value) => value.trim()),
218
+ distinctUntilChanged(),
219
+ ),
220
+ { initialValue: '' },
221
+ );
222
+ readonly suggestions = rxResource({
223
+ params: () => {
224
+ const query = this.debouncedSearch();
225
+ return query.length < 2 ? undefined : { q: query };
226
+ },
227
+ stream: ({ params }) => {
228
+ if (!params) return of([]);
229
+ return from(this.api).pipe(switchMap((service) => service.search(params)));
230
+ },
231
+ defaultValue: [],
232
+ });
233
+ }
234
+ `,
235
+ });
236
+
237
+ const result = await runPrimitivesMigration({
238
+ rootDir: root,
239
+ write: true,
240
+ eslint: false,
241
+ log: () => undefined,
242
+ });
243
+
244
+ const output = await readFile(join(root, 'location-field.ts'), 'utf8');
245
+ expect(output).toContain('readonly suggestions = query({');
246
+ expect(output).toContain('loader: async ({ params }) =>');
247
+ expect(output).toContain('return [];');
248
+ expect(output).toContain(
249
+ '// CRAFT_FIRST_VALUE_FROM_REVIEW: firstValueFrom bridges an Observable temporarily; prefer a Promise-native Craft API when possible.',
250
+ );
251
+ expect(output).toContain(
252
+ 'return firstValueFrom((await this.api).search(params));',
253
+ );
254
+ expect(output).not.toContain('rxResource');
255
+ expect(output).not.toContain("from 'rxjs/operators'");
256
+ expect(result.diagnostics).toEqual([]);
257
+ });
258
+
259
+ it('supports check mode for remaining signal forms', async () => {
260
+ const root = await fixture({
261
+ 'tsconfig.json': '{}',
262
+ 'form.ts': `
263
+ import { form } from '@angular/forms/signals';
264
+ export const x = form;
265
+ `,
266
+ });
267
+
268
+ const result = await runPrimitivesMigration({
269
+ rootDir: root,
270
+ write: false,
271
+ check: true,
272
+ eslint: false,
273
+ log: () => undefined,
274
+ });
275
+
276
+ expect(result.exitCode).toBe(1);
277
+ expect(result.remainingSignalForms).toBe(1);
278
+ });
279
+ });