@ontrails/warden 1.0.0-beta.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 (118) hide show
  1. package/.turbo/turbo-build.log +1 -0
  2. package/.turbo/turbo-lint.log +3 -0
  3. package/.turbo/turbo-typecheck.log +1 -0
  4. package/CHANGELOG.md +21 -0
  5. package/README.md +132 -0
  6. package/dist/cli.d.ts +46 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +221 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/drift.d.ts +26 -0
  11. package/dist/drift.d.ts.map +1 -0
  12. package/dist/drift.js +27 -0
  13. package/dist/drift.js.map +1 -0
  14. package/dist/formatters.d.ts +29 -0
  15. package/dist/formatters.d.ts.map +1 -0
  16. package/dist/formatters.js +87 -0
  17. package/dist/formatters.js.map +1 -0
  18. package/dist/index.d.ts +26 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +26 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/rules/ast.d.ts +41 -0
  23. package/dist/rules/ast.d.ts.map +1 -0
  24. package/dist/rules/ast.js +163 -0
  25. package/dist/rules/ast.js.map +1 -0
  26. package/dist/rules/context-no-surface-types.d.ts +12 -0
  27. package/dist/rules/context-no-surface-types.d.ts.map +1 -0
  28. package/dist/rules/context-no-surface-types.js +96 -0
  29. package/dist/rules/context-no-surface-types.js.map +1 -0
  30. package/dist/rules/implementation-returns-result.d.ts +13 -0
  31. package/dist/rules/implementation-returns-result.d.ts.map +1 -0
  32. package/dist/rules/implementation-returns-result.js +231 -0
  33. package/dist/rules/implementation-returns-result.js.map +1 -0
  34. package/dist/rules/index.d.ts +22 -0
  35. package/dist/rules/index.d.ts.map +1 -0
  36. package/dist/rules/index.js +41 -0
  37. package/dist/rules/index.js.map +1 -0
  38. package/dist/rules/no-direct-impl-in-route.d.ts +12 -0
  39. package/dist/rules/no-direct-impl-in-route.d.ts.map +1 -0
  40. package/dist/rules/no-direct-impl-in-route.js +46 -0
  41. package/dist/rules/no-direct-impl-in-route.js.map +1 -0
  42. package/dist/rules/no-direct-implementation-call.d.ts +12 -0
  43. package/dist/rules/no-direct-implementation-call.d.ts.map +1 -0
  44. package/dist/rules/no-direct-implementation-call.js +39 -0
  45. package/dist/rules/no-direct-implementation-call.js.map +1 -0
  46. package/dist/rules/no-sync-result-assumption.d.ts +6 -0
  47. package/dist/rules/no-sync-result-assumption.d.ts.map +1 -0
  48. package/dist/rules/no-sync-result-assumption.js +98 -0
  49. package/dist/rules/no-sync-result-assumption.js.map +1 -0
  50. package/dist/rules/no-throw-in-detour-target.d.ts +12 -0
  51. package/dist/rules/no-throw-in-detour-target.d.ts.map +1 -0
  52. package/dist/rules/no-throw-in-detour-target.js +87 -0
  53. package/dist/rules/no-throw-in-detour-target.js.map +1 -0
  54. package/dist/rules/no-throw-in-implementation.d.ts +9 -0
  55. package/dist/rules/no-throw-in-implementation.d.ts.map +1 -0
  56. package/dist/rules/no-throw-in-implementation.js +34 -0
  57. package/dist/rules/no-throw-in-implementation.js.map +1 -0
  58. package/dist/rules/prefer-schema-inference.d.ts +7 -0
  59. package/dist/rules/prefer-schema-inference.d.ts.map +1 -0
  60. package/dist/rules/prefer-schema-inference.js +86 -0
  61. package/dist/rules/prefer-schema-inference.js.map +1 -0
  62. package/dist/rules/scan.d.ts +8 -0
  63. package/dist/rules/scan.d.ts.map +1 -0
  64. package/dist/rules/scan.js +32 -0
  65. package/dist/rules/scan.js.map +1 -0
  66. package/dist/rules/specs.d.ts +29 -0
  67. package/dist/rules/specs.d.ts.map +1 -0
  68. package/dist/rules/specs.js +192 -0
  69. package/dist/rules/specs.js.map +1 -0
  70. package/dist/rules/structure.d.ts +13 -0
  71. package/dist/rules/structure.d.ts.map +1 -0
  72. package/dist/rules/structure.js +142 -0
  73. package/dist/rules/structure.js.map +1 -0
  74. package/dist/rules/types.d.ts +52 -0
  75. package/dist/rules/types.d.ts.map +1 -0
  76. package/dist/rules/types.js +2 -0
  77. package/dist/rules/types.js.map +1 -0
  78. package/dist/rules/valid-describe-refs.d.ts +7 -0
  79. package/dist/rules/valid-describe-refs.d.ts.map +1 -0
  80. package/dist/rules/valid-describe-refs.js +51 -0
  81. package/dist/rules/valid-describe-refs.js.map +1 -0
  82. package/dist/rules/valid-detour-refs.d.ts +6 -0
  83. package/dist/rules/valid-detour-refs.d.ts.map +1 -0
  84. package/dist/rules/valid-detour-refs.js +116 -0
  85. package/dist/rules/valid-detour-refs.js.map +1 -0
  86. package/package.json +25 -0
  87. package/src/__tests__/cli.test.ts +198 -0
  88. package/src/__tests__/drift.test.ts +74 -0
  89. package/src/__tests__/formatters.test.ts +157 -0
  90. package/src/__tests__/implementation-returns-result.test.ts +75 -0
  91. package/src/__tests__/no-direct-implementation-call.test.ts +83 -0
  92. package/src/__tests__/no-sync-result-assumption.test.ts +85 -0
  93. package/src/__tests__/no-throw-in-detour-target.test.ts +78 -0
  94. package/src/__tests__/prefer-schema-inference.test.ts +84 -0
  95. package/src/__tests__/rules.test.ts +188 -0
  96. package/src/__tests__/valid-describe-refs.test.ts +60 -0
  97. package/src/cli.ts +343 -0
  98. package/src/drift.ts +50 -0
  99. package/src/formatters.ts +113 -0
  100. package/src/index.ts +47 -0
  101. package/src/rules/ast.ts +217 -0
  102. package/src/rules/context-no-surface-types.ts +150 -0
  103. package/src/rules/implementation-returns-result.ts +343 -0
  104. package/src/rules/index.ts +54 -0
  105. package/src/rules/no-direct-impl-in-route.ts +77 -0
  106. package/src/rules/no-direct-implementation-call.ts +47 -0
  107. package/src/rules/no-sync-result-assumption.ts +156 -0
  108. package/src/rules/no-throw-in-detour-target.ts +150 -0
  109. package/src/rules/no-throw-in-implementation.ts +41 -0
  110. package/src/rules/prefer-schema-inference.ts +141 -0
  111. package/src/rules/scan.ts +46 -0
  112. package/src/rules/specs.ts +384 -0
  113. package/src/rules/structure.ts +234 -0
  114. package/src/rules/types.ts +62 -0
  115. package/src/rules/valid-describe-refs.ts +94 -0
  116. package/src/rules/valid-detour-refs.ts +187 -0
  117. package/tsconfig.json +9 -0
  118. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,29 @@
1
+ export interface ParsedEntry {
2
+ readonly line: number;
3
+ readonly start: number;
4
+ readonly text: string;
5
+ }
6
+ export interface ObjectProperty extends ParsedEntry {
7
+ readonly key: string;
8
+ readonly value: string;
9
+ }
10
+ export interface TrailLikeSpec {
11
+ readonly id: string;
12
+ readonly kind: 'hike' | 'trail';
13
+ readonly line: number;
14
+ readonly properties: ReadonlyMap<string, ObjectProperty>;
15
+ readonly specText: string;
16
+ readonly start: number;
17
+ }
18
+ export interface SchemaFieldInfo {
19
+ readonly derivedLabel: string;
20
+ readonly options?: readonly string[] | undefined;
21
+ readonly required: boolean;
22
+ }
23
+ export declare const parseStringLiteral: (text: string) => string | null;
24
+ export declare const parseArrayEntries: (arrayText: string, arrayStart: number, sourceCode: string) => readonly ParsedEntry[];
25
+ export declare const parseObjectProperties: (objectText: string, objectStart: number, sourceCode: string) => ReadonlyMap<string, ObjectProperty>;
26
+ export declare const findTrailLikeSpecs: (sourceCode: string) => readonly TrailLikeSpec[];
27
+ export declare const collectTrailIds: (sourceCode: string) => ReadonlySet<string>;
28
+ export declare const parseZodObjectShape: (schemaText: string) => ReadonlyMap<string, SchemaFieldInfo>;
29
+ //# sourceMappingURL=specs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specs.d.ts","sourceRoot":"","sources":["../../src/rules/specs.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAe,SAAQ,WAAW;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAuFD,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,MAAM,GAAG,IAc1D,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAC5B,WAAW,MAAM,EACjB,YAAY,MAAM,EAClB,YAAY,MAAM,KACjB,SAAS,WAAW,EActB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,YAAY,MAAM,EAClB,aAAa,MAAM,EACnB,YAAY,MAAM,KACjB,WAAW,CAAC,MAAM,EAAE,cAAc,CAcpC,CAAC;AA2KF,eAAO,MAAM,kBAAkB,GAC7B,YAAY,MAAM,KACjB,SAAS,aAAa,EAiBxB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,YAAY,MAAM,KAAG,WAAW,CAAC,MAAM,CACP,CAAC;AAEjE,eAAO,MAAM,mBAAmB,GAC9B,YAAY,MAAM,KACjB,WAAW,CAAC,MAAM,EAAE,eAAe,CAcrC,CAAC"}
@@ -0,0 +1,192 @@
1
+ import { captureBalanced, lineNumberAt, splitTopLevelEntriesWithOffsets, } from './structure.js';
2
+ const TRAIL_LIKE_PATTERN = /\b(trail|hike)\s*\(/g;
3
+ const PROPERTY_PATTERN = /^(?:readonly\s+)?(?:(["'`])([^"'`]+)\1|([A-Za-z_$][\w$]*))\s*:\s*([\s\S]+)$/;
4
+ const OPTIONALISH_PATTERN = /(?:^|[^\w])z\.(?:default|nullish|optional)\s*\(|\.(?:default|nullish|optional)\s*\(/;
5
+ const humanize = (str) => str
6
+ .replaceAll(/([a-z])([A-Z])/g, '$1 $2')
7
+ .replaceAll(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
8
+ .replace(/^./, (ch) => ch.toUpperCase());
9
+ const trimWrapped = (text, open, close) => {
10
+ const trimmed = text.trim();
11
+ if (!trimmed.startsWith(open) || !trimmed.endsWith(close)) {
12
+ return null;
13
+ }
14
+ return trimmed.slice(1, -1);
15
+ };
16
+ const firstEntry = (text) => {
17
+ const [entry] = splitTopLevelEntriesWithOffsets(text);
18
+ return entry ?? null;
19
+ };
20
+ const createParsedEntry = (sourceCode, start, text) => ({
21
+ line: lineNumberAt(sourceCode, start),
22
+ start,
23
+ text,
24
+ });
25
+ const createObjectProperty = (entry, key, value, objectStart, objectOffset, sourceCode) => {
26
+ const start = objectStart + objectOffset + 1 + entry.start;
27
+ return {
28
+ key,
29
+ line: lineNumberAt(sourceCode, start),
30
+ start,
31
+ text: entry.text,
32
+ value,
33
+ };
34
+ };
35
+ const parsePropertyEntry = (entry, objectStart, objectOffset, sourceCode) => {
36
+ const propertyMatch = entry.text.match(PROPERTY_PATTERN);
37
+ const key = propertyMatch?.[2] ?? propertyMatch?.[3];
38
+ const value = propertyMatch?.[4]?.trim();
39
+ if (!key || !value) {
40
+ return null;
41
+ }
42
+ return createObjectProperty(entry, key, value, objectStart, objectOffset, sourceCode);
43
+ };
44
+ const isDefined = (value) => value !== null;
45
+ export const parseStringLiteral = (text) => {
46
+ const trimmed = text.trim();
47
+ const [quote = ''] = trimmed;
48
+ const closer = quote === "'" || quote === '"' || quote === '`' ? quote : null;
49
+ if (closer === null || trimmed.at(-1) !== closer) {
50
+ return null;
51
+ }
52
+ const value = trimmed.slice(1, -1);
53
+ if (quote === '`' && value.includes('${')) {
54
+ return null;
55
+ }
56
+ return value;
57
+ };
58
+ export const parseArrayEntries = (arrayText, arrayStart, sourceCode) => {
59
+ const inner = trimWrapped(arrayText, '[', ']');
60
+ if (inner === null) {
61
+ return [];
62
+ }
63
+ const arrayOffset = arrayText.indexOf('[');
64
+ return splitTopLevelEntriesWithOffsets(inner).map((entry) => createParsedEntry(sourceCode, arrayStart + arrayOffset + 1 + entry.start, entry.text));
65
+ };
66
+ export const parseObjectProperties = (objectText, objectStart, sourceCode) => {
67
+ const inner = trimWrapped(objectText, '{', '}');
68
+ if (inner === null) {
69
+ return new Map();
70
+ }
71
+ const objectOffset = objectText.indexOf('{');
72
+ const properties = splitTopLevelEntriesWithOffsets(inner)
73
+ .map((entry) => parsePropertyEntry(entry, objectStart, objectOffset, sourceCode))
74
+ .filter(isDefined);
75
+ return new Map(properties.map((property) => [property.key, property]));
76
+ };
77
+ const resolveSpecTarget = (args) => {
78
+ const [firstArg, secondArg] = args;
79
+ if (!firstArg) {
80
+ return null;
81
+ }
82
+ const id = parseStringLiteral(firstArg.text);
83
+ return {
84
+ id,
85
+ specArg: id === null ? firstArg : (secondArg ?? firstArg),
86
+ };
87
+ };
88
+ const parseCallArguments = (sourceCode, callStart) => {
89
+ const openParen = sourceCode.indexOf('(', callStart);
90
+ const call = openParen === -1 ? null : captureBalanced(sourceCode, openParen);
91
+ if (call === null || openParen === -1) {
92
+ return null;
93
+ }
94
+ return {
95
+ argsStart: openParen + 1,
96
+ argsText: call.text.slice(1, -1),
97
+ };
98
+ };
99
+ const isSpecObject = (entry) => entry !== undefined && entry.text.trim().startsWith('{');
100
+ const resolveSpecId = (resolved, properties) => resolved.id ?? parseStringLiteral(properties.get('id')?.value ?? '');
101
+ const buildTrailLikeSpec = (sourceCode, kind, specArg, specStart, id, properties) => ({
102
+ id,
103
+ kind,
104
+ line: lineNumberAt(sourceCode, specStart),
105
+ properties,
106
+ specText: specArg.text,
107
+ start: specStart,
108
+ });
109
+ const parseResolvedSpec = (sourceCode, resolved, call) => {
110
+ const specStart = call.argsStart + resolved.specArg.start;
111
+ const properties = parseObjectProperties(resolved.specArg.text, specStart, sourceCode);
112
+ const id = resolveSpecId(resolved, properties);
113
+ return id === null ? null : { id, properties, specStart };
114
+ };
115
+ const resolveTrailLikeSpec = (sourceCode, callStart) => {
116
+ const call = parseCallArguments(sourceCode, callStart);
117
+ if (call === null) {
118
+ return null;
119
+ }
120
+ const resolved = resolveSpecTarget(splitTopLevelEntriesWithOffsets(call.argsText));
121
+ if (!resolved || !isSpecObject(resolved.specArg)) {
122
+ return null;
123
+ }
124
+ const parsed = parseResolvedSpec(sourceCode, resolved, call);
125
+ return parsed === null ? null : { parsed, resolved };
126
+ };
127
+ const parseTrailLikeMatch = (sourceCode, kind, callStart) => {
128
+ const resolved = resolveTrailLikeSpec(sourceCode, callStart);
129
+ if (resolved === null) {
130
+ return null;
131
+ }
132
+ return buildTrailLikeSpec(sourceCode, kind, resolved.resolved.specArg, resolved.parsed.specStart, resolved.parsed.id, resolved.parsed.properties);
133
+ };
134
+ const findCallArguments = (sourceText, pattern) => {
135
+ const index = pattern.exec(sourceText)?.index;
136
+ if (index === undefined) {
137
+ return null;
138
+ }
139
+ return parseCallArguments(sourceText, index)?.argsText ?? null;
140
+ };
141
+ const parseStringArrayLiteral = (arrayText) => {
142
+ const inner = trimWrapped(arrayText, '[', ']');
143
+ if (inner === null) {
144
+ return null;
145
+ }
146
+ const values = splitTopLevelEntriesWithOffsets(inner).map((entry) => parseStringLiteral(entry.text));
147
+ const strings = values.filter((value) => value !== null);
148
+ return strings.length === values.length ? strings : null;
149
+ };
150
+ const parseDescribeLabel = (fieldText) => {
151
+ const args = findCallArguments(fieldText, /\.describe\s*\(/);
152
+ return args === null ? undefined : (parseStringLiteral(args) ?? undefined);
153
+ };
154
+ const parseEnumValues = (fieldText) => {
155
+ const args = findCallArguments(fieldText, /\bz\.enum\s*\(/);
156
+ const entry = args === null ? null : firstEntry(args);
157
+ return entry ? (parseStringArrayLiteral(entry.text) ?? undefined) : undefined;
158
+ };
159
+ const toSchemaFieldInfo = (key, property) => ({
160
+ derivedLabel: parseDescribeLabel(property.value) ?? humanize(key),
161
+ options: parseEnumValues(property.value),
162
+ required: !OPTIONALISH_PATTERN.test(property.value),
163
+ });
164
+ export const findTrailLikeSpecs = (sourceCode) => {
165
+ const specs = [];
166
+ for (const match of sourceCode.matchAll(TRAIL_LIKE_PATTERN)) {
167
+ const callStart = match.index;
168
+ if (callStart === undefined) {
169
+ continue;
170
+ }
171
+ const kind = match[1] === 'hike' ? 'hike' : 'trail';
172
+ const spec = parseTrailLikeMatch(sourceCode, kind, callStart);
173
+ if (spec !== null) {
174
+ specs.push(spec);
175
+ }
176
+ }
177
+ return specs;
178
+ };
179
+ export const collectTrailIds = (sourceCode) => new Set(findTrailLikeSpecs(sourceCode).map((spec) => spec.id));
180
+ export const parseZodObjectShape = (schemaText) => {
181
+ const args = findCallArguments(schemaText, /\bz\.object\s*\(/);
182
+ const shapeEntry = args === null ? null : firstEntry(args);
183
+ if (!shapeEntry || !shapeEntry.text.trim().startsWith('{')) {
184
+ return new Map();
185
+ }
186
+ const shape = parseObjectProperties(shapeEntry.text, 0, shapeEntry.text);
187
+ return new Map([...shape.entries()].map(([key, property]) => [
188
+ key,
189
+ toSchemaFieldInfo(key, property),
190
+ ]));
191
+ };
192
+ //# sourceMappingURL=specs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"specs.js","sourceRoot":"","sources":["../../src/rules/specs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ interface BalancedSegment {
2
+ readonly end: number;
3
+ readonly text: string;
4
+ }
5
+ export interface SplitEntry {
6
+ readonly start: number;
7
+ readonly text: string;
8
+ }
9
+ export declare const captureBalanced: (sourceText: string, startIndex: number) => BalancedSegment | null;
10
+ export declare const lineNumberAt: (sourceText: string, startIndex: number) => number;
11
+ export declare const splitTopLevelEntriesWithOffsets: (sourceText: string) => SplitEntry[];
12
+ export {};
13
+ //# sourceMappingURL=structure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.d.ts","sourceRoot":"","sources":["../../src/rules/structure.ts"],"names":[],"mappings":"AAYA,UAAU,eAAe;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAmHD,eAAO,MAAM,eAAe,GAC1B,YAAY,MAAM,EAClB,YAAY,MAAM,KACjB,eAAe,GAAG,IAiBpB,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,YAAY,MAAM,EAAE,YAAY,MAAM,KAAG,MAClB,CAAC;AAuDrD,eAAO,MAAM,+BAA+B,GAC1C,YAAY,MAAM,KACjB,UAAU,EAkBZ,CAAC"}
@@ -0,0 +1,142 @@
1
+ const createState = () => ({
2
+ braceDepth: 0,
3
+ bracketDepth: 0,
4
+ escaped: false,
5
+ parenDepth: 0,
6
+ quoteMode: null,
7
+ });
8
+ const enterQuote = (ch) => {
9
+ if (ch === "'" || ch === '"' || ch === '`') {
10
+ return ch;
11
+ }
12
+ return null;
13
+ };
14
+ const clearEscape = (state) => {
15
+ if (!state.escaped) {
16
+ return false;
17
+ }
18
+ state.escaped = false;
19
+ return true;
20
+ };
21
+ const beginEscape = (state, ch) => {
22
+ if (ch !== '\\') {
23
+ return false;
24
+ }
25
+ state.escaped = true;
26
+ return true;
27
+ };
28
+ const closeQuote = (state, ch) => {
29
+ if (ch === state.quoteMode) {
30
+ state.quoteMode = null;
31
+ }
32
+ };
33
+ const updateQuotedState = (state, ch) => {
34
+ if (state.quoteMode === null) {
35
+ return false;
36
+ }
37
+ if (clearEscape(state)) {
38
+ return true;
39
+ }
40
+ if (beginEscape(state, ch)) {
41
+ return true;
42
+ }
43
+ closeQuote(state, ch);
44
+ return true;
45
+ };
46
+ const STRUCTURAL_DELTAS = {
47
+ '(': ['parenDepth', 1],
48
+ ')': ['parenDepth', -1],
49
+ '[': ['bracketDepth', 1],
50
+ ']': ['bracketDepth', -1],
51
+ '{': ['braceDepth', 1],
52
+ '}': ['braceDepth', -1],
53
+ };
54
+ const updateStructuralDepth = (state, ch) => {
55
+ if (!(ch in STRUCTURAL_DELTAS)) {
56
+ return;
57
+ }
58
+ const delta = STRUCTURAL_DELTAS[ch];
59
+ const [key, amount] = delta;
60
+ state[key] += amount;
61
+ };
62
+ const isTopLevel = (state) => state.braceDepth === 0 &&
63
+ state.bracketDepth === 0 &&
64
+ state.parenDepth === 0 &&
65
+ state.quoteMode === null;
66
+ const scanCharacter = (state, ch) => {
67
+ if (updateQuotedState(state, ch)) {
68
+ return;
69
+ }
70
+ const nextQuoteMode = enterQuote(ch);
71
+ if (nextQuoteMode !== null) {
72
+ state.quoteMode = nextQuoteMode;
73
+ return;
74
+ }
75
+ updateStructuralDepth(state, ch);
76
+ };
77
+ const isBalancedOpener = (ch) => ch === '{' || ch === '[' || ch === '(';
78
+ const appendBalancedCharacter = (sourceText, state, index, text) => {
79
+ const ch = sourceText[index];
80
+ if (!ch) {
81
+ return text;
82
+ }
83
+ scanCharacter(state, ch);
84
+ return `${text}${ch}`;
85
+ };
86
+ export const captureBalanced = (sourceText, startIndex) => {
87
+ if (!isBalancedOpener(sourceText[startIndex])) {
88
+ return null;
89
+ }
90
+ const state = createState();
91
+ let text = '';
92
+ for (let index = startIndex; index < sourceText.length; index += 1) {
93
+ text = appendBalancedCharacter(sourceText, state, index, text);
94
+ if (index > startIndex && isTopLevel(state)) {
95
+ return { end: index, text };
96
+ }
97
+ }
98
+ return null;
99
+ };
100
+ export const lineNumberAt = (sourceText, startIndex) => sourceText.slice(0, startIndex).split('\n').length;
101
+ const createSplitEntry = (sourceText, startIndex, endIndex) => {
102
+ const raw = sourceText.slice(startIndex, endIndex);
103
+ const firstContent = raw.search(/\S/);
104
+ if (firstContent === -1) {
105
+ return null;
106
+ }
107
+ const trailingWhitespace = raw.match(/\s*$/)?.[0].length ?? 0;
108
+ const trimmedEnd = raw.length - trailingWhitespace;
109
+ return {
110
+ start: startIndex + firstContent,
111
+ text: raw.slice(firstContent, trimmedEnd),
112
+ };
113
+ };
114
+ const pushSplitEntry = (entries, sourceText, startIndex, endIndex) => {
115
+ const entry = createSplitEntry(sourceText, startIndex, endIndex);
116
+ if (entry !== null) {
117
+ entries.push(entry);
118
+ }
119
+ };
120
+ const processSplitCharacter = (entries, sourceText, state, entryStart, index) => {
121
+ const ch = sourceText[index];
122
+ if (!ch) {
123
+ return entryStart;
124
+ }
125
+ if (ch === ',' && isTopLevel(state)) {
126
+ pushSplitEntry(entries, sourceText, entryStart, index);
127
+ return index + 1;
128
+ }
129
+ scanCharacter(state, ch);
130
+ return entryStart;
131
+ };
132
+ export const splitTopLevelEntriesWithOffsets = (sourceText) => {
133
+ const entries = [];
134
+ const state = createState();
135
+ let entryStart = 0;
136
+ for (let index = 0; index < sourceText.length; index += 1) {
137
+ entryStart = processSplitCharacter(entries, sourceText, state, entryStart, index);
138
+ }
139
+ pushSplitEntry(entries, sourceText, entryStart, sourceText.length);
140
+ return entries;
141
+ };
142
+ //# sourceMappingURL=structure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"structure.js","sourceRoot":"","sources":["../../src/rules/structure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Severity level for warden diagnostics.
3
+ */
4
+ export type WardenSeverity = 'error' | 'warn';
5
+ /**
6
+ * A single diagnostic reported by a warden rule.
7
+ */
8
+ export interface WardenDiagnostic {
9
+ /** Rule identifier, e.g. "no-throw-in-implementation" */
10
+ readonly rule: string;
11
+ /** Severity level */
12
+ readonly severity: WardenSeverity;
13
+ /** Human-readable message describing the violation */
14
+ readonly message: string;
15
+ /** 1-based line number where the violation was detected */
16
+ readonly line: number;
17
+ /** File path that was analyzed */
18
+ readonly filePath: string;
19
+ }
20
+ /**
21
+ * A warden rule is a function that analyzes source code and returns diagnostics.
22
+ *
23
+ * Rules use string/regex analysis (not full AST parsing) to detect patterns
24
+ * that violate Trails conventions.
25
+ */
26
+ export interface WardenRule {
27
+ /** Unique rule identifier */
28
+ readonly name: string;
29
+ /** Default severity */
30
+ readonly severity: WardenSeverity;
31
+ /** Human-readable description of what the rule enforces */
32
+ readonly description: string;
33
+ /** Run the rule against source code and return any diagnostics */
34
+ readonly check: (sourceCode: string, filePath: string) => readonly WardenDiagnostic[];
35
+ }
36
+ /**
37
+ * Options for cross-file rules that need knowledge of all trail IDs in a project.
38
+ */
39
+ export interface ProjectContext {
40
+ /** All known trail IDs in the project */
41
+ readonly knownTrailIds: ReadonlySet<string>;
42
+ /** All trail IDs referenced as detour targets across the project */
43
+ readonly detourTargetTrailIds?: ReadonlySet<string>;
44
+ }
45
+ /**
46
+ * A project-aware rule that requires knowledge of all trail IDs.
47
+ */
48
+ export interface ProjectAwareWardenRule extends WardenRule {
49
+ /** Run the rule with project-level context */
50
+ readonly checkWithContext: (sourceCode: string, filePath: string, context: ProjectContext) => readonly WardenDiagnostic[];
51
+ }
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/rules/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qBAAqB;IACrB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,sDAAsD;IACtD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uBAAuB;IACvB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,CACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,KACb,SAAS,gBAAgB,EAAE,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5C,oEAAoE;IACpE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACrD;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,UAAU;IACxD,8CAA8C;IAC9C,QAAQ,CAAC,gBAAgB,EAAE,CACzB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,cAAc,KACpB,SAAS,gBAAgB,EAAE,CAAC;CAClC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/rules/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,7 @@
1
+ import type { ProjectAwareWardenRule } from './types.js';
2
+ /**
3
+ * Warns when @see references inside Zod .describe() strings point at unknown
4
+ * trails.
5
+ */
6
+ export declare const validDescribeRefs: ProjectAwareWardenRule;
7
+ //# sourceMappingURL=valid-describe-refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valid-describe-refs.d.ts","sourceRoot":"","sources":["../../src/rules/valid-describe-refs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,YAAY,CAAC;AAsEpB;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,sBAe/B,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { isTestFile } from './scan.js';
2
+ import { collectTrailIds, parseStringLiteral } from './specs.js';
3
+ import { captureBalanced, lineNumberAt } from './structure.js';
4
+ const DESCRIBE_PATTERN = /\.describe\s*\(/g;
5
+ const SEE_PATTERN = /@see\s+([A-Za-z0-9_.-]+)/g;
6
+ const describeTextAt = (sourceCode, matchIndex) => {
7
+ const openParen = sourceCode.indexOf('(', matchIndex);
8
+ if (openParen === -1) {
9
+ return null;
10
+ }
11
+ return captureBalanced(sourceCode, openParen)?.text.slice(1, -1) ?? null;
12
+ };
13
+ const refsInDescription = (description, line) => [...description.matchAll(SEE_PATTERN)].flatMap((see) => see[1] ? [{ line, ref: see[1] }] : []);
14
+ const refsForDescribe = (sourceCode, matchIndex) => {
15
+ const args = describeTextAt(sourceCode, matchIndex);
16
+ const description = args ? parseStringLiteral(args) : null;
17
+ return description === null
18
+ ? []
19
+ : refsInDescription(description, lineNumberAt(sourceCode, matchIndex));
20
+ };
21
+ const collectDescribeRefs = (sourceCode) => [...sourceCode.matchAll(DESCRIBE_PATTERN)].flatMap((match) => match.index === undefined ? [] : refsForDescribe(sourceCode, match.index));
22
+ const checkDescribeRefs = (sourceCode, filePath, knownTrailIds) => {
23
+ if (isTestFile(filePath)) {
24
+ return [];
25
+ }
26
+ return collectDescribeRefs(sourceCode)
27
+ .filter(({ ref }) => !knownTrailIds.has(ref))
28
+ .map(({ line, ref }) => ({
29
+ filePath,
30
+ line,
31
+ message: `@see reference "${ref}" does not resolve to a defined trail.`,
32
+ rule: 'valid-describe-refs',
33
+ severity: 'warn',
34
+ }));
35
+ };
36
+ /**
37
+ * Warns when @see references inside Zod .describe() strings point at unknown
38
+ * trails.
39
+ */
40
+ export const validDescribeRefs = {
41
+ check(sourceCode, filePath) {
42
+ return checkDescribeRefs(sourceCode, filePath, collectTrailIds(sourceCode));
43
+ },
44
+ checkWithContext(sourceCode, filePath, context) {
45
+ return checkDescribeRefs(sourceCode, filePath, context.knownTrailIds);
46
+ },
47
+ description: 'Ensure @see tags inside schema .describe() strings reference defined trails.',
48
+ name: 'valid-describe-refs',
49
+ severity: 'warn',
50
+ };
51
+ //# sourceMappingURL=valid-describe-refs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valid-describe-refs.js","sourceRoot":"","sources":["../../src/rules/valid-describe-refs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { ProjectAwareWardenRule } from './types.js';
2
+ /**
3
+ * Checks that all trail IDs referenced in `detours` declarations exist.
4
+ */
5
+ export declare const validDetourRefs: ProjectAwareWardenRule;
6
+ //# sourceMappingURL=valid-detour-refs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"valid-detour-refs.d.ts","sourceRoot":"","sources":["../../src/rules/valid-detour-refs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,YAAY,CAAC;AAoKpB;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,sBAc7B,CAAC"}