@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,162 +0,0 @@
1
- import { mkdir, writeFile } from 'node:fs/promises';
2
- import { dirname, resolve } from 'node:path';
3
- import {
4
- runPrimitivesMigration,
5
- type MigratePrimitivesResult,
6
- } from './primitives/migrate-primitives.js';
7
- import {
8
- runRoutesMigration,
9
- type MigrateRoutesResult,
10
- } from './routes/migrate-routes.js';
11
- import {
12
- runServicesMigration,
13
- type MigrateServicesResult,
14
- } from './services/migrate-services.js';
15
- import {
16
- runComponentsMigration,
17
- type MigrateComponentsResult,
18
- } from './components/migrate-components.js';
19
- import {
20
- runArchitectureMigration,
21
- type MigrateArchitectureResult,
22
- } from './architecture/migrate-architecture.js';
23
-
24
- export type MigrateOptions = {
25
- rootDir?: string;
26
- tsConfigFilePath?: string;
27
- configFilePath?: string;
28
- files?: readonly string[];
29
- write?: boolean;
30
- check?: boolean;
31
- json?: boolean;
32
- jsonFilePath?: string;
33
- failOnManual?: boolean;
34
- eslint?: boolean;
35
- collectionName?: string;
36
- parentMount?: string;
37
- parentNames?: readonly string[];
38
- log?: (message: string) => void;
39
- };
40
-
41
- export type MigrateResult = {
42
- primitives: MigratePrimitivesResult;
43
- services: MigrateServicesResult;
44
- routes: MigrateRoutesResult;
45
- components: MigrateComponentsResult;
46
- architecture: MigrateArchitectureResult;
47
- changedFiles: string[];
48
- diagnostics: {
49
- primitives: MigratePrimitivesResult['diagnostics'];
50
- services: MigrateServicesResult['diagnostics'];
51
- routes: MigrateRoutesResult['diagnostics'];
52
- components: MigrateComponentsResult['diagnostics'];
53
- };
54
- exitCode: number;
55
- };
56
-
57
- export async function runMigration(
58
- options: MigrateOptions = {},
59
- ): Promise<MigrateResult> {
60
- const log = options.log ?? console.log;
61
- const stepLog = options.json ? () => undefined : log;
62
- const shared = {
63
- rootDir: options.rootDir,
64
- tsConfigFilePath: options.tsConfigFilePath,
65
- files: options.files,
66
- write: options.write,
67
- check: options.check,
68
- failOnManual: options.failOnManual,
69
- log: stepLog,
70
- };
71
-
72
- if (!options.json) log('1/5 Migrating primitives and Signal Forms...');
73
- const primitives = await runPrimitivesMigration({
74
- ...shared,
75
- eslint: options.eslint,
76
- });
77
-
78
- if (!options.json) log('2/5 Migrating Angular services...');
79
- const services = await runServicesMigration({
80
- ...shared,
81
- configFilePath: options.configFilePath,
82
- eslint: options.eslint,
83
- });
84
-
85
- if (!options.json) log('3/5 Migrating Angular routes...');
86
- const routes = await runRoutesMigration({
87
- ...shared,
88
- collectionName: options.collectionName,
89
- parentMount: options.parentMount,
90
- parentNames: options.parentNames,
91
- });
92
-
93
- if (!options.json) log('4/5 Migrating Craft components and directives...');
94
- const components = await runComponentsMigration({
95
- ...shared,
96
- eslint: options.eslint,
97
- });
98
-
99
- if (!options.json) log('5/5 Scaffolding architecture tests...');
100
- const architecture = await runArchitectureMigration({
101
- rootDir: options.rootDir,
102
- tsConfigFilePath: options.tsConfigFilePath,
103
- write: options.write,
104
- check: options.check,
105
- log: stepLog,
106
- });
107
-
108
- const result: MigrateResult = {
109
- primitives,
110
- services,
111
- routes,
112
- components,
113
- architecture,
114
- changedFiles: [
115
- ...new Set([
116
- ...primitives.changedFiles,
117
- ...services.changedFiles,
118
- ...routes.changedFiles,
119
- ...components.changedFiles,
120
- ...architecture.changedFiles,
121
- ]),
122
- ],
123
- diagnostics: {
124
- primitives: primitives.diagnostics,
125
- services: services.diagnostics,
126
- routes: routes.diagnostics,
127
- components: components.diagnostics,
128
- },
129
- exitCode: Math.max(
130
- primitives.exitCode,
131
- services.exitCode,
132
- routes.exitCode,
133
- components.exitCode,
134
- architecture.exitCode,
135
- ),
136
- };
137
-
138
- if (options.jsonFilePath) {
139
- const path = resolve(options.jsonFilePath);
140
- await mkdir(dirname(path), { recursive: true });
141
- await writeFile(path, `${JSON.stringify(result, null, 2)}\n`, 'utf8');
142
- }
143
-
144
- if (options.json) log(JSON.stringify(result, null, 2));
145
- else {
146
- const manualCount =
147
- primitives.diagnostics.length +
148
- services.diagnostics.length +
149
- routes.diagnostics.length +
150
- components.diagnostics.length;
151
- log(
152
- `Migration complete: ${result.changedFiles.length} changed file(s), ${manualCount} manual diagnostic(s).`,
153
- );
154
- if (manualCount > 0) {
155
- log(
156
- 'Review the diagnostics, then run the project type-check, tests and production build.',
157
- );
158
- }
159
- }
160
-
161
- return result;
162
- }
@@ -1,93 +0,0 @@
1
- import { existsSync } from 'node:fs';
2
- import { dirname, join, resolve } from 'node:path';
3
- import { Node, Project, SourceFile, SyntaxKind } from 'ts-morph';
4
-
5
- const ESLINT_CONFIG_NAMES = [
6
- 'eslint.config.js',
7
- 'eslint.config.mjs',
8
- 'eslint.config.cjs',
9
- 'eslint.config.ts',
10
- 'eslint.config.mts',
11
- 'eslint.config.cts',
12
- ];
13
-
14
- export function migrateEslintConfig(
15
- project: Project,
16
- searchFromDir: string,
17
- ): SourceFile | undefined {
18
- const filePath = findUp(searchFromDir, ESLINT_CONFIG_NAMES);
19
- if (!filePath) return undefined;
20
- const sourceFile =
21
- project.getSourceFile(filePath) ?? project.addSourceFileAtPath(filePath);
22
- const rulesObjects = sourceFile
23
- .getDescendantsOfKind(SyntaxKind.PropertyAssignment)
24
- .filter((property) => property.getName() === 'rules')
25
- .map((property) => ({
26
- config: property.getFirstAncestorByKind(SyntaxKind.ObjectLiteralExpression),
27
- rules: property.getInitializer(),
28
- }))
29
- .filter(
30
- (entry): entry is { config: NonNullable<typeof entry.config>; rules: NonNullable<typeof entry.rules> } =>
31
- Boolean(entry.config && Node.isObjectLiteralExpression(entry.rules)),
32
- );
33
- const rulesEntry =
34
- rulesObjects.find((entry) =>
35
- /\*\*\/\*\.ts|\.tsx|\[jt\]s/.test(
36
- entry.config.getProperty('files')?.getText() ?? '',
37
- ),
38
- ) ?? rulesObjects.at(-1);
39
- const rules =
40
- rulesEntry && Node.isObjectLiteralExpression(rulesEntry.rules)
41
- ? rulesEntry.rules
42
- : undefined;
43
- if (!rules) return undefined;
44
- const changedReturnTypeRule = setRule(
45
- rules,
46
- '@typescript-eslint/explicit-function-return-type',
47
- "'off'",
48
- );
49
- const changedEmptyObjectRule = setRule(
50
- rules,
51
- '@typescript-eslint/no-empty-object-type',
52
- "['error', { allowObjectTypes: 'always' }]",
53
- );
54
- return changedReturnTypeRule || changedEmptyObjectRule ? sourceFile : undefined;
55
- }
56
-
57
- function setRule(
58
- rules: import('ts-morph').ObjectLiteralExpression,
59
- ruleName: string,
60
- initializer: string,
61
- ): boolean {
62
- const existing = rules.getProperty(
63
- (property) =>
64
- Node.isPropertyAssignment(property) &&
65
- getPropertyName(property.getNameNode()) === ruleName,
66
- );
67
- if (Node.isPropertyAssignment(existing)) {
68
- if (existing.getInitializer()?.getText() === initializer) return false;
69
- existing.setInitializer(initializer);
70
- } else {
71
- rules.addPropertyAssignment({ name: `'${ruleName}'`, initializer });
72
- }
73
- return true;
74
- }
75
-
76
- function getPropertyName(node: Node): string {
77
- return Node.isStringLiteral(node) || Node.isNoSubstitutionTemplateLiteral(node)
78
- ? node.getLiteralValue()
79
- : node.getText();
80
- }
81
-
82
- function findUp(startDir: string, names: readonly string[]): string | undefined {
83
- let current = resolve(startDir);
84
- while (true) {
85
- for (const name of names) {
86
- const candidate = join(current, name);
87
- if (existsSync(candidate)) return candidate;
88
- }
89
- const parent = dirname(current);
90
- if (parent === current) return undefined;
91
- current = parent;
92
- }
93
- }