@alexgorbatchev/typescript-ai-policy 0.1.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 (62) hide show
  1. package/README.md +223 -0
  2. package/package.json +60 -0
  3. package/src/oxfmt/createOxfmtConfig.ts +26 -0
  4. package/src/oxlint/assertNoRuleCollisions.ts +40 -0
  5. package/src/oxlint/createOxlintConfig.ts +161 -0
  6. package/src/oxlint/oxlint.config.ts +3 -0
  7. package/src/oxlint/plugin.ts +90 -0
  8. package/src/oxlint/rules/component-directory-file-convention.ts +65 -0
  9. package/src/oxlint/rules/component-file-contract.ts +328 -0
  10. package/src/oxlint/rules/component-file-location-convention.ts +43 -0
  11. package/src/oxlint/rules/component-file-naming-convention.ts +260 -0
  12. package/src/oxlint/rules/component-story-file-convention.ts +108 -0
  13. package/src/oxlint/rules/fixture-export-naming-convention.ts +72 -0
  14. package/src/oxlint/rules/fixture-export-type-contract.ts +264 -0
  15. package/src/oxlint/rules/fixture-file-contract.ts +91 -0
  16. package/src/oxlint/rules/fixture-import-path-convention.ts +125 -0
  17. package/src/oxlint/rules/helpers.ts +544 -0
  18. package/src/oxlint/rules/hook-export-location-convention.ts +169 -0
  19. package/src/oxlint/rules/hook-file-contract.ts +179 -0
  20. package/src/oxlint/rules/hook-file-naming-convention.ts +151 -0
  21. package/src/oxlint/rules/hook-test-file-convention.ts +60 -0
  22. package/src/oxlint/rules/hooks-directory-file-convention.ts +75 -0
  23. package/src/oxlint/rules/index-file-contract.ts +177 -0
  24. package/src/oxlint/rules/interface-naming-convention.ts +72 -0
  25. package/src/oxlint/rules/no-conditional-logic-in-tests.ts +53 -0
  26. package/src/oxlint/rules/no-fixture-exports-outside-fixture-entrypoint.ts +68 -0
  27. package/src/oxlint/rules/no-imports-from-tests-directory.ts +114 -0
  28. package/src/oxlint/rules/no-inline-fixture-bindings-in-tests.ts +54 -0
  29. package/src/oxlint/rules/no-inline-type-expressions.ts +169 -0
  30. package/src/oxlint/rules/no-local-type-declarations-in-fixture-files.ts +55 -0
  31. package/src/oxlint/rules/no-module-mocking.ts +85 -0
  32. package/src/oxlint/rules/no-non-running-tests.ts +72 -0
  33. package/src/oxlint/rules/no-react-create-element.ts +59 -0
  34. package/src/oxlint/rules/no-test-file-exports.ts +52 -0
  35. package/src/oxlint/rules/no-throw-in-tests.ts +40 -0
  36. package/src/oxlint/rules/no-type-exports-from-constants.ts +97 -0
  37. package/src/oxlint/rules/no-type-imports-from-constants.ts +73 -0
  38. package/src/oxlint/rules/no-value-exports-from-types.ts +115 -0
  39. package/src/oxlint/rules/require-component-root-testid.ts +547 -0
  40. package/src/oxlint/rules/require-template-indent.ts +83 -0
  41. package/src/oxlint/rules/single-fixture-entrypoint.ts +142 -0
  42. package/src/oxlint/rules/stories-directory-file-convention.ts +55 -0
  43. package/src/oxlint/rules/story-export-contract.ts +343 -0
  44. package/src/oxlint/rules/story-file-location-convention.ts +64 -0
  45. package/src/oxlint/rules/story-meta-type-annotation.ts +129 -0
  46. package/src/oxlint/rules/test-file-location-convention.ts +115 -0
  47. package/src/oxlint/rules/testid-naming-convention.ts +63 -0
  48. package/src/oxlint/rules/tests-directory-file-convention.ts +55 -0
  49. package/src/oxlint/rules/types.ts +45 -0
  50. package/src/semantic-fixes/applyFileChanges.ts +81 -0
  51. package/src/semantic-fixes/applySemanticFixes.ts +239 -0
  52. package/src/semantic-fixes/applyTextEdits.ts +164 -0
  53. package/src/semantic-fixes/backends/tsgo-lsp/TsgoLspClient.ts +439 -0
  54. package/src/semantic-fixes/backends/tsgo-lsp/createTsgoLspSemanticFixBackend.ts +251 -0
  55. package/src/semantic-fixes/providers/createInterfaceNamingConventionSemanticFixProvider.ts +132 -0
  56. package/src/semantic-fixes/providers/createTestFileLocationConventionSemanticFixProvider.ts +52 -0
  57. package/src/semantic-fixes/readMovedFileTextEdits.ts +150 -0
  58. package/src/semantic-fixes/readSemanticFixRuntimePaths.ts +38 -0
  59. package/src/semantic-fixes/runApplySemanticFixes.ts +120 -0
  60. package/src/semantic-fixes/runOxlintJson.ts +139 -0
  61. package/src/semantic-fixes/types.ts +163 -0
  62. package/src/shared/mergeConfig.ts +38 -0
@@ -0,0 +1,163 @@
1
+ export type IOxlintSpan = {
2
+ column: number;
3
+ length: number;
4
+ line: number;
5
+ offset: number;
6
+ };
7
+
8
+ export type IOxlintLabel = {
9
+ label?: string;
10
+ span: IOxlintSpan;
11
+ };
12
+
13
+ export type IOxlintDiagnostic = {
14
+ code: string;
15
+ filename: string;
16
+ labels: readonly IOxlintLabel[];
17
+ message: string;
18
+ severity: string;
19
+ };
20
+
21
+ export type IOxlintJsonReport = {
22
+ diagnostics: readonly IOxlintDiagnostic[];
23
+ };
24
+
25
+ export type ILineAndCharacter = {
26
+ character: number;
27
+ line: number;
28
+ };
29
+
30
+ export type ITextEdit = {
31
+ end: ILineAndCharacter;
32
+ filePath: string;
33
+ newText: string;
34
+ start: ILineAndCharacter;
35
+ };
36
+
37
+ export type ISymbolRenameOperation = {
38
+ filePath: string;
39
+ id: string;
40
+ kind: "rename-symbol";
41
+ newName: string;
42
+ position: ILineAndCharacter;
43
+ ruleCode: string;
44
+ symbolName: string;
45
+ };
46
+
47
+ export type IMoveFileOperation = {
48
+ filePath: string;
49
+ id: string;
50
+ kind: "move-file";
51
+ newFilePath: string;
52
+ ruleCode: string;
53
+ };
54
+
55
+ export type ISemanticFixOperation = ISymbolRenameOperation | IMoveFileOperation;
56
+
57
+ export type IFileMove = {
58
+ destinationFilePath: string;
59
+ sourceFilePath: string;
60
+ };
61
+
62
+ export type ISemanticFixPlan = {
63
+ description: string;
64
+ fileMoves: readonly IFileMove[];
65
+ operationId: string;
66
+ ruleCode: string;
67
+ textEdits: readonly ITextEdit[];
68
+ };
69
+
70
+ export type ISemanticFixPlanSuccess = {
71
+ kind: "plan";
72
+ plan: ISemanticFixPlan;
73
+ };
74
+
75
+ export type ISemanticFixPlanSkip = {
76
+ kind: "skip";
77
+ reason: string;
78
+ };
79
+
80
+ export type ISemanticFixPlanResult = ISemanticFixPlanSkip | ISemanticFixPlanSuccess;
81
+
82
+ export type ISemanticFixProviderContext = {
83
+ targetDirectoryPath: string;
84
+ };
85
+
86
+ export type ISemanticFixProvider = {
87
+ createOperation: (
88
+ diagnostic: IOxlintDiagnostic,
89
+ context: ISemanticFixProviderContext,
90
+ ) => ISemanticFixOperation | null;
91
+ ruleCode: string;
92
+ };
93
+
94
+ export type ISemanticFixBackendContext = {
95
+ targetDirectoryPath: string;
96
+ };
97
+
98
+ export type ISemanticFixBackend = {
99
+ createPlan: (
100
+ operation: ISemanticFixOperation,
101
+ context: ISemanticFixBackendContext,
102
+ ) => Promise<ISemanticFixPlanResult>;
103
+ dispose: () => Promise<void>;
104
+ name: string;
105
+ };
106
+
107
+ export type IApplySemanticFixesProgressEvent =
108
+ | {
109
+ kind: "running-oxlint";
110
+ targetDirectoryPath: string;
111
+ }
112
+ | {
113
+ diagnosticCount: number;
114
+ kind: "collected-diagnostics";
115
+ }
116
+ | {
117
+ kind: "planning-start";
118
+ operationCount: number;
119
+ }
120
+ | {
121
+ description: string;
122
+ kind: "planning-operation";
123
+ operationCount: number;
124
+ operationId: string;
125
+ operationIndex: number;
126
+ }
127
+ | {
128
+ dryRun: boolean;
129
+ fileCount: number;
130
+ kind: "applying-file-changes";
131
+ moveCount: number;
132
+ textEditCount: number;
133
+ }
134
+ | {
135
+ appliedFileCount: number;
136
+ changedFileCount: number;
137
+ kind: "complete";
138
+ plannedFixCount: number;
139
+ skippedDiagnosticCount: number;
140
+ };
141
+
142
+ export type IApplySemanticFixesOptions = {
143
+ dryRun?: boolean;
144
+ onProgress?: (event: IApplySemanticFixesProgressEvent) => void;
145
+ oxlintConfigPath: string;
146
+ oxlintExecutablePath: string;
147
+ targetDirectoryPath: string;
148
+ tsgoExecutablePath: string;
149
+ };
150
+
151
+ export type ISkippedDiagnostic = {
152
+ filePath: string;
153
+ reason: string;
154
+ ruleCode: string;
155
+ };
156
+
157
+ export type IApplySemanticFixesResult = {
158
+ appliedFileCount: number;
159
+ backendName: string;
160
+ changedFilePaths: readonly string[];
161
+ plannedFixCount: number;
162
+ skippedDiagnostics: readonly ISkippedDiagnostic[];
163
+ };
@@ -0,0 +1,38 @@
1
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
2
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3
+ }
4
+
5
+ function mergeValue(userValue: unknown, defaultValue: unknown): unknown {
6
+ if (Array.isArray(userValue) && Array.isArray(defaultValue)) {
7
+ return [...userValue, ...defaultValue];
8
+ }
9
+
10
+ if (isPlainObject(userValue) && isPlainObject(defaultValue)) {
11
+ const mergedValue: Record<string, unknown> = structuredClone(userValue);
12
+
13
+ for (const [key, value] of Object.entries(defaultValue)) {
14
+ if (Object.hasOwn(mergedValue, key)) {
15
+ mergedValue[key] = mergeValue(mergedValue[key], value);
16
+ continue;
17
+ }
18
+
19
+ mergedValue[key] = structuredClone(value);
20
+ }
21
+
22
+ return mergedValue;
23
+ }
24
+
25
+ return structuredClone(defaultValue);
26
+ }
27
+
28
+ /**
29
+ * Deep-merge two config objects with user values applied first and defaults applied last.
30
+ * This preserves all default policy values while still allowing additive user extensions.
31
+ */
32
+ export function mergeConfig<TConfig extends Record<string, unknown>>(
33
+ userConfig: TConfig,
34
+ defaultConfig: TConfig,
35
+ ): TConfig;
36
+ export function mergeConfig(userConfig: unknown, defaultConfig: unknown): unknown {
37
+ return mergeValue(structuredClone(userConfig), defaultConfig);
38
+ }