@ontrails/warden 1.0.0-beta.4 → 1.0.0-beta.41

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 (279) hide show
  1. package/CHANGELOG.md +835 -13
  2. package/README.md +133 -26
  3. package/bin/warden.ts +51 -0
  4. package/package.json +27 -6
  5. package/src/adapter-check.ts +136 -0
  6. package/src/cli.ts +1570 -105
  7. package/src/command.ts +986 -0
  8. package/src/config.ts +193 -0
  9. package/src/draft.ts +22 -0
  10. package/src/drift.ts +233 -23
  11. package/src/fix.ts +126 -0
  12. package/src/formatters.ts +78 -13
  13. package/src/guide.ts +245 -0
  14. package/src/index.ts +247 -15
  15. package/src/project-context.ts +446 -0
  16. package/src/project-rules.ts +290 -0
  17. package/src/resolve.ts +531 -0
  18. package/src/rules/activation-orphan.ts +97 -0
  19. package/src/rules/captured-kernel.ts +375 -0
  20. package/src/rules/circular-refs.ts +150 -0
  21. package/src/rules/cli-command-route-coherence.ts +177 -0
  22. package/src/rules/composes-declarations.ts +839 -0
  23. package/src/rules/context-no-surface-types.ts +79 -15
  24. package/src/rules/dead-internal-trail.ts +161 -0
  25. package/src/rules/dead-public-trail.ts +258 -0
  26. package/src/rules/draft-file-marking.ts +155 -0
  27. package/src/rules/draft-visible-debt.ts +82 -0
  28. package/src/rules/duplicate-exported-symbol.ts +211 -0
  29. package/src/rules/duplicate-public-contract.ts +137 -0
  30. package/src/rules/entity-exists.ts +254 -0
  31. package/src/rules/entity-ids.ts +15 -0
  32. package/src/rules/error-mapping-completeness.ts +290 -0
  33. package/src/rules/example-valid.ts +395 -0
  34. package/src/rules/fires-declarations.ts +740 -0
  35. package/src/rules/governed-symbol-residue.ts +438 -0
  36. package/src/rules/implementation-returns-result.ts +1409 -166
  37. package/src/rules/incomplete-accessor-for-standard-op.ts +272 -0
  38. package/src/rules/incomplete-crud.ts +583 -0
  39. package/src/rules/index.ts +277 -10
  40. package/src/rules/intent-propagation.ts +125 -0
  41. package/src/rules/layer-field-name-drift.ts +102 -0
  42. package/src/rules/library-projection-coherence.ts +100 -0
  43. package/src/rules/metadata.ts +871 -0
  44. package/src/rules/missing-reconcile.ts +97 -0
  45. package/src/rules/missing-visibility.ts +111 -0
  46. package/src/rules/no-destructured-compose.ts +196 -0
  47. package/src/rules/no-dev-permit-in-source.ts +99 -0
  48. package/src/rules/no-direct-implementation-call.ts +12 -7
  49. package/src/rules/no-legacy-cli-alias-export.ts +247 -0
  50. package/src/rules/no-legacy-layer-imports.ts +211 -0
  51. package/src/rules/no-native-error-result.ts +118 -0
  52. package/src/rules/no-redundant-result-error-wrap.ts +384 -0
  53. package/src/rules/no-retired-cross-vocabulary.ts +204 -0
  54. package/src/rules/no-sync-result-assumption.ts +1141 -98
  55. package/src/rules/no-throw-in-detour-recover.ts +225 -0
  56. package/src/rules/no-throw-in-implementation.ts +15 -8
  57. package/src/rules/no-top-level-surface.ts +371 -0
  58. package/src/rules/on-references-exist.ts +194 -0
  59. package/src/rules/orphaned-signal.ts +149 -0
  60. package/src/rules/owner-projection-parity.ts +143 -0
  61. package/src/rules/permit-governance.ts +25 -0
  62. package/src/rules/public-export-example-coverage.ts +573 -0
  63. package/src/rules/public-internal-deep-imports.ts +456 -0
  64. package/src/rules/public-output-schema.ts +29 -0
  65. package/src/rules/public-union-output-discriminants.ts +150 -0
  66. package/src/rules/read-intent-fires.ts +188 -0
  67. package/src/rules/reference-exists.ts +97 -0
  68. package/src/rules/registry-names.ts +167 -0
  69. package/src/rules/resolved-import-boundary.ts +146 -0
  70. package/src/rules/resource-declarations.ts +697 -0
  71. package/src/rules/resource-exists.ts +181 -0
  72. package/src/rules/resource-id-grammar.ts +65 -0
  73. package/src/rules/resource-mock-coverage.ts +115 -0
  74. package/src/rules/retired-vocabulary.ts +633 -0
  75. package/src/rules/scan.ts +38 -25
  76. package/src/rules/scheduled-destroy-intent.ts +44 -0
  77. package/src/rules/signal-graph-coaching.ts +220 -0
  78. package/src/rules/source/composition.ts +165 -0
  79. package/src/rules/source/drafts.ts +164 -0
  80. package/src/rules/source/entities.ts +618 -0
  81. package/src/rules/source/pragmas.ts +45 -0
  82. package/src/rules/source/resources.ts +64 -0
  83. package/src/rules/source/signals.ts +397 -0
  84. package/src/rules/source/stores.ts +310 -0
  85. package/src/rules/specs.ts +9 -5
  86. package/src/rules/static-resource-accessor-preference.ts +653 -0
  87. package/src/rules/surface-overlay-coherence.ts +262 -0
  88. package/src/rules/surface-trailhead-coherence.ts +366 -0
  89. package/src/rules/trail-fork-coaching.ts +625 -0
  90. package/src/rules/trail-versioning-source.ts +1076 -0
  91. package/src/rules/trail-versioning-topo.ts +172 -0
  92. package/src/rules/trailhead-override-divergence.ts +356 -0
  93. package/src/rules/types.ts +354 -8
  94. package/src/rules/unmaterialized-activation-source.ts +85 -0
  95. package/src/rules/unreachable-detour-shadowing.ts +339 -0
  96. package/src/rules/valid-describe-refs.ts +162 -32
  97. package/src/rules/valid-detour-contract.ts +78 -0
  98. package/src/rules/warden-export-symmetry.ts +540 -0
  99. package/src/rules/warden-rules-use-ast.ts +1109 -0
  100. package/src/rules/webhook-route-collision.ts +306 -0
  101. package/src/trails/activation-orphan.trail.ts +84 -0
  102. package/src/trails/captured-kernel.trail.ts +108 -0
  103. package/src/trails/circular-refs.trail.ts +29 -0
  104. package/src/trails/cli-command-route-coherence.trail.ts +47 -0
  105. package/src/trails/composes-declarations.trail.ts +22 -0
  106. package/src/trails/context-no-surface-types.trail.ts +21 -0
  107. package/src/trails/dead-internal-trail.trail.ts +26 -0
  108. package/src/trails/dead-public-trail.trail.ts +31 -0
  109. package/src/trails/deprecation-without-guidance.trail.ts +21 -0
  110. package/src/trails/draft-file-marking.trail.ts +16 -0
  111. package/src/trails/draft-visible-debt.trail.ts +16 -0
  112. package/src/trails/duplicate-exported-symbol.trail.ts +48 -0
  113. package/src/trails/duplicate-public-contract.trail.ts +47 -0
  114. package/src/trails/entity-exists.trail.ts +21 -0
  115. package/src/trails/error-mapping-completeness.trail.ts +30 -0
  116. package/src/trails/example-valid.trail.ts +25 -0
  117. package/src/trails/fires-declarations.trail.ts +23 -0
  118. package/src/trails/fork-without-preserved-implementation.trail.ts +31 -0
  119. package/src/trails/governed-symbol-residue.trail.ts +24 -0
  120. package/src/trails/implementation-returns-result.trail.ts +20 -0
  121. package/src/trails/incomplete-accessor-for-standard-op.trail.ts +76 -0
  122. package/src/trails/incomplete-crud.trail.ts +39 -0
  123. package/src/trails/index.ts +89 -0
  124. package/src/trails/intent-propagation.trail.ts +30 -0
  125. package/src/trails/layer-field-name-drift.trail.ts +39 -0
  126. package/src/trails/library-projection-coherence.trail.ts +43 -0
  127. package/src/trails/marker-schema-unsupported.trail.ts +23 -0
  128. package/src/trails/missing-reconcile.trail.ts +33 -0
  129. package/src/trails/missing-visibility.trail.ts +22 -0
  130. package/src/trails/no-destructured-compose.trail.ts +44 -0
  131. package/src/trails/no-dev-permit-in-source.trail.ts +16 -0
  132. package/src/trails/no-direct-implementation-call.trail.ts +16 -0
  133. package/src/trails/no-legacy-cli-alias-export.trail.ts +41 -0
  134. package/src/trails/no-legacy-layer-imports.trail.ts +41 -0
  135. package/src/trails/no-native-error-result.trail.ts +18 -0
  136. package/src/trails/no-redundant-result-error-wrap.trail.ts +55 -0
  137. package/src/trails/no-retired-cross-vocabulary.trail.ts +42 -0
  138. package/src/trails/no-sync-result-assumption.trail.ts +19 -0
  139. package/src/trails/no-throw-in-detour-recover.trail.ts +24 -0
  140. package/src/trails/no-throw-in-implementation.trail.ts +20 -0
  141. package/src/trails/no-top-level-surface.trail.ts +43 -0
  142. package/src/trails/on-references-exist.trail.ts +21 -0
  143. package/src/trails/orphaned-signal.trail.ts +36 -0
  144. package/src/trails/owner-projection-parity.trail.ts +26 -0
  145. package/src/trails/pending-force.trail.ts +21 -0
  146. package/src/trails/permit-governance.trail.ts +51 -0
  147. package/src/trails/prefer-schema-inference.trail.ts +21 -0
  148. package/src/trails/public-export-example-coverage.trail.ts +16 -0
  149. package/src/trails/public-internal-deep-imports.trail.ts +94 -0
  150. package/src/trails/public-output-schema.trail.ts +55 -0
  151. package/src/trails/public-union-output-discriminants.trail.ts +33 -0
  152. package/src/trails/read-intent-fires.trail.ts +20 -0
  153. package/src/trails/reference-exists.trail.ts +25 -0
  154. package/src/trails/resolved-import-boundary.trail.ts +109 -0
  155. package/src/trails/resource-declarations.trail.ts +25 -0
  156. package/src/trails/resource-exists.trail.ts +27 -0
  157. package/src/trails/resource-id-grammar.trail.ts +39 -0
  158. package/src/trails/resource-mock-coverage.trail.ts +40 -0
  159. package/src/trails/run.ts +160 -0
  160. package/src/trails/scheduled-destroy-intent.trail.ts +56 -0
  161. package/src/trails/schema.ts +237 -0
  162. package/src/trails/signal-graph-coaching.trail.ts +77 -0
  163. package/src/trails/static-resource-accessor-preference.trail.ts +25 -0
  164. package/src/trails/surface-overlay-coherence.trail.ts +24 -0
  165. package/src/trails/surface-trailhead-coherence.trail.ts +25 -0
  166. package/src/trails/topo.ts +6 -0
  167. package/src/trails/trail-fork-coaching.trail.ts +42 -0
  168. package/src/trails/trailhead-override-divergence.trail.ts +47 -0
  169. package/src/trails/unmaterialized-activation-source.trail.ts +72 -0
  170. package/src/trails/unreachable-detour-shadowing.trail.ts +45 -0
  171. package/src/trails/valid-describe-refs.trail.ts +18 -0
  172. package/src/trails/valid-detour-contract.trail.ts +71 -0
  173. package/src/trails/version-gap.trail.ts +35 -0
  174. package/src/trails/version-pinned-compose.trail.ts +23 -0
  175. package/src/trails/version-without-examples.trail.ts +38 -0
  176. package/src/trails/warden-export-symmetry.trail.ts +16 -0
  177. package/src/trails/warden-rules-use-ast.trail.ts +64 -0
  178. package/src/trails/webhook-route-collision.trail.ts +50 -0
  179. package/src/trails/wrap-rule.ts +224 -0
  180. package/src/workspaces.ts +199 -0
  181. package/.turbo/turbo-build.log +0 -1
  182. package/.turbo/turbo-lint.log +0 -3
  183. package/.turbo/turbo-typecheck.log +0 -1
  184. package/dist/cli.d.ts +0 -46
  185. package/dist/cli.d.ts.map +0 -1
  186. package/dist/cli.js +0 -218
  187. package/dist/cli.js.map +0 -1
  188. package/dist/drift.d.ts +0 -26
  189. package/dist/drift.d.ts.map +0 -1
  190. package/dist/drift.js +0 -27
  191. package/dist/drift.js.map +0 -1
  192. package/dist/formatters.d.ts +0 -29
  193. package/dist/formatters.d.ts.map +0 -1
  194. package/dist/formatters.js +0 -87
  195. package/dist/formatters.js.map +0 -1
  196. package/dist/index.d.ts +0 -26
  197. package/dist/index.d.ts.map +0 -1
  198. package/dist/index.js +0 -26
  199. package/dist/index.js.map +0 -1
  200. package/dist/rules/ast.d.ts +0 -41
  201. package/dist/rules/ast.d.ts.map +0 -1
  202. package/dist/rules/ast.js +0 -161
  203. package/dist/rules/ast.js.map +0 -1
  204. package/dist/rules/context-no-surface-types.d.ts +0 -12
  205. package/dist/rules/context-no-surface-types.d.ts.map +0 -1
  206. package/dist/rules/context-no-surface-types.js +0 -96
  207. package/dist/rules/context-no-surface-types.js.map +0 -1
  208. package/dist/rules/implementation-returns-result.d.ts +0 -13
  209. package/dist/rules/implementation-returns-result.d.ts.map +0 -1
  210. package/dist/rules/implementation-returns-result.js +0 -277
  211. package/dist/rules/implementation-returns-result.js.map +0 -1
  212. package/dist/rules/index.d.ts +0 -15
  213. package/dist/rules/index.d.ts.map +0 -1
  214. package/dist/rules/index.js +0 -34
  215. package/dist/rules/index.js.map +0 -1
  216. package/dist/rules/no-direct-impl-in-route.d.ts +0 -12
  217. package/dist/rules/no-direct-impl-in-route.d.ts.map +0 -1
  218. package/dist/rules/no-direct-impl-in-route.js +0 -47
  219. package/dist/rules/no-direct-impl-in-route.js.map +0 -1
  220. package/dist/rules/no-direct-implementation-call.d.ts +0 -12
  221. package/dist/rules/no-direct-implementation-call.d.ts.map +0 -1
  222. package/dist/rules/no-direct-implementation-call.js +0 -39
  223. package/dist/rules/no-direct-implementation-call.js.map +0 -1
  224. package/dist/rules/no-sync-result-assumption.d.ts +0 -6
  225. package/dist/rules/no-sync-result-assumption.d.ts.map +0 -1
  226. package/dist/rules/no-sync-result-assumption.js +0 -98
  227. package/dist/rules/no-sync-result-assumption.js.map +0 -1
  228. package/dist/rules/no-throw-in-detour-target.d.ts +0 -12
  229. package/dist/rules/no-throw-in-detour-target.d.ts.map +0 -1
  230. package/dist/rules/no-throw-in-detour-target.js +0 -87
  231. package/dist/rules/no-throw-in-detour-target.js.map +0 -1
  232. package/dist/rules/no-throw-in-implementation.d.ts +0 -9
  233. package/dist/rules/no-throw-in-implementation.d.ts.map +0 -1
  234. package/dist/rules/no-throw-in-implementation.js +0 -34
  235. package/dist/rules/no-throw-in-implementation.js.map +0 -1
  236. package/dist/rules/prefer-schema-inference.d.ts +0 -7
  237. package/dist/rules/prefer-schema-inference.d.ts.map +0 -1
  238. package/dist/rules/prefer-schema-inference.js +0 -86
  239. package/dist/rules/prefer-schema-inference.js.map +0 -1
  240. package/dist/rules/scan.d.ts +0 -8
  241. package/dist/rules/scan.d.ts.map +0 -1
  242. package/dist/rules/scan.js +0 -32
  243. package/dist/rules/scan.js.map +0 -1
  244. package/dist/rules/specs.d.ts +0 -29
  245. package/dist/rules/specs.d.ts.map +0 -1
  246. package/dist/rules/specs.js +0 -192
  247. package/dist/rules/specs.js.map +0 -1
  248. package/dist/rules/structure.d.ts +0 -13
  249. package/dist/rules/structure.d.ts.map +0 -1
  250. package/dist/rules/structure.js +0 -142
  251. package/dist/rules/structure.js.map +0 -1
  252. package/dist/rules/types.d.ts +0 -52
  253. package/dist/rules/types.d.ts.map +0 -1
  254. package/dist/rules/types.js +0 -2
  255. package/dist/rules/types.js.map +0 -1
  256. package/dist/rules/valid-describe-refs.d.ts +0 -7
  257. package/dist/rules/valid-describe-refs.d.ts.map +0 -1
  258. package/dist/rules/valid-describe-refs.js +0 -51
  259. package/dist/rules/valid-describe-refs.js.map +0 -1
  260. package/dist/rules/valid-detour-refs.d.ts +0 -6
  261. package/dist/rules/valid-detour-refs.d.ts.map +0 -1
  262. package/dist/rules/valid-detour-refs.js +0 -116
  263. package/dist/rules/valid-detour-refs.js.map +0 -1
  264. package/src/__tests__/cli.test.ts +0 -198
  265. package/src/__tests__/drift.test.ts +0 -74
  266. package/src/__tests__/formatters.test.ts +0 -157
  267. package/src/__tests__/implementation-returns-result.test.ts +0 -129
  268. package/src/__tests__/no-direct-implementation-call.test.ts +0 -83
  269. package/src/__tests__/no-sync-result-assumption.test.ts +0 -85
  270. package/src/__tests__/no-throw-in-detour-target.test.ts +0 -78
  271. package/src/__tests__/prefer-schema-inference.test.ts +0 -84
  272. package/src/__tests__/rules.test.ts +0 -227
  273. package/src/__tests__/valid-describe-refs.test.ts +0 -60
  274. package/src/rules/ast.ts +0 -213
  275. package/src/rules/no-direct-impl-in-route.ts +0 -81
  276. package/src/rules/no-throw-in-detour-target.ts +0 -150
  277. package/src/rules/valid-detour-refs.ts +0 -187
  278. package/tsconfig.json +0 -9
  279. package/tsconfig.tsbuildinfo +0 -1
@@ -1,150 +0,0 @@
1
- /**
2
- * Flags throws in implementations that are used as detour targets.
3
- *
4
- * Uses AST parsing for accurate detection of detour target IDs and
5
- * throw statements within those trail implementations.
6
- */
7
-
8
- import {
9
- findRunBodies,
10
- findTrailDefinitions,
11
- offsetToLine,
12
- parse,
13
- walk,
14
- } from './ast.js';
15
- import { isTestFile } from './scan.js';
16
- import type {
17
- ProjectAwareWardenRule,
18
- ProjectContext,
19
- WardenDiagnostic,
20
- } from './types.js';
21
-
22
- interface AstNode {
23
- readonly type: string;
24
- readonly start: number;
25
- readonly end: number;
26
- readonly [key: string]: unknown;
27
- }
28
-
29
- /** Collect all trail IDs referenced as detour targets in the AST. */
30
- const collectDetourTargets = (ast: AstNode): ReadonlySet<string> => {
31
- const targets = new Set<string>();
32
-
33
- walk(ast, (node) => {
34
- if (
35
- node.type !== 'Property' ||
36
- node.key?.name !== 'detours' ||
37
- !node.value
38
- ) {
39
- return;
40
- }
41
-
42
- walk(node.value as AstNode, (inner) => {
43
- if (inner.type === 'Literal' || inner.type === 'StringLiteral') {
44
- const { value } = inner as unknown as { value?: unknown };
45
- if (typeof value === 'string' && value.includes('.')) {
46
- targets.add(value);
47
- }
48
- }
49
- });
50
- });
51
-
52
- return targets;
53
- };
54
-
55
- /** Find throws in implementation bodies of targeted trails. */
56
- const findThrowsInTargetedTrails = (
57
- ast: AstNode,
58
- sourceCode: string,
59
- filePath: string,
60
- detourTargets: ReadonlySet<string>
61
- ): WardenDiagnostic[] => {
62
- const diagnostics: WardenDiagnostic[] = [];
63
-
64
- for (const def of findTrailDefinitions(ast)) {
65
- if (!detourTargets.has(def.id)) {
66
- continue;
67
- }
68
-
69
- for (const body of findRunBodies(def.config as AstNode)) {
70
- walk(body, (node) => {
71
- if (node.type === 'ThrowStatement') {
72
- diagnostics.push({
73
- filePath,
74
- line: offsetToLine(sourceCode, node.start),
75
- message: `Trail "${def.id}" is a detour target and must not throw. Use Result.err() instead.`,
76
- rule: 'no-throw-in-detour-target',
77
- severity: 'error',
78
- });
79
- }
80
- });
81
- }
82
- }
83
-
84
- return diagnostics;
85
- };
86
-
87
- const checkThrowInDetourTargets = (
88
- sourceCode: string,
89
- filePath: string,
90
- detourTargets: ReadonlySet<string>
91
- ): readonly WardenDiagnostic[] => {
92
- if (isTestFile(filePath)) {
93
- return [];
94
- }
95
-
96
- const ast = parse(filePath, sourceCode);
97
- if (!ast) {
98
- return [];
99
- }
100
-
101
- return findThrowsInTargetedTrails(
102
- ast as AstNode,
103
- sourceCode,
104
- filePath,
105
- detourTargets
106
- );
107
- };
108
-
109
- /**
110
- * Flags throws in implementations that are used as detour targets.
111
- */
112
- export const noThrowInDetourTarget: ProjectAwareWardenRule = {
113
- check(sourceCode: string, filePath: string): readonly WardenDiagnostic[] {
114
- const ast = parse(filePath, sourceCode);
115
- if (!ast) {
116
- return [];
117
- }
118
- return checkThrowInDetourTargets(
119
- sourceCode,
120
- filePath,
121
- collectDetourTargets(ast as AstNode)
122
- );
123
- },
124
- checkWithContext(
125
- sourceCode: string,
126
- filePath: string,
127
- context: ProjectContext
128
- ): readonly WardenDiagnostic[] {
129
- if (context.detourTargetTrailIds) {
130
- return checkThrowInDetourTargets(
131
- sourceCode,
132
- filePath,
133
- context.detourTargetTrailIds
134
- );
135
- }
136
- const ast = parse(filePath, sourceCode);
137
- if (!ast) {
138
- return [];
139
- }
140
- return checkThrowInDetourTargets(
141
- sourceCode,
142
- filePath,
143
- collectDetourTargets(ast as AstNode)
144
- );
145
- },
146
- description:
147
- 'Disallow throw statements inside implementations that are referenced as detour targets.',
148
- name: 'no-throw-in-detour-target',
149
- severity: 'error',
150
- };
@@ -1,187 +0,0 @@
1
- import { collectTrailIds } from './specs.js';
2
- import type {
3
- ProjectAwareWardenRule,
4
- ProjectContext,
5
- WardenDiagnostic,
6
- } from './types.js';
7
-
8
- interface BraceState {
9
- depth: number;
10
- found: boolean;
11
- }
12
-
13
- const trackBraces = (line: string, state: BraceState): void => {
14
- for (const ch of line) {
15
- if (ch === '{') {
16
- state.depth += 1;
17
- state.found = true;
18
- }
19
- if (ch === '}') {
20
- state.depth -= 1;
21
- }
22
- }
23
- };
24
-
25
- const collectArrayText = (lines: readonly string[], start: number): string => {
26
- let text = '';
27
- for (let k = start; k < lines.length && k < start + 20; k += 1) {
28
- const line = lines[k];
29
- if (!line) {
30
- continue;
31
- }
32
- text += `${line}\n`;
33
- if (text.includes(']')) {
34
- break;
35
- }
36
- }
37
- return text;
38
- };
39
-
40
- const findMissingDetourTargets = (
41
- text: string,
42
- knownIds: ReadonlySet<string>
43
- ): string[] => {
44
- const missing: string[] = [];
45
- for (const m of text.matchAll(/target\s*:\s*["'`]([^"'`]+)["'`]/g)) {
46
- const [, id] = m;
47
- if (id && !knownIds.has(id)) {
48
- missing.push(id);
49
- }
50
- }
51
- return missing;
52
- };
53
-
54
- const findMissingPlainDetours = (
55
- text: string,
56
- knownIds: ReadonlySet<string>
57
- ): string[] => {
58
- const missing: string[] = [];
59
- const cleaned = text.replaceAll(/target\s*:\s*["'`][^"'`]+["'`]/g, '');
60
- for (const m of cleaned.matchAll(/["'`]([^"'`]+)["'`]/g)) {
61
- const [, id] = m;
62
- if (id && id.includes('.') && !knownIds.has(id)) {
63
- missing.push(id);
64
- }
65
- }
66
- return missing;
67
- };
68
-
69
- const findAllMissingDetours = (
70
- text: string,
71
- knownIds: ReadonlySet<string>
72
- ): string[] => [
73
- ...findMissingDetourTargets(text, knownIds),
74
- ...findMissingPlainDetours(text, knownIds),
75
- ];
76
-
77
- const addMissingDetourDiagnostics = (
78
- specLine: string,
79
- j: number,
80
- lines: readonly string[],
81
- trailId: string,
82
- lineNum: number,
83
- filePath: string,
84
- knownIds: ReadonlySet<string>,
85
- diagnostics: WardenDiagnostic[]
86
- ): void => {
87
- if (!/\bdetours\s*:/.test(specLine)) {
88
- return;
89
- }
90
- for (const targetId of findAllMissingDetours(
91
- collectArrayText(lines, j),
92
- knownIds
93
- )) {
94
- diagnostics.push({
95
- filePath,
96
- line: lineNum,
97
- message: `Trail "${trailId}" has detour targeting "${targetId}" which is not defined.`,
98
- rule: 'valid-detour-refs',
99
- severity: 'error',
100
- });
101
- }
102
- };
103
-
104
- const scanTrailDetours = (
105
- lines: readonly string[],
106
- startIndex: number,
107
- trailId: string,
108
- filePath: string,
109
- knownIds: ReadonlySet<string>,
110
- diagnostics: WardenDiagnostic[]
111
- ): void => {
112
- const braceState: BraceState = { depth: 0, found: false };
113
- for (let j = startIndex; j < lines.length && j < startIndex + 200; j += 1) {
114
- const specLine = lines[j];
115
- if (!specLine) {
116
- continue;
117
- }
118
- trackBraces(specLine, braceState);
119
- addMissingDetourDiagnostics(
120
- specLine,
121
- j,
122
- lines,
123
- trailId,
124
- startIndex + 1,
125
- filePath,
126
- knownIds,
127
- diagnostics
128
- );
129
- if (braceState.found && braceState.depth <= 0) {
130
- break;
131
- }
132
- }
133
- };
134
-
135
- const processLine = (
136
- line: string,
137
- i: number,
138
- lines: readonly string[],
139
- filePath: string,
140
- knownIds: ReadonlySet<string>,
141
- diagnostics: WardenDiagnostic[]
142
- ): void => {
143
- const trailMatch = line.match(/\btrail\s*\(\s*["'`]([^"'`]+)["'`]/);
144
- if (!trailMatch) {
145
- return;
146
- }
147
- const [, trailId] = trailMatch;
148
- if (!trailId) {
149
- return;
150
- }
151
- scanTrailDetours(lines, i, trailId, filePath, knownIds, diagnostics);
152
- };
153
-
154
- const checkDetourRefs = (
155
- sourceCode: string,
156
- filePath: string,
157
- knownIds: ReadonlySet<string>
158
- ): readonly WardenDiagnostic[] => {
159
- const diagnostics: WardenDiagnostic[] = [];
160
- const lines = sourceCode.split('\n');
161
- for (let i = 0; i < lines.length; i += 1) {
162
- const line = lines[i];
163
- if (line) {
164
- processLine(line, i, lines, filePath, knownIds, diagnostics);
165
- }
166
- }
167
- return diagnostics;
168
- };
169
-
170
- /**
171
- * Checks that all trail IDs referenced in `detours` declarations exist.
172
- */
173
- export const validDetourRefs: ProjectAwareWardenRule = {
174
- check(sourceCode: string, filePath: string): readonly WardenDiagnostic[] {
175
- return checkDetourRefs(sourceCode, filePath, collectTrailIds(sourceCode));
176
- },
177
- checkWithContext(
178
- sourceCode: string,
179
- filePath: string,
180
- context: ProjectContext
181
- ): readonly WardenDiagnostic[] {
182
- return checkDetourRefs(sourceCode, filePath, context.knownTrailIds);
183
- },
184
- description: 'Ensure all detour target trail IDs reference defined trails.',
185
- name: 'valid-detour-refs',
186
- severity: 'error',
187
- };
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "rootDir": "src"
6
- },
7
- "include": ["src"],
8
- "exclude": ["**/__tests__/**", "**/*.test.ts", "dist"]
9
- }
@@ -1 +0,0 @@
1
- {"root":["./src/cli.ts","./src/drift.ts","./src/formatters.ts","./src/index.ts","./src/rules/ast.ts","./src/rules/context-no-surface-types.ts","./src/rules/implementation-returns-result.ts","./src/rules/index.ts","./src/rules/no-direct-impl-in-route.ts","./src/rules/no-direct-implementation-call.ts","./src/rules/no-sync-result-assumption.ts","./src/rules/no-throw-in-detour-target.ts","./src/rules/no-throw-in-implementation.ts","./src/rules/prefer-schema-inference.ts","./src/rules/scan.ts","./src/rules/specs.ts","./src/rules/structure.ts","./src/rules/types.ts","./src/rules/valid-describe-refs.ts","./src/rules/valid-detour-refs.ts"],"version":"5.9.3"}