@ontrails/warden 1.0.0-beta.2 → 1.0.0-beta.4
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/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +46 -0
- package/README.md +6 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -4
- package/dist/cli.js.map +1 -1
- package/dist/rules/ast.d.ts +6 -6
- package/dist/rules/ast.d.ts.map +1 -1
- package/dist/rules/ast.js +8 -10
- package/dist/rules/ast.js.map +1 -1
- package/dist/rules/context-no-surface-types.js +1 -1
- package/dist/rules/context-no-surface-types.js.map +1 -1
- package/dist/rules/implementation-returns-result.d.ts +1 -1
- package/dist/rules/implementation-returns-result.d.ts.map +1 -1
- package/dist/rules/implementation-returns-result.js +52 -6
- package/dist/rules/implementation-returns-result.js.map +1 -1
- package/dist/rules/index.d.ts +1 -8
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +1 -8
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/no-direct-impl-in-route.d.ts +4 -4
- package/dist/rules/no-direct-impl-in-route.d.ts.map +1 -1
- package/dist/rules/no-direct-impl-in-route.js +15 -14
- package/dist/rules/no-direct-impl-in-route.js.map +1 -1
- package/dist/rules/no-direct-implementation-call.d.ts +3 -3
- package/dist/rules/no-direct-implementation-call.js +7 -7
- package/dist/rules/no-direct-implementation-call.js.map +1 -1
- package/dist/rules/no-sync-result-assumption.d.ts +1 -1
- package/dist/rules/no-sync-result-assumption.js +5 -5
- package/dist/rules/no-sync-result-assumption.js.map +1 -1
- package/dist/rules/no-throw-in-detour-target.js +2 -2
- package/dist/rules/no-throw-in-detour-target.js.map +1 -1
- package/dist/rules/no-throw-in-implementation.d.ts +1 -1
- package/dist/rules/no-throw-in-implementation.js +3 -3
- package/dist/rules/no-throw-in-implementation.js.map +1 -1
- package/dist/rules/specs.d.ts +1 -1
- package/dist/rules/specs.d.ts.map +1 -1
- package/dist/rules/specs.js +2 -2
- package/dist/rules/specs.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/cli.test.ts +7 -7
- package/src/__tests__/drift.test.ts +1 -1
- package/src/__tests__/implementation-returns-result.test.ts +60 -6
- package/src/__tests__/no-direct-implementation-call.test.ts +8 -8
- package/src/__tests__/no-sync-result-assumption.test.ts +6 -6
- package/src/__tests__/no-throw-in-detour-target.test.ts +6 -6
- package/src/__tests__/prefer-schema-inference.test.ts +4 -4
- package/src/__tests__/rules.test.ts +59 -20
- package/src/__tests__/valid-describe-refs.test.ts +4 -4
- package/src/cli.ts +1 -4
- package/src/rules/ast.ts +10 -14
- package/src/rules/context-no-surface-types.ts +1 -1
- package/src/rules/implementation-returns-result.ts +63 -6
- package/src/rules/index.ts +1 -8
- package/src/rules/no-direct-impl-in-route.ts +20 -16
- package/src/rules/no-direct-implementation-call.ts +7 -7
- package/src/rules/no-sync-result-assumption.ts +5 -5
- package/src/rules/no-throw-in-detour-target.ts +2 -2
- package/src/rules/no-throw-in-implementation.ts +3 -3
- package/src/rules/specs.ts +5 -5
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Flags direct `.
|
|
2
|
+
* Flags direct `.run()` calls in application code.
|
|
3
3
|
*
|
|
4
|
-
* Uses AST parsing to find `.
|
|
4
|
+
* Uses AST parsing to find `.run()` call expressions,
|
|
5
5
|
* ignoring occurrences in strings and comments.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { isRunCall, offsetToLine, parse, walk } from './ast.js';
|
|
8
8
|
import { isFrameworkInternalFile, isTestFile } from './scan.js';
|
|
9
9
|
/**
|
|
10
|
-
* Flags direct `.
|
|
10
|
+
* Flags direct `.run()` calls in application code.
|
|
11
11
|
*/
|
|
12
12
|
export const noDirectImplementationCall = {
|
|
13
13
|
check(sourceCode, filePath) {
|
|
@@ -20,11 +20,11 @@ export const noDirectImplementationCall = {
|
|
|
20
20
|
}
|
|
21
21
|
const diagnostics = [];
|
|
22
22
|
walk(ast, (node) => {
|
|
23
|
-
if (
|
|
23
|
+
if (isRunCall(node)) {
|
|
24
24
|
diagnostics.push({
|
|
25
25
|
filePath,
|
|
26
26
|
line: offsetToLine(sourceCode, node.start),
|
|
27
|
-
message: 'Use ctx.follow("trailId", input) instead of direct .
|
|
27
|
+
message: 'Use ctx.follow("trailId", input) instead of direct .run() calls. Direct implementation access bypasses validation, tracing, and layers.',
|
|
28
28
|
rule: 'no-direct-implementation-call',
|
|
29
29
|
severity: 'warn',
|
|
30
30
|
});
|
|
@@ -32,7 +32,7 @@ export const noDirectImplementationCall = {
|
|
|
32
32
|
});
|
|
33
33
|
return diagnostics;
|
|
34
34
|
},
|
|
35
|
-
description: 'Disallow direct .
|
|
35
|
+
description: 'Disallow direct .run() calls in application code. Use ctx.follow() instead.',
|
|
36
36
|
name: 'no-direct-implementation-call',
|
|
37
37
|
severity: 'warn',
|
|
38
38
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-direct-implementation-call.js","sourceRoot":"","sources":["../../src/rules/no-direct-implementation-call.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"no-direct-implementation-call.js","sourceRoot":"","sources":["../../src/rules/no-direct-implementation-call.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGhE;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAe;IACpD,KAAK,CAAC,UAAkB,EAAE,QAAgB;QACxC,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,uBAAuB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC9D,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,WAAW,GAAuB,EAAE,CAAC;QAE3C,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;YACjB,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpB,WAAW,CAAC,IAAI,CAAC;oBACf,QAAQ;oBACR,IAAI,EAAE,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC;oBAC1C,OAAO,EACL,yIAAyI;oBAC3I,IAAI,EAAE,+BAA+B;oBACrC,QAAQ,EAAE,MAAM;iBACjB,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,WAAW,EACT,6EAA6E;IAC/E,IAAI,EAAE,+BAA+B;IACrC,QAAQ,EAAE,MAAM;CACjB,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { WardenRule } from './types.js';
|
|
2
2
|
/**
|
|
3
|
-
* Flags code that assumes `.
|
|
3
|
+
* Flags code that assumes `.run()` returns a synchronous result.
|
|
4
4
|
*/
|
|
5
5
|
export declare const noSyncResultAssumption: WardenRule;
|
|
6
6
|
//# sourceMappingURL=no-sync-result-assumption.d.ts.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isFrameworkInternalFile, isTestFile, stripQuotedContent, } from './scan.js';
|
|
2
2
|
const RESULT_ACCESS_PATTERN = /\.(?:isOk|isErr|match|map)\s*\(|\.(?:value|error)\b/;
|
|
3
|
-
const IMPLEMENTATION_CALL_PATTERN = /\.
|
|
3
|
+
const IMPLEMENTATION_CALL_PATTERN = /\.run\s*\(/;
|
|
4
4
|
const isAwaitedImplementationCall = (line) => {
|
|
5
|
-
const callIndex = line.indexOf('.
|
|
5
|
+
const callIndex = line.indexOf('.run(');
|
|
6
6
|
if (callIndex === -1) {
|
|
7
7
|
return false;
|
|
8
8
|
}
|
|
@@ -17,7 +17,7 @@ const isPendingUse = (line, variableName) => {
|
|
|
17
17
|
const pendingPattern = new RegExp(`\\b${escaped}\\s*(?:\\.(?:isOk|isErr|match|map)\\s*\\(|\\.(?:value|error)\\b)`);
|
|
18
18
|
return pendingPattern.test(line);
|
|
19
19
|
};
|
|
20
|
-
const MISSING_AWAIT_MESSAGE = 'Missing await: .
|
|
20
|
+
const MISSING_AWAIT_MESSAGE = 'Missing await: .run() returns Promise<Result> after normalization. Use `const result = await trail.run(input, ctx)`.';
|
|
21
21
|
const createMissingAwaitDiagnostic = (filePath, line) => ({
|
|
22
22
|
filePath,
|
|
23
23
|
line,
|
|
@@ -82,7 +82,7 @@ const scanSourceCode = (sourceCode, filePath) => {
|
|
|
82
82
|
return diagnostics;
|
|
83
83
|
};
|
|
84
84
|
/**
|
|
85
|
-
* Flags code that assumes `.
|
|
85
|
+
* Flags code that assumes `.run()` returns a synchronous result.
|
|
86
86
|
*/
|
|
87
87
|
export const noSyncResultAssumption = {
|
|
88
88
|
check(sourceCode, filePath) {
|
|
@@ -91,7 +91,7 @@ export const noSyncResultAssumption = {
|
|
|
91
91
|
}
|
|
92
92
|
return scanSourceCode(stripQuotedContent(sourceCode), filePath);
|
|
93
93
|
},
|
|
94
|
-
description: 'Disallow treating .
|
|
94
|
+
description: 'Disallow treating .run() as synchronous after normalization. Always await the returned Promise<Result>.',
|
|
95
95
|
name: 'no-sync-result-assumption',
|
|
96
96
|
severity: 'error',
|
|
97
97
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-sync-result-assumption.js","sourceRoot":"","sources":["../../src/rules/no-sync-result-assumption.ts"],"names":[],"mappings":"AACA,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,kBAAkB,GACnB,MAAM,WAAW,CAAC;AAEnB,MAAM,qBAAqB,GACzB,qDAAqD,CAAC;AACxD,MAAM,2BAA2B,GAAG,
|
|
1
|
+
{"version":3,"file":"no-sync-result-assumption.js","sourceRoot":"","sources":["../../src/rules/no-sync-result-assumption.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Uses AST parsing for accurate detection of detour target IDs and
|
|
5
5
|
* throw statements within those trail implementations.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { findRunBodies, findTrailDefinitions, offsetToLine, parse, walk, } from './ast.js';
|
|
8
8
|
import { isTestFile } from './scan.js';
|
|
9
9
|
/** Collect all trail IDs referenced as detour targets in the AST. */
|
|
10
10
|
const collectDetourTargets = (ast) => {
|
|
@@ -33,7 +33,7 @@ const findThrowsInTargetedTrails = (ast, sourceCode, filePath, detourTargets) =>
|
|
|
33
33
|
if (!detourTargets.has(def.id)) {
|
|
34
34
|
continue;
|
|
35
35
|
}
|
|
36
|
-
for (const body of
|
|
36
|
+
for (const body of findRunBodies(def.config)) {
|
|
37
37
|
walk(body, (node) => {
|
|
38
38
|
if (node.type === 'ThrowStatement') {
|
|
39
39
|
diagnostics.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-throw-in-detour-target.js","sourceRoot":"","sources":["../../src/rules/no-throw-in-detour-target.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"no-throw-in-detour-target.js","sourceRoot":"","sources":["../../src/rules/no-throw-in-detour-target.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Finds `throw` statements inside `
|
|
2
|
+
* Finds `throw` statements inside `run:` function bodies.
|
|
3
3
|
*
|
|
4
4
|
* Uses AST parsing for accurate detection — no false positives from
|
|
5
5
|
* throw in comments, strings, or nested non-implementation functions.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Finds `throw` statements inside `
|
|
2
|
+
* Finds `throw` statements inside `run:` function bodies.
|
|
3
3
|
*
|
|
4
4
|
* Uses AST parsing for accurate detection — no false positives from
|
|
5
5
|
* throw in comments, strings, or nested non-implementation functions.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { findRunBodies, offsetToLine, parse, walk } from './ast.js';
|
|
8
8
|
export const noThrowInImplementation = {
|
|
9
9
|
check(sourceCode, filePath) {
|
|
10
10
|
const ast = parse(filePath, sourceCode);
|
|
@@ -12,7 +12,7 @@ export const noThrowInImplementation = {
|
|
|
12
12
|
return [];
|
|
13
13
|
}
|
|
14
14
|
const diagnostics = [];
|
|
15
|
-
for (const body of
|
|
15
|
+
for (const body of findRunBodies(ast)) {
|
|
16
16
|
walk(body, (node) => {
|
|
17
17
|
if (node.type === 'ThrowStatement') {
|
|
18
18
|
diagnostics.push({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"no-throw-in-implementation.js","sourceRoot":"","sources":["../../src/rules/no-throw-in-implementation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"no-throw-in-implementation.js","sourceRoot":"","sources":["../../src/rules/no-throw-in-implementation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGpE,MAAM,CAAC,MAAM,uBAAuB,GAAe;IACjD,KAAK,CAAC,UAAkB,EAAE,QAAgB;QACxC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACxC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,WAAW,GAAuB,EAAE,CAAC;QAE3C,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;gBAClB,IAAI,IAAI,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;oBACnC,WAAW,CAAC,IAAI,CAAC;wBACf,QAAQ;wBACR,IAAI,EAAE,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC;wBAC1C,OAAO,EACL,+DAA+D;wBACjE,IAAI,EAAE,4BAA4B;wBAClC,QAAQ,EAAE,OAAO;qBAClB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,WAAW,EACT,+FAA+F;IACjG,IAAI,EAAE,4BAA4B;IAClC,QAAQ,EAAE,OAAO;CAClB,CAAC"}
|
package/dist/rules/specs.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface ObjectProperty extends ParsedEntry {
|
|
|
9
9
|
}
|
|
10
10
|
export interface TrailLikeSpec {
|
|
11
11
|
readonly id: string;
|
|
12
|
-
readonly kind: '
|
|
12
|
+
readonly kind: 'event' | 'trail';
|
|
13
13
|
readonly line: number;
|
|
14
14
|
readonly properties: ReadonlyMap<string, ObjectProperty>;
|
|
15
15
|
readonly specText: string;
|
|
@@ -1 +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,
|
|
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,OAAO,GAAG,OAAO,CAAC;IACjC,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"}
|
package/dist/rules/specs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { captureBalanced, lineNumberAt, splitTopLevelEntriesWithOffsets, } from './structure.js';
|
|
2
|
-
const TRAIL_LIKE_PATTERN = /\b(trail|
|
|
2
|
+
const TRAIL_LIKE_PATTERN = /\b(trail|event)\s*\(/g;
|
|
3
3
|
const PROPERTY_PATTERN = /^(?:readonly\s+)?(?:(["'`])([^"'`]+)\1|([A-Za-z_$][\w$]*))\s*:\s*([\s\S]+)$/;
|
|
4
4
|
const OPTIONALISH_PATTERN = /(?:^|[^\w])z\.(?:default|nullish|optional)\s*\(|\.(?:default|nullish|optional)\s*\(/;
|
|
5
5
|
const humanize = (str) => str
|
|
@@ -168,7 +168,7 @@ export const findTrailLikeSpecs = (sourceCode) => {
|
|
|
168
168
|
if (callStart === undefined) {
|
|
169
169
|
continue;
|
|
170
170
|
}
|
|
171
|
-
const kind = match[1] === '
|
|
171
|
+
const kind = match[1] === 'event' ? 'event' : 'trail';
|
|
172
172
|
const spec = parseTrailLikeMatch(sourceCode, kind, callStart);
|
|
173
173
|
if (spec !== null) {
|
|
174
174
|
specs.push(spec);
|
package/dist/rules/specs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specs.js","sourceRoot":"","sources":["../../src/rules/specs.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,+BAA+B,GAChC,MAAM,gBAAgB,CAAC;AA6BxB,MAAM,kBAAkB,GAAG,
|
|
1
|
+
{"version":3,"file":"specs.js","sourceRoot":"","sources":["../../src/rules/specs.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,+BAA+B,GAChC,MAAM,gBAAgB,CAAC;AA6BxB,MAAM,kBAAkB,GAAG,uBAAuB,CAAC;AAEnD,MAAM,gBAAgB,GACpB,6EAA6E,CAAC;AAEhF,MAAM,mBAAmB,GACvB,qFAAqF,CAAC;AAExF,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAU,EAAE,CACvC,GAAG;KACA,UAAU,CAAC,iBAAiB,EAAE,OAAO,CAAC;KACtC,UAAU,CAAC,uBAAuB,EAAE,OAAO,CAAC;KAC5C,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AAE7C,MAAM,WAAW,GAAG,CAClB,IAAY,EACZ,IAAe,EACf,KAAgB,EACD,EAAE;IACjB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9B,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,IAAY,EAAqB,EAAE;IACrD,MAAM,CAAC,KAAK,CAAC,GAAG,+BAA+B,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,KAAK,IAAI,IAAI,CAAC;AACvB,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CACxB,UAAkB,EAClB,KAAa,EACb,IAAY,EACC,EAAE,CAAC,CAAC;IACjB,IAAI,EAAE,YAAY,CAAC,UAAU,EAAE,KAAK,CAAC;IACrC,KAAK;IACL,IAAI;CACL,CAAC,CAAC;AAEH,MAAM,oBAAoB,GAAG,CAC3B,KAAiB,EACjB,GAAW,EACX,KAAa,EACb,WAAmB,EACnB,YAAoB,EACpB,UAAkB,EACF,EAAE;IAClB,MAAM,KAAK,GAAG,WAAW,GAAG,YAAY,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;IAC3D,OAAO;QACL,GAAG;QACH,IAAI,EAAE,YAAY,CAAC,UAAU,EAAE,KAAK,CAAC;QACrC,KAAK;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK;KACN,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CACzB,KAAiB,EACjB,WAAmB,EACnB,YAAoB,EACpB,UAAkB,EACK,EAAE;IACzB,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IACzC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,oBAAoB,CACzB,KAAK,EACL,GAAG,EACH,KAAK,EACL,WAAW,EACX,YAAY,EACZ,UAAU,CACX,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CAAI,KAAe,EAAc,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC;AAErE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAiB,EAAE;IAChE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC;IAC7B,MAAM,MAAM,GAAG,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9E,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,SAAiB,EACjB,UAAkB,EAClB,UAAkB,EACM,EAAE;IAC1B,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/C,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,+BAA+B,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC1D,iBAAiB,CACf,UAAU,EACV,UAAU,GAAG,WAAW,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,EAC1C,KAAK,CAAC,IAAI,CACX,CACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,UAAkB,EAClB,WAAmB,EACnB,UAAkB,EACmB,EAAE;IACvC,MAAM,KAAK,GAAG,WAAW,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAChD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,+BAA+B,CAAC,KAAK,CAAC;SACtD,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CACb,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,CAAC,CACjE;SACA,MAAM,CAAC,SAAS,CAAC,CAAC;IAErB,OAAO,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CACxB,IAA2B,EACwB,EAAE;IACrD,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC;IACnC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EAAE,GAAG,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO;QACL,EAAE;QACF,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC;KAC1D,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CACzB,UAAkB,EAClB,SAAiB,EAC+B,EAAE;IAClD,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC9E,IAAI,IAAI,KAAK,IAAI,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,SAAS,EAAE,SAAS,GAAG,CAAC;QACxB,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KACjC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,YAAY,GAAG,CAAC,KAA6B,EAAuB,EAAE,CAC1E,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAE3D,MAAM,aAAa,GAAG,CACpB,QAAoD,EACpD,UAA+C,EAChC,EAAE,CACjB,QAAQ,CAAC,EAAE,IAAI,kBAAkB,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;AAEvE,MAAM,kBAAkB,GAAG,CACzB,UAAkB,EAClB,IAAuB,EACvB,OAAmB,EACnB,SAAiB,EACjB,EAAU,EACV,UAA+C,EAChC,EAAE,CAAC,CAAC;IACnB,EAAE;IACF,IAAI;IACJ,IAAI,EAAE,YAAY,CAAC,UAAU,EAAE,SAAS,CAAC;IACzC,UAAU;IACV,QAAQ,EAAE,OAAO,CAAC,IAAI;IACtB,KAAK,EAAE,SAAS;CACjB,CAAC,CAAC;AAEH,MAAM,iBAAiB,GAAG,CACxB,UAAkB,EAClB,QAAoD,EACpD,IAA6C,EAKtC,EAAE;IACT,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC;IAC1D,MAAM,UAAU,GAAG,qBAAqB,CACtC,QAAQ,CAAC,OAAO,CAAC,IAAI,EACrB,SAAS,EACT,UAAU,CACX,CAAC;IACF,MAAM,EAAE,GAAG,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IAC/C,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AAC5D,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAC3B,UAAkB,EAClB,SAAiB,EAQV,EAAE;IACT,MAAM,IAAI,GAAG,kBAAkB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IACvD,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,iBAAiB,CAChC,+BAA+B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAC/C,CAAC;IACF,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,UAAU,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC7D,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AACvD,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAC1B,UAAkB,EAClB,IAAuB,EACvB,SAAiB,EACK,EAAE;IACxB,MAAM,QAAQ,GAAG,oBAAoB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC7D,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,kBAAkB,CACvB,UAAU,EACV,IAAI,EACJ,QAAQ,CAAC,QAAQ,CAAC,OAAO,EACzB,QAAQ,CAAC,MAAM,CAAC,SAAS,EACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,EAClB,QAAQ,CAAC,MAAM,CAAC,UAAU,CAC3B,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CACxB,UAAkB,EAClB,OAAe,EACA,EAAE;IACjB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC;IAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,kBAAkB,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,QAAQ,IAAI,IAAI,CAAC;AACjE,CAAC,CAAC;AAEF,MAAM,uBAAuB,GAAG,CAC9B,SAAiB,EACS,EAAE;IAC5B,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/C,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,+BAA+B,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAClE,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAC/B,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IAC1E,OAAO,OAAO,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,SAAiB,EAAsB,EAAE;IACnE,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAC7D,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,SAAiB,EAAiC,EAAE;IAC3E,MAAM,IAAI,GAAG,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,uBAAuB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAChF,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CACxB,GAAW,EACX,QAAwB,EACP,EAAE,CAAC,CAAC;IACrB,YAAY,EAAE,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC;IACjE,OAAO,EAAE,eAAe,CAAC,QAAQ,CAAC,KAAK,CAAC;IACxC,QAAQ,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;CACpD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,UAAkB,EACQ,EAAE;IAC5B,MAAM,KAAK,GAAoB,EAAE,CAAC;IAElC,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC5D,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC;QAC9B,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,SAAS;QACX,CAAC;QAED,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QACtD,MAAM,IAAI,GAAG,mBAAmB,CAAC,UAAU,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAC9D,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,UAAkB,EAAuB,EAAE,CACzE,IAAI,GAAG,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AAEjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,UAAkB,EACoB,EAAE;IACxC,MAAM,IAAI,GAAG,iBAAiB,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IAC/D,MAAM,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC3D,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC3D,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;IAED,MAAM,KAAK,GAAG,qBAAqB,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACzE,OAAO,IAAI,GAAG,CACZ,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC;QAC5C,GAAG;QACH,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC;KACjC,CAAC,CACH,CAAC;AACJ,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -21,7 +21,7 @@ describe('runWarden', () => {
|
|
|
21
21
|
writeFileSync(
|
|
22
22
|
join(dir, 'bad.ts'),
|
|
23
23
|
`trail("entity.show", {
|
|
24
|
-
|
|
24
|
+
run: async (input, ctx) => {
|
|
25
25
|
throw new Error("boom");
|
|
26
26
|
}
|
|
27
27
|
})`
|
|
@@ -41,7 +41,7 @@ describe('runWarden', () => {
|
|
|
41
41
|
writeFileSync(
|
|
42
42
|
join(dir, 'good.ts'),
|
|
43
43
|
`trail("entity.show", {
|
|
44
|
-
|
|
44
|
+
run: async (input, ctx) => {
|
|
45
45
|
return Result.ok(data);
|
|
46
46
|
}
|
|
47
47
|
})`
|
|
@@ -72,7 +72,7 @@ describe('runWarden', () => {
|
|
|
72
72
|
// Even with bad code, driftOnly should produce 0 diagnostics
|
|
73
73
|
writeFileSync(
|
|
74
74
|
join(dir, 'bad.ts'),
|
|
75
|
-
`trail("x", {
|
|
75
|
+
`trail("x", { run: async () => { throw new Error("x"); } })`
|
|
76
76
|
);
|
|
77
77
|
const report = await runWarden({ driftOnly: true, rootDir: dir });
|
|
78
78
|
expect(report.diagnostics.length).toBe(0);
|
|
@@ -89,7 +89,7 @@ describe('runWarden', () => {
|
|
|
89
89
|
join(dir, 'show.ts'),
|
|
90
90
|
`trail("entity.show", {
|
|
91
91
|
detours: { NotFoundError: ["entity.search"] },
|
|
92
|
-
|
|
92
|
+
run: async (input, ctx) => {
|
|
93
93
|
return Result.ok(data);
|
|
94
94
|
}
|
|
95
95
|
})`
|
|
@@ -97,7 +97,7 @@ describe('runWarden', () => {
|
|
|
97
97
|
writeFileSync(
|
|
98
98
|
join(dir, 'search.ts'),
|
|
99
99
|
`trail("entity.search", {
|
|
100
|
-
|
|
100
|
+
run: async (input, ctx) => {
|
|
101
101
|
return Result.ok(data);
|
|
102
102
|
}
|
|
103
103
|
})`
|
|
@@ -121,7 +121,7 @@ describe('runWarden', () => {
|
|
|
121
121
|
join(dir, 'show.ts'),
|
|
122
122
|
`trail("entity.show", {
|
|
123
123
|
detours: { NotFoundError: ["entity.search"] },
|
|
124
|
-
|
|
124
|
+
run: async (input, ctx) => {
|
|
125
125
|
return Result.ok(data);
|
|
126
126
|
}
|
|
127
127
|
})`
|
|
@@ -129,7 +129,7 @@ describe('runWarden', () => {
|
|
|
129
129
|
writeFileSync(
|
|
130
130
|
join(dir, 'search.ts'),
|
|
131
131
|
`trail("entity.search", {
|
|
132
|
-
|
|
132
|
+
run: async (input, ctx) => {
|
|
133
133
|
throw new Error("boom");
|
|
134
134
|
}
|
|
135
135
|
})`
|
|
@@ -11,9 +11,9 @@ import { checkDrift } from '../drift.js';
|
|
|
11
11
|
|
|
12
12
|
const makeTopo = () => {
|
|
13
13
|
const t = trail('test.hello', {
|
|
14
|
-
implementation: () => Result.ok({ greeting: 'hi' }),
|
|
15
14
|
input: z.object({ name: z.string() }),
|
|
16
15
|
output: z.object({ greeting: z.string() }),
|
|
16
|
+
run: () => Result.ok({ greeting: 'hi' }),
|
|
17
17
|
});
|
|
18
18
|
return topo('test-app', { t });
|
|
19
19
|
};
|
|
@@ -8,7 +8,7 @@ describe('implementation-returns-result', () => {
|
|
|
8
8
|
test('flags raw object return in trail implementation', () => {
|
|
9
9
|
const code = `
|
|
10
10
|
trail("entity.show", {
|
|
11
|
-
|
|
11
|
+
run: async (input, ctx) => {
|
|
12
12
|
return { name: "foo" };
|
|
13
13
|
}
|
|
14
14
|
})`;
|
|
@@ -22,15 +22,16 @@ trail("entity.show", {
|
|
|
22
22
|
|
|
23
23
|
test('allows Result.ok() and returning ctx.follow() results', () => {
|
|
24
24
|
const code = `
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
trail("entity.onboard", {
|
|
26
|
+
follow: ["entity.create"],
|
|
27
|
+
run: async (input, ctx) => {
|
|
27
28
|
const result = await ctx.follow("entity.create", input);
|
|
28
29
|
return result;
|
|
29
30
|
}
|
|
30
31
|
})
|
|
31
32
|
|
|
32
33
|
trail("entity.create", {
|
|
33
|
-
|
|
34
|
+
run: async (input, ctx) => Result.ok({ id: "123" })
|
|
34
35
|
})`;
|
|
35
36
|
|
|
36
37
|
const diagnostics = implementationReturnsResult.check(code, TEST_FILE);
|
|
@@ -41,7 +42,7 @@ trail("entity.create", {
|
|
|
41
42
|
test('flags concise raw implementation bodies', () => {
|
|
42
43
|
const code = `
|
|
43
44
|
trail("entity.create", {
|
|
44
|
-
|
|
45
|
+
run: async (input, ctx) => ({ id: "123" })
|
|
45
46
|
})`;
|
|
46
47
|
|
|
47
48
|
const diagnostics = implementationReturnsResult.check(code, TEST_FILE);
|
|
@@ -50,6 +51,59 @@ trail("entity.create", {
|
|
|
50
51
|
expect(diagnostics[0]?.message).toContain('entity.create');
|
|
51
52
|
});
|
|
52
53
|
|
|
54
|
+
test('ignores return statements inside nested callbacks like .map()', () => {
|
|
55
|
+
const code = `
|
|
56
|
+
trail("entity.list", {
|
|
57
|
+
run: async (input, ctx) => {
|
|
58
|
+
const items = ["a", "b", "c"];
|
|
59
|
+
const mapped = items.map((item) => {
|
|
60
|
+
return { name: item };
|
|
61
|
+
});
|
|
62
|
+
const filtered = items.filter((item) => {
|
|
63
|
+
return item !== "b";
|
|
64
|
+
});
|
|
65
|
+
return Result.ok(mapped);
|
|
66
|
+
}
|
|
67
|
+
})`;
|
|
68
|
+
|
|
69
|
+
const diagnostics = implementationReturnsResult.check(code, TEST_FILE);
|
|
70
|
+
|
|
71
|
+
expect(diagnostics.length).toBe(0);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test('ignores return statements inside .then() callbacks', () => {
|
|
75
|
+
const code = `
|
|
76
|
+
trail("entity.fetch", {
|
|
77
|
+
run: async (input, ctx) => {
|
|
78
|
+
const data = await somePromise.then((res) => {
|
|
79
|
+
return res.json();
|
|
80
|
+
});
|
|
81
|
+
return Result.ok(data);
|
|
82
|
+
}
|
|
83
|
+
})`;
|
|
84
|
+
|
|
85
|
+
const diagnostics = implementationReturnsResult.check(code, TEST_FILE);
|
|
86
|
+
|
|
87
|
+
expect(diagnostics.length).toBe(0);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('still flags raw returns at the implementation level', () => {
|
|
91
|
+
const code = `
|
|
92
|
+
trail("entity.list", {
|
|
93
|
+
run: async (input, ctx) => {
|
|
94
|
+
const items = ["a", "b"].map((item) => {
|
|
95
|
+
return { name: item };
|
|
96
|
+
});
|
|
97
|
+
return items;
|
|
98
|
+
}
|
|
99
|
+
})`;
|
|
100
|
+
|
|
101
|
+
const diagnostics = implementationReturnsResult.check(code, TEST_FILE);
|
|
102
|
+
|
|
103
|
+
expect(diagnostics.length).toBe(1);
|
|
104
|
+
expect(diagnostics[0]?.message).toContain('entity.list');
|
|
105
|
+
});
|
|
106
|
+
|
|
53
107
|
test('allows returning explicitly Result-typed local helpers', () => {
|
|
54
108
|
const code = `
|
|
55
109
|
const buildDetail = (trailId: string): Result<object, Error> =>
|
|
@@ -59,7 +113,7 @@ const buildDiff = async (): Promise<Result<object, Error>> =>
|
|
|
59
113
|
Result.ok({ breaking: [] });
|
|
60
114
|
|
|
61
115
|
trail("survey", {
|
|
62
|
-
|
|
116
|
+
run: async (input, ctx) => {
|
|
63
117
|
if (input.diff) {
|
|
64
118
|
return await buildDiff();
|
|
65
119
|
}
|
|
@@ -8,11 +8,11 @@ describe('no-direct-implementation-call', () => {
|
|
|
8
8
|
import { trail, Result } from "@ontrails/core";
|
|
9
9
|
|
|
10
10
|
const entityShow = trail("entity.show", {
|
|
11
|
-
|
|
11
|
+
run: async (input, ctx) => Result.ok({ id: input.id }),
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
async function run() {
|
|
15
|
-
const result = await entityShow.
|
|
15
|
+
const result = await entityShow.run({ id: "1" }, ctx);
|
|
16
16
|
return result;
|
|
17
17
|
}`;
|
|
18
18
|
|
|
@@ -26,9 +26,9 @@ async function run() {
|
|
|
26
26
|
|
|
27
27
|
test('allows ctx.follow() calls', () => {
|
|
28
28
|
const code = `
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
trail("entity.onboard", {
|
|
30
|
+
follow: ["entity.create"],
|
|
31
|
+
run: async (input, ctx) => {
|
|
32
32
|
const result = await ctx.follow("entity.create", input);
|
|
33
33
|
return Result.ok(result);
|
|
34
34
|
},
|
|
@@ -43,7 +43,7 @@ hike("entity.onboard", {
|
|
|
43
43
|
test('ignores test files', () => {
|
|
44
44
|
const code = `
|
|
45
45
|
async function run() {
|
|
46
|
-
return await entityShow.
|
|
46
|
+
return await entityShow.run({ id: "1" }, ctx);
|
|
47
47
|
}`;
|
|
48
48
|
|
|
49
49
|
const diagnostics = noDirectImplementationCall.check(
|
|
@@ -57,7 +57,7 @@ async function run() {
|
|
|
57
57
|
test('ignores framework internals that intentionally call implementations', () => {
|
|
58
58
|
const code = `
|
|
59
59
|
export async function run() {
|
|
60
|
-
return await entityShow.
|
|
60
|
+
return await entityShow.run({ id: "1" }, ctx);
|
|
61
61
|
}`;
|
|
62
62
|
|
|
63
63
|
const diagnostics = noDirectImplementationCall.check(
|
|
@@ -70,7 +70,7 @@ export async function run() {
|
|
|
70
70
|
|
|
71
71
|
test('ignores implementation references inside template strings', () => {
|
|
72
72
|
const code = `
|
|
73
|
-
const generated = \`const result = await entityShow.
|
|
73
|
+
const generated = \`const result = await entityShow.run({ id: "1" }, ctx);\`;
|
|
74
74
|
`;
|
|
75
75
|
|
|
76
76
|
const diagnostics = noDirectImplementationCall.check(
|
|
@@ -6,7 +6,7 @@ describe('no-sync-result-assumption', () => {
|
|
|
6
6
|
test('flags direct result access on implementation calls', () => {
|
|
7
7
|
const code = `
|
|
8
8
|
async function run() {
|
|
9
|
-
const isOk = entityShow.
|
|
9
|
+
const isOk = entityShow.run({ id: "1" }, ctx).isOk();
|
|
10
10
|
return isOk;
|
|
11
11
|
}`;
|
|
12
12
|
|
|
@@ -20,7 +20,7 @@ async function run() {
|
|
|
20
20
|
|
|
21
21
|
test('flags a stored implementation result that is used synchronously', () => {
|
|
22
22
|
const code = `
|
|
23
|
-
const result = entityShow.
|
|
23
|
+
const result = entityShow.run({ id: "1" }, ctx);
|
|
24
24
|
|
|
25
25
|
if (result.isOk()) {
|
|
26
26
|
console.log("ok");
|
|
@@ -35,7 +35,7 @@ if (result.isOk()) {
|
|
|
35
35
|
test('allows awaited implementation calls before result access', () => {
|
|
36
36
|
const code = `
|
|
37
37
|
async function run() {
|
|
38
|
-
const result = await entityShow.
|
|
38
|
+
const result = await entityShow.run({ id: "1" }, ctx);
|
|
39
39
|
return result.isOk();
|
|
40
40
|
}`;
|
|
41
41
|
|
|
@@ -47,7 +47,7 @@ async function run() {
|
|
|
47
47
|
test('allows awaited implementation calls when the property access is chained', () => {
|
|
48
48
|
const code = `
|
|
49
49
|
async function run() {
|
|
50
|
-
return (await entityShow.
|
|
50
|
+
return (await entityShow.run({ id: "1" }, ctx)).isOk();
|
|
51
51
|
}`;
|
|
52
52
|
|
|
53
53
|
const diagnostics = noSyncResultAssumption.check(code, 'src/app.ts');
|
|
@@ -57,7 +57,7 @@ async function run() {
|
|
|
57
57
|
|
|
58
58
|
test('ignores test files', () => {
|
|
59
59
|
const code = `
|
|
60
|
-
const result = entityShow.
|
|
60
|
+
const result = entityShow.run({ id: "1" }, ctx);
|
|
61
61
|
result.isOk();
|
|
62
62
|
`;
|
|
63
63
|
|
|
@@ -71,7 +71,7 @@ result.isOk();
|
|
|
71
71
|
|
|
72
72
|
test('ignores framework internals that intentionally call implementations', () => {
|
|
73
73
|
const code = `
|
|
74
|
-
const result = entityShow.
|
|
74
|
+
const result = entityShow.run({ id: "1" }, ctx);
|
|
75
75
|
result.isOk();
|
|
76
76
|
`;
|
|
77
77
|
|
|
@@ -9,11 +9,11 @@ describe('no-throw-in-detour-target', () => {
|
|
|
9
9
|
const code = `
|
|
10
10
|
trail("entity.show", {
|
|
11
11
|
detours: { NotFoundError: ["entity.fallback"] },
|
|
12
|
-
|
|
12
|
+
run: async (input, ctx) => Result.ok({ id: "123" })
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
trail("entity.fallback", {
|
|
16
|
-
|
|
16
|
+
run: async (input, ctx) => {
|
|
17
17
|
throw new Error("boom");
|
|
18
18
|
}
|
|
19
19
|
})`;
|
|
@@ -28,7 +28,7 @@ trail("entity.fallback", {
|
|
|
28
28
|
test('allows throw in implementations that are not detour targets', () => {
|
|
29
29
|
const code = `
|
|
30
30
|
trail("entity.show", {
|
|
31
|
-
|
|
31
|
+
run: async (input, ctx) => {
|
|
32
32
|
throw new Error("boom");
|
|
33
33
|
}
|
|
34
34
|
})`;
|
|
@@ -42,11 +42,11 @@ trail("entity.show", {
|
|
|
42
42
|
const code = `
|
|
43
43
|
trail("entity.show", {
|
|
44
44
|
detours: { NotFoundError: ["entity.fallback"] },
|
|
45
|
-
|
|
45
|
+
run: async (input, ctx) => Result.ok({ id: "123" })
|
|
46
46
|
})
|
|
47
47
|
|
|
48
48
|
trail("entity.fallback", {
|
|
49
|
-
|
|
49
|
+
run: async (input, ctx) => { throw new Error("boom"); }
|
|
50
50
|
})`;
|
|
51
51
|
|
|
52
52
|
const diagnostics = noThrowInDetourTarget.check(code, TEST_FILE);
|
|
@@ -58,7 +58,7 @@ trail("entity.fallback", {
|
|
|
58
58
|
test('uses project context when the detour target is defined in another file', () => {
|
|
59
59
|
const code = `
|
|
60
60
|
trail("entity.fallback", {
|
|
61
|
-
|
|
61
|
+
run: async (input, ctx) => {
|
|
62
62
|
throw new Error("boom");
|
|
63
63
|
}
|
|
64
64
|
})`;
|