@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.
- package/README.md +60 -10
- package/package.json +8 -2
- package/src/bin/agent-selector.d.ts +22 -0
- package/src/bin/agent-selector.js +100 -0
- package/src/bin/agent-selector.js.map +1 -0
- package/src/bin/craft-graph.js +74 -8
- package/src/bin/craft-graph.js.map +1 -1
- package/src/bin/craft.d.ts +22 -0
- package/src/bin/craft.js +231 -28
- package/src/bin/craft.js.map +1 -1
- package/src/eslint-rules/anchor-has-href.cjs +37 -3
- package/src/eslint-rules/craft-computed-name-match.cjs +26 -5
- package/src/eslint-rules/craft-name-match-utils.cjs +18 -9
- package/src/eslint-rules/hyperscript-walk.cjs +3 -3
- package/src/eslint-rules/index.cjs +46 -1
- package/src/eslint-rules/no-auth-token-in-local-storage.cjs +17 -0
- package/src/eslint-rules/no-craft-computed-side-effects.cjs +12 -5
- package/src/eslint-rules/no-craft-service-component-same-file.cjs +138 -0
- package/src/eslint-rules/no-effect-import-in-frontend.cjs +52 -0
- package/src/eslint-rules/no-effect-in-params.cjs +31 -1
- package/src/eslint-rules/no-explicit-effect-type.cjs +137 -0
- package/src/eslint-rules/no-free-has.cjs +47 -0
- package/src/eslint-rules/no-heading-level-skip.cjs +6 -6
- package/src/eslint-rules/no-raw-class.cjs +76 -0
- package/src/eslint-rules/no-raw-css-value.cjs +163 -0
- package/src/eslint-rules/no-raw-user-url.cjs +114 -0
- package/src/eslint-rules/no-trust-forwarded-headers.cjs +43 -0
- package/src/eslint-rules/no-unsafe-html.cjs +93 -0
- package/src/eslint-rules/no-unsafe-transfer-state.cjs +54 -0
- package/src/eslint-rules/prefer-craft-template-blocks.cjs +8 -8
- package/src/eslint-rules/prefer-direct-yieldable-callback.cjs +57 -14
- package/src/eslint-rules/prefer-inline-effect-insertion.cjs +263 -0
- package/src/eslint-rules/prefer-inline-route-providers.cjs +138 -0
- package/src/eslint-rules/recommended-config.cjs +6 -0
- package/src/eslint-rules/require-reactive-template-bindings.cjs +8 -8
- package/src/eslint-rules/require-route-security-policy.cjs +87 -0
- package/src/eslint-rules/require-server-function-timeout.cjs +39 -0
- package/src/eslint-rules/security-config.cjs +14 -0
- package/src/eslint-rules/security-rule-utils.cjs +21 -0
- package/src/eslint-rules/style-file-boundary.cjs +75 -0
- package/src/eslint-rules/sync-effect-body.cjs +343 -0
- package/src/index.d.ts +4 -0
- package/src/index.js +4 -0
- package/src/index.js.map +1 -1
- package/src/scripts/architecture-graph.js +8 -2
- package/src/scripts/architecture-graph.js.map +1 -1
- package/src/scripts/create/create-project.d.ts +60 -1
- package/src/scripts/create/create-project.js +2082 -184
- package/src/scripts/create/create-project.js.map +1 -1
- package/src/scripts/data-flow-graph.d.ts +1 -1
- package/src/scripts/effect-dependency-graph.d.ts +1 -1
- package/src/scripts/security-check.d.ts +30 -0
- package/src/scripts/security-check.js +223 -0
- package/src/scripts/security-check.js.map +1 -0
- package/src/scripts/style-architecture.d.ts +56 -0
- package/src/scripts/style-architecture.js +142 -0
- package/src/scripts/style-architecture.js.map +1 -0
- package/src/scripts/style-graph.d.ts +99 -0
- package/src/scripts/style-graph.js +179 -0
- package/src/scripts/style-graph.js.map +1 -0
- package/src/scripts/style-report.d.ts +55 -0
- package/src/scripts/style-report.js +67 -0
- package/src/scripts/style-report.js.map +1 -0
- package/src/scripts/template/migrate-template.js +1 -1
- package/src/scripts/template/migrate-template.js.map +1 -1
- package/src/scripts/angular-brand-codemod.ts +0 -3985
- package/src/scripts/architecture/migrate-architecture.ts +0 -653
- package/src/scripts/architecture-graph.ts +0 -3136
- package/src/scripts/components/migrate-components.ts +0 -227
- package/src/scripts/components/migration-diagnostic.ts +0 -8
- package/src/scripts/create/create-project.ts +0 -849
- package/src/scripts/data-flow-graph.ts +0 -240
- package/src/scripts/dependency-graph.ts +0 -5908
- package/src/scripts/effect-dependency-graph.ts +0 -630
- package/src/scripts/migrate.ts +0 -162
- package/src/scripts/migration-workspace.ts +0 -93
- package/src/scripts/primitives/migrate-named-primitives.ts +0 -627
- package/src/scripts/primitives/migrate-primitive-generators.ts +0 -410
- package/src/scripts/primitives/migrate-primitives.ts +0 -655
- package/src/scripts/primitives/migrate-yieldable-reactive-reads.ts +0 -499
- package/src/scripts/primitives/migration-diagnostic.ts +0 -15
- package/src/scripts/routes/migrate-routes.ts +0 -895
- package/src/scripts/routes/migration-diagnostic.ts +0 -25
- package/src/scripts/routes/route-command.ts +0 -1807
- package/src/scripts/routes/verify-routes.ts +0 -1511
- package/src/scripts/services/config.ts +0 -60
- package/src/scripts/services/migrate-services.ts +0 -1348
- package/src/scripts/services/migration-diagnostic.ts +0 -28
- 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
|
-
}
|