@craft-ts/dev-tools 0.7.0-beta.13 → 0.7.0-beta.16

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 (89) hide show
  1. package/README.md +60 -10
  2. package/package.json +8 -2
  3. package/src/bin/agent-selector.d.ts +22 -0
  4. package/src/bin/agent-selector.js +100 -0
  5. package/src/bin/agent-selector.js.map +1 -0
  6. package/src/bin/craft-graph.js +74 -8
  7. package/src/bin/craft-graph.js.map +1 -1
  8. package/src/bin/craft.d.ts +22 -0
  9. package/src/bin/craft.js +231 -28
  10. package/src/bin/craft.js.map +1 -1
  11. package/src/eslint-rules/anchor-has-href.cjs +37 -3
  12. package/src/eslint-rules/craft-computed-name-match.cjs +26 -5
  13. package/src/eslint-rules/craft-name-match-utils.cjs +18 -9
  14. package/src/eslint-rules/hyperscript-walk.cjs +3 -3
  15. package/src/eslint-rules/index.cjs +46 -1
  16. package/src/eslint-rules/no-auth-token-in-local-storage.cjs +17 -0
  17. package/src/eslint-rules/no-craft-computed-side-effects.cjs +12 -5
  18. package/src/eslint-rules/no-craft-service-component-same-file.cjs +138 -0
  19. package/src/eslint-rules/no-effect-import-in-frontend.cjs +52 -0
  20. package/src/eslint-rules/no-effect-in-params.cjs +31 -1
  21. package/src/eslint-rules/no-explicit-effect-type.cjs +137 -0
  22. package/src/eslint-rules/no-free-has.cjs +47 -0
  23. package/src/eslint-rules/no-heading-level-skip.cjs +6 -6
  24. package/src/eslint-rules/no-raw-class.cjs +76 -0
  25. package/src/eslint-rules/no-raw-css-value.cjs +163 -0
  26. package/src/eslint-rules/no-raw-user-url.cjs +114 -0
  27. package/src/eslint-rules/no-trust-forwarded-headers.cjs +43 -0
  28. package/src/eslint-rules/no-unsafe-html.cjs +93 -0
  29. package/src/eslint-rules/no-unsafe-transfer-state.cjs +54 -0
  30. package/src/eslint-rules/prefer-craft-template-blocks.cjs +8 -8
  31. package/src/eslint-rules/prefer-direct-yieldable-callback.cjs +57 -14
  32. package/src/eslint-rules/prefer-inline-effect-insertion.cjs +263 -0
  33. package/src/eslint-rules/prefer-inline-route-providers.cjs +138 -0
  34. package/src/eslint-rules/recommended-config.cjs +6 -0
  35. package/src/eslint-rules/require-reactive-template-bindings.cjs +8 -8
  36. package/src/eslint-rules/require-route-security-policy.cjs +87 -0
  37. package/src/eslint-rules/require-server-function-timeout.cjs +39 -0
  38. package/src/eslint-rules/security-config.cjs +14 -0
  39. package/src/eslint-rules/security-rule-utils.cjs +21 -0
  40. package/src/eslint-rules/style-file-boundary.cjs +75 -0
  41. package/src/eslint-rules/sync-effect-body.cjs +343 -0
  42. package/src/index.d.ts +4 -0
  43. package/src/index.js +4 -0
  44. package/src/index.js.map +1 -1
  45. package/src/scripts/architecture-graph.js +8 -2
  46. package/src/scripts/architecture-graph.js.map +1 -1
  47. package/src/scripts/create/create-project.d.ts +60 -1
  48. package/src/scripts/create/create-project.js +2082 -184
  49. package/src/scripts/create/create-project.js.map +1 -1
  50. package/src/scripts/data-flow-graph.d.ts +1 -1
  51. package/src/scripts/effect-dependency-graph.d.ts +1 -1
  52. package/src/scripts/security-check.d.ts +30 -0
  53. package/src/scripts/security-check.js +223 -0
  54. package/src/scripts/security-check.js.map +1 -0
  55. package/src/scripts/style-architecture.d.ts +56 -0
  56. package/src/scripts/style-architecture.js +142 -0
  57. package/src/scripts/style-architecture.js.map +1 -0
  58. package/src/scripts/style-graph.d.ts +99 -0
  59. package/src/scripts/style-graph.js +179 -0
  60. package/src/scripts/style-graph.js.map +1 -0
  61. package/src/scripts/style-report.d.ts +55 -0
  62. package/src/scripts/style-report.js +67 -0
  63. package/src/scripts/style-report.js.map +1 -0
  64. package/src/scripts/template/migrate-template.js +1 -1
  65. package/src/scripts/template/migrate-template.js.map +1 -1
  66. package/src/scripts/angular-brand-codemod.ts +0 -3985
  67. package/src/scripts/architecture/migrate-architecture.ts +0 -653
  68. package/src/scripts/architecture-graph.ts +0 -3136
  69. package/src/scripts/components/migrate-components.ts +0 -227
  70. package/src/scripts/components/migration-diagnostic.ts +0 -8
  71. package/src/scripts/create/create-project.ts +0 -849
  72. package/src/scripts/data-flow-graph.ts +0 -240
  73. package/src/scripts/dependency-graph.ts +0 -5908
  74. package/src/scripts/effect-dependency-graph.ts +0 -630
  75. package/src/scripts/migrate.ts +0 -162
  76. package/src/scripts/migration-workspace.ts +0 -93
  77. package/src/scripts/primitives/migrate-named-primitives.ts +0 -627
  78. package/src/scripts/primitives/migrate-primitive-generators.ts +0 -410
  79. package/src/scripts/primitives/migrate-primitives.ts +0 -655
  80. package/src/scripts/primitives/migrate-yieldable-reactive-reads.ts +0 -499
  81. package/src/scripts/primitives/migration-diagnostic.ts +0 -15
  82. package/src/scripts/routes/migrate-routes.ts +0 -895
  83. package/src/scripts/routes/migration-diagnostic.ts +0 -25
  84. package/src/scripts/routes/route-command.ts +0 -1807
  85. package/src/scripts/routes/verify-routes.ts +0 -1511
  86. package/src/scripts/services/config.ts +0 -60
  87. package/src/scripts/services/migrate-services.ts +0 -1348
  88. package/src/scripts/services/migration-diagnostic.ts +0 -28
  89. package/src/scripts/template/migrate-template.ts +0 -418
@@ -1,227 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { join, resolve } from 'node:path';
3
- import {
4
- Node,
5
- Project,
6
- QuoteKind,
7
- SourceFile,
8
- SyntaxKind,
9
- type CallExpression,
10
- } from 'ts-morph';
11
- import type { ComponentMigrationDiagnostic } from './migration-diagnostic.js';
12
-
13
- export type MigrateComponentsOptions = {
14
- rootDir?: string;
15
- tsConfigFilePath?: string;
16
- files?: readonly string[];
17
- write?: boolean;
18
- check?: boolean;
19
- json?: boolean;
20
- failOnManual?: boolean;
21
- eslint?: boolean;
22
- log?: (message: string) => void;
23
- };
24
-
25
- export type MigrateComponentsResult = {
26
- changedFiles: string[];
27
- diagnostics: ComponentMigrationDiagnostic[];
28
- remainingLegacyComponents: number;
29
- remainingLegacyDirectives: number;
30
- exitCode: number;
31
- };
32
-
33
- export async function runComponentsMigration(
34
- options: MigrateComponentsOptions = {},
35
- ): Promise<MigrateComponentsResult> {
36
- const rootDir = resolve(options.rootDir ?? process.cwd());
37
- const tsConfigFilePath = options.tsConfigFilePath
38
- ? resolve(options.tsConfigFilePath)
39
- : join(rootDir, 'tsconfig.json');
40
- const project = new Project({
41
- ...(existsSync(tsConfigFilePath) ? { tsConfigFilePath } : {}),
42
- manipulationSettings: { quoteKind: QuoteKind.Single },
43
- skipAddingFilesFromTsConfig: false,
44
- });
45
- project.addSourceFilesAtPaths([
46
- join(rootDir, '**/*.ts'),
47
- `!${join(rootDir, '**/node_modules/**')}`,
48
- `!${join(rootDir, '**/dist/**')}`,
49
- `!${join(rootDir, '**/.angular/**')}`,
50
- `!${join(rootDir, '**/*.d.ts')}`,
51
- ]);
52
-
53
- const selected = options.files?.length
54
- ? new Set(options.files.map((file) => resolve(rootDir, file)))
55
- : undefined;
56
- const sourceFiles = project.getSourceFiles().filter((file) => {
57
- const path = resolve(file.getFilePath());
58
- return path.startsWith(`${rootDir}/`) && (!selected || selected.has(path));
59
- });
60
- const touched = new Set<SourceFile>();
61
- const diagnostics: ComponentMigrationDiagnostic[] = [];
62
- const legacyComponentsBeforeMigration = sourceFiles.reduce(
63
- (count, sourceFile) => count + countLegacyComponentCalls(sourceFile),
64
- 0,
65
- );
66
-
67
- for (const sourceFile of sourceFiles) {
68
- const componentImport = sourceFile
69
- .getImportDeclarations()
70
- .flatMap((declaration) => declaration.getNamedImports())
71
- .find((specifier) => specifier.getName() === 'component');
72
- const componentNameNode = componentImport?.getNameNode();
73
- const componentAliasNode = componentImport?.getAliasNode();
74
- if (componentImport && componentAliasNode) {
75
- if (componentAliasNode.getText() !== 'craftComponent') {
76
- componentAliasNode.rename('craftComponent');
77
- }
78
- componentImport.setName('craftComponent').removeAlias();
79
- touched.add(sourceFile);
80
- } else if (componentNameNode && Node.isIdentifier(componentNameNode)) {
81
- if (componentNameNode.getText() !== 'craftComponent') {
82
- componentNameNode.rename('craftComponent');
83
- touched.add(sourceFile);
84
- }
85
- }
86
-
87
- const componentCalls = sourceFile
88
- .getDescendantsOfKind(SyntaxKind.CallExpression)
89
- .filter((call) => call.getExpression().getText() === 'craftComponent');
90
- for (const call of componentCalls.sort(
91
- (a, b) => b.getStart() - a.getStart(),
92
- )) {
93
- const name = declaredNameFor(call);
94
- if (!name) {
95
- diagnostics.push({
96
- code: 'NAME_NOT_DEDUCIBLE',
97
- filePath: sourceFile.getFilePath(),
98
- message: 'Could not infer the name for craftComponent(...).',
99
- manual: true,
100
- });
101
- continue;
102
- }
103
- if (!isStringLiteral(call.getArguments()[0])) {
104
- call.insertArgument(0, `'${name}'`);
105
- touched.add(sourceFile);
106
- }
107
- }
108
-
109
- const directiveCalls = sourceFile
110
- .getDescendantsOfKind(SyntaxKind.CallExpression)
111
- .filter((call) => call.getExpression().getText() === 'craftDirective');
112
- for (const call of directiveCalls.sort(
113
- (a, b) => b.getStart() - a.getStart(),
114
- )) {
115
- const name = declaredNameFor(call);
116
- if (!name) {
117
- diagnostics.push({
118
- code: 'NAME_NOT_DEDUCIBLE',
119
- filePath: sourceFile.getFilePath(),
120
- message: 'Could not infer the name for craftDirective(...).',
121
- manual: true,
122
- });
123
- continue;
124
- }
125
- if (!isStringLiteral(call.getArguments()[0])) {
126
- call.insertArgument(0, `'${name}'`);
127
- call.insertArgument(1, '{}');
128
- touched.add(sourceFile);
129
- }
130
- }
131
- }
132
-
133
- if (options.write) await Promise.all([...touched].map((file) => file.save()));
134
-
135
- const remainingLegacyComponentsAfterMigration = sourceFiles.reduce(
136
- (count, sourceFile) => {
137
- const hasLegacyImport = sourceFile
138
- .getImportDeclarations()
139
- .flatMap((declaration) => declaration.getNamedImports())
140
- .some((specifier) => specifier.getName() === 'component');
141
- return hasLegacyImport
142
- ? count + countCalls(sourceFile, 'component')
143
- : count;
144
- },
145
- 0,
146
- );
147
- const remainingLegacyComponents = options.write
148
- ? remainingLegacyComponentsAfterMigration
149
- : legacyComponentsBeforeMigration;
150
- const remainingLegacyDirectives = sourceFiles.reduce(
151
- (count, sourceFile) =>
152
- count + countCalls(sourceFile, 'craftDirective', true),
153
- 0,
154
- );
155
- const result: MigrateComponentsResult = {
156
- changedFiles: [...touched].map((file) => file.getFilePath()),
157
- diagnostics,
158
- remainingLegacyComponents,
159
- remainingLegacyDirectives,
160
- exitCode:
161
- (options.check &&
162
- (remainingLegacyComponents > 0 || remainingLegacyDirectives > 0)) ||
163
- (options.failOnManual && diagnostics.length > 0)
164
- ? 1
165
- : 0,
166
- };
167
- const log = options.log ?? console.log;
168
- if (options.json) log(JSON.stringify(result, null, 2));
169
- else
170
- log(
171
- `Components migration complete: ${result.changedFiles.length} changed file(s), ${diagnostics.length} manual diagnostic(s).`,
172
- );
173
- return result;
174
- }
175
-
176
- function declaredNameFor(call: CallExpression): string | undefined {
177
- let current: Node | undefined = call;
178
- while (current) {
179
- if (Node.isVariableDeclaration(current) && current.getNameNode()) {
180
- return current.getName();
181
- }
182
- if (
183
- Node.isPropertyDeclaration(current) ||
184
- Node.isPropertyAssignment(current)
185
- ) {
186
- return current.getName();
187
- }
188
- current = current.getParent();
189
- }
190
- return undefined;
191
- }
192
-
193
- function isStringLiteral(node: Node | undefined): boolean {
194
- return Boolean(
195
- node &&
196
- (Node.isStringLiteral(node) ||
197
- (Node.isNoSubstitutionTemplateLiteral(node) && node.getLiteralText())),
198
- );
199
- }
200
-
201
- function countCalls(
202
- sourceFile: SourceFile,
203
- name: string,
204
- migrated = false,
205
- ): number {
206
- return sourceFile
207
- .getDescendantsOfKind(SyntaxKind.CallExpression)
208
- .filter((call) => {
209
- const expression = call.getExpression().getText();
210
- return migrated
211
- ? expression === name && !isStringLiteral(call.getArguments()[0])
212
- : expression === name;
213
- }).length;
214
- }
215
-
216
- function countLegacyComponentCalls(sourceFile: SourceFile): number {
217
- const localNames = new Set(
218
- sourceFile
219
- .getImportDeclarations()
220
- .flatMap((declaration) => declaration.getNamedImports())
221
- .filter((specifier) => specifier.getName() === 'component')
222
- .map((specifier) => specifier.getAliasNode()?.getText() ?? 'component'),
223
- );
224
- return sourceFile
225
- .getDescendantsOfKind(SyntaxKind.CallExpression)
226
- .filter((call) => localNames.has(call.getExpression().getText())).length;
227
- }
@@ -1,8 +0,0 @@
1
- export type ComponentMigrationDiagnosticCode = 'NAME_NOT_DEDUCIBLE';
2
-
3
- export type ComponentMigrationDiagnostic = {
4
- code: ComponentMigrationDiagnosticCode;
5
- filePath: string;
6
- message: string;
7
- manual: true;
8
- };