@ontrails/testing 1.0.0-beta.13 → 1.0.0-beta.15

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 (83) hide show
  1. package/.turbo/turbo-lint.log +1 -1
  2. package/CHANGELOG.md +28 -0
  3. package/README.md +11 -11
  4. package/dist/all.d.ts +10 -5
  5. package/dist/all.d.ts.map +1 -1
  6. package/dist/all.js +78 -26
  7. package/dist/all.js.map +1 -1
  8. package/dist/assertions.d.ts +23 -0
  9. package/dist/assertions.d.ts.map +1 -1
  10. package/dist/assertions.js +154 -0
  11. package/dist/assertions.js.map +1 -1
  12. package/dist/context.d.ts +17 -16
  13. package/dist/context.d.ts.map +1 -1
  14. package/dist/context.js +31 -20
  15. package/dist/context.js.map +1 -1
  16. package/dist/contracts.d.ts.map +1 -1
  17. package/dist/contracts.js +9 -5
  18. package/dist/contracts.js.map +1 -1
  19. package/dist/crosses.d.ts +4 -4
  20. package/dist/crosses.d.ts.map +1 -1
  21. package/dist/crosses.js +49 -39
  22. package/dist/crosses.js.map +1 -1
  23. package/dist/detours.d.ts +5 -4
  24. package/dist/detours.d.ts.map +1 -1
  25. package/dist/detours.js +93 -14
  26. package/dist/detours.js.map +1 -1
  27. package/dist/effective-examples.d.ts +30 -0
  28. package/dist/effective-examples.d.ts.map +1 -0
  29. package/dist/effective-examples.js +227 -0
  30. package/dist/effective-examples.js.map +1 -0
  31. package/dist/examples.d.ts +1 -1
  32. package/dist/examples.d.ts.map +1 -1
  33. package/dist/examples.js +79 -41
  34. package/dist/examples.js.map +1 -1
  35. package/dist/harness-cli.d.ts +3 -3
  36. package/dist/harness-cli.d.ts.map +1 -1
  37. package/dist/harness-cli.js +25 -33
  38. package/dist/harness-cli.js.map +1 -1
  39. package/dist/harness-mcp.d.ts +3 -3
  40. package/dist/harness-mcp.d.ts.map +1 -1
  41. package/dist/harness-mcp.js +9 -8
  42. package/dist/harness-mcp.js.map +1 -1
  43. package/dist/index.d.ts +6 -4
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +5 -2
  46. package/dist/index.js.map +1 -1
  47. package/dist/scenario.d.ts +37 -0
  48. package/dist/scenario.d.ts.map +1 -0
  49. package/dist/scenario.js +235 -0
  50. package/dist/scenario.js.map +1 -0
  51. package/dist/types.d.ts +38 -5
  52. package/dist/types.d.ts.map +1 -1
  53. package/package.json +9 -5
  54. package/src/__tests__/all.test.ts +217 -29
  55. package/src/__tests__/context.test.ts +32 -12
  56. package/src/__tests__/contracts.test.ts +72 -18
  57. package/src/__tests__/crosses.test.ts +78 -78
  58. package/src/__tests__/detours.test.ts +176 -19
  59. package/src/__tests__/effective-examples.test.ts +203 -0
  60. package/src/__tests__/examples.test.ts +152 -50
  61. package/src/__tests__/harness-cli.test.ts +90 -0
  62. package/src/__tests__/harness-mcp.test.ts +37 -0
  63. package/src/__tests__/partial-match.test.ts +126 -0
  64. package/src/__tests__/scenario.test.ts +381 -0
  65. package/src/all.ts +149 -12
  66. package/src/assertions.ts +253 -0
  67. package/src/context.ts +64 -38
  68. package/src/contracts.ts +14 -8
  69. package/src/crosses.ts +93 -51
  70. package/src/detours.ts +155 -18
  71. package/src/effective-examples.ts +350 -0
  72. package/src/examples.ts +127 -59
  73. package/src/harness-cli.ts +33 -49
  74. package/src/harness-mcp.ts +9 -8
  75. package/src/index.ts +13 -3
  76. package/src/scenario.ts +370 -0
  77. package/src/types.ts +63 -5
  78. package/tsconfig.tests.json +10 -0
  79. package/tsconfig.tsbuildinfo +1 -1
  80. package/dist/follows.d.ts +0 -38
  81. package/dist/follows.d.ts.map +0 -1
  82. package/dist/follows.js +0 -212
  83. package/dist/follows.js.map +0 -1
package/dist/context.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Test context factory for creating TrailContext instances suitable for testing.
3
3
  */
4
- import { Result, createProvisionLookup } from '@ontrails/core';
4
+ import { Result, buildCrossValidationSchema, createResourceLookup, passthroughTrace, } from '@ontrails/core';
5
5
  import { createTestLogger } from './logger.js';
6
6
  // ---------------------------------------------------------------------------
7
7
  // createTestContext
@@ -22,10 +22,11 @@ export const createTestContext = (overrides) => {
22
22
  extensions: undefined,
23
23
  logger: overrides?.logger ?? createTestLogger(),
24
24
  requestId: overrides?.requestId ?? 'test-request-001',
25
+ trace: overrides?.trace ?? passthroughTrace,
25
26
  workspaceRoot: cwd,
26
27
  };
27
- const lookup = createProvisionLookup(() => ctx);
28
- ctx.provision = lookup;
28
+ const lookup = createResourceLookup(() => ctx);
29
+ ctx.resource = lookup;
29
30
  return ctx;
30
31
  };
31
32
  /**
@@ -44,19 +45,27 @@ export const createTestContext = (overrides) => {
44
45
  */
45
46
  export const createCrossContext = (options) => {
46
47
  const responses = options?.responses ?? {};
47
- return (id, _input) => {
48
+ const respondToCross = (idOrTrail) => {
49
+ const id = typeof idOrTrail === 'string' ? idOrTrail : idOrTrail.id;
48
50
  const response = responses[id];
49
51
  if (response === undefined) {
50
52
  return Promise.resolve(Result.err(new Error(`No mock response for cross("${id}")`)));
51
53
  }
52
54
  return Promise.resolve(response);
53
55
  };
56
+ const cross = (async (idOrTrail, _input) => {
57
+ if (Array.isArray(idOrTrail)) {
58
+ return await Promise.all(idOrTrail.map(([target]) => respondToCross(target)));
59
+ }
60
+ return await respondToCross(idOrTrail);
61
+ });
62
+ return cross;
54
63
  };
55
64
  /**
56
- * Default permit minter — reads `trail.permit.scopes` and produces a
65
+ * Default permit creator — reads `trail.permit.scopes` and produces a
57
66
  * minimal permit object. No dependency on `@ontrails/permits`.
58
67
  */
59
- export const defaultMintPermit = (trail) => {
68
+ export const defaultCreatePermit = (trail) => {
60
69
  if (!trail.permit || trail.permit === 'public') {
61
70
  return undefined;
62
71
  }
@@ -64,44 +73,46 @@ export const defaultMintPermit = (trail) => {
64
73
  };
65
74
  const isTestExecutionOptions = (input) => input !== undefined &&
66
75
  (Object.hasOwn(input, 'ctx') ||
67
- Object.hasOwn(input, 'provisions') ||
76
+ Object.hasOwn(input, 'resources') ||
68
77
  Object.hasOwn(input, 'strictPermits') ||
69
- Object.hasOwn(input, 'mintPermit'));
78
+ Object.hasOwn(input, 'createPermit'));
70
79
  export const normalizeTestExecutionOptions = (input) => isTestExecutionOptions(input) ? input : { ctx: input };
71
- export const mergeProvisionOverrides = (autoResolved, ctx, explicit) => ({
80
+ export const mergeResourceOverrides = (autoResolved, ctx, explicit) => ({
72
81
  ...autoResolved,
73
82
  ...ctx?.extensions,
74
83
  ...explicit,
75
84
  });
76
- const buildMockProvisions = async (app) => {
77
- const provisions = {};
78
- for (const declaredProvision of app.listProvisions()) {
79
- if (!declaredProvision.mock) {
85
+ const buildMockResources = async (app) => {
86
+ const resources = {};
87
+ for (const declaredResource of app.listResources()) {
88
+ if (!declaredResource.mock) {
80
89
  continue;
81
90
  }
82
- provisions[declaredProvision.id] = await declaredProvision.mock();
91
+ resources[declaredResource.id] = await declaredResource.mock();
83
92
  }
84
- return provisions;
93
+ return resources;
85
94
  };
86
- export const resolveMockProvisions = async (app) => await buildMockProvisions(app);
95
+ export const createMockResources = async (app) => await buildMockResources(app);
96
+ // Re-export from core so existing consumers of this module continue to work.
97
+ export { buildCrossValidationSchema };
87
98
  /**
88
99
  * Merge a Partial<TrailContext> into a test context.
89
100
  * Used internally when the public API accepts Partial<TrailContext>.
90
101
  */
91
- export const mergeTestContext = (ctx, provisions) => {
102
+ export const mergeTestContext = (ctx, resources) => {
92
103
  const base = createTestContext();
93
104
  const extensions = {
94
105
  ...base.extensions,
95
106
  ...ctx?.extensions,
96
- ...provisions,
107
+ ...resources,
97
108
  };
98
109
  const merged = {
99
110
  ...base,
100
111
  ...ctx,
101
112
  extensions: Object.keys(extensions).length === 0 ? undefined : extensions,
102
113
  };
103
- const lookup = createProvisionLookup(() => merged);
104
- merged.provision = lookup;
114
+ const lookup = createResourceLookup(() => merged);
115
+ merged.resource = lookup;
105
116
  return merged;
106
117
  };
107
118
  //# sourceMappingURL=context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAuB,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAW9E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAqCzD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,IAAI,EACT,eACI,OAAO,CAAC,YAAY,CAAC,GACrB,oBAAoB,GACpB,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,GAAG,oBAAoB,CAAC,KACvD,IA6CF,CAAC"}
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAuB,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAW9E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAsCzD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,IAAI,EACT,eACI,OAAO,CAAC,YAAY,CAAC,GACrB,oBAAoB,GACpB,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,GAAG,oBAAoB,CAAC,KACvD,IAkDF,CAAC"}
package/dist/contracts.js CHANGED
@@ -8,7 +8,8 @@
8
8
  import { describe, test } from 'bun:test';
9
9
  import { executeTrail, formatZodIssues, validateInput } from '@ontrails/core';
10
10
  import { expectOk } from './assertions.js';
11
- import { mergeProvisionOverrides, mergeTestContext, normalizeTestExecutionOptions, resolveMockProvisions, } from './context.js';
11
+ import { mergeResourceOverrides, mergeTestContext, normalizeTestExecutionOptions, createMockResources, } from './context.js';
12
+ import { deriveTrailExamples } from './effective-examples.js';
12
13
  // ---------------------------------------------------------------------------
13
14
  // Helpers
14
15
  // ---------------------------------------------------------------------------
@@ -38,13 +39,16 @@ const validateOutputSchema = (outputSchema, value, trailId, exampleName) => {
38
39
  */
39
40
  export const testContracts = (app, ctxOrFactory) => {
40
41
  const resolveInput = typeof ctxOrFactory === 'function' ? ctxOrFactory : () => ctxOrFactory;
41
- const allEntries = app.list();
42
+ const allEntries = app.list().map((trailDef) => ({
43
+ ...trailDef,
44
+ examples: deriveTrailExamples(trailDef),
45
+ }));
42
46
  describe('contracts', () => {
43
47
  describe.each(allEntries)('$id', (t) => {
44
48
  if (t.output === undefined) {
45
49
  return;
46
50
  }
47
- if (t.examples === undefined || t.examples.length === 0) {
51
+ if (t.examples.length === 0) {
48
52
  return;
49
53
  }
50
54
  if (needsCrossContext(t, resolveInput)) {
@@ -54,13 +58,13 @@ export const testContracts = (app, ctxOrFactory) => {
54
58
  const successExamples = examples.filter((e) => e.error === undefined);
55
59
  test.each(successExamples)('contract: $name', async (example) => {
56
60
  const resolved = normalizeTestExecutionOptions(resolveInput());
57
- const provisions = mergeProvisionOverrides(await resolveMockProvisions(app), resolved.ctx, resolved.provisions);
61
+ const resources = mergeResourceOverrides(await createMockResources(app), resolved.ctx, resolved.resources);
58
62
  const testCtx = mergeTestContext(resolved.ctx);
59
63
  const validated = validateInput(t.input, example.input);
60
64
  expectOk(validated);
61
65
  const result = await executeTrail(t, example.input, {
62
66
  ctx: testCtx,
63
- provisions,
67
+ resources,
64
68
  });
65
69
  const resultValue = expectOk(result);
66
70
  validateOutputSchema(outputSchema, resultValue, t.id, example.name);
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
package/dist/crosses.d.ts CHANGED
@@ -4,18 +4,18 @@
4
4
  * Tests the crossing graph: which trails were crossed, in what order,
5
5
  * and supports failure injection from crossed trail examples.
6
6
  */
7
- import type { AnyTrail, ProvisionOverrideMap, TrailContext } from '@ontrails/core';
7
+ import type { AnyTrail, ResourceOverrideMap, TrailContext } from '@ontrails/core';
8
8
  import type { CrossScenario } from './types.js';
9
9
  /** Options for testCrosses that provide trail definitions for injection. */
10
10
  export interface TestCrossOptions {
11
11
  /** Partial context overrides. */
12
12
  readonly ctx?: Partial<TrailContext> | undefined;
13
13
  /**
14
- * Explicit provision overrides merged on top of auto-resolved mocks for every
14
+ * Explicit resource overrides merged on top of auto-resolved mocks for every
15
15
  * scenario. Values are passed by reference — provide immutable objects, or
16
- * use `mock()` on the provision definition to get a fresh instance per run.
16
+ * use `mock()` on the resource definition to get a fresh instance per run.
17
17
  */
18
- readonly provisions?: ProvisionOverrideMap | undefined;
18
+ readonly resources?: ResourceOverrideMap | undefined;
19
19
  /** Map of trail ID to trail definition, used for injectFromExample. */
20
20
  readonly trails?: ReadonlyMap<string, AnyTrail> | undefined;
21
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"crosses.d.ts","sourceRoot":"","sources":["../src/crosses.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,QAAQ,EAER,oBAAoB,EACpB,YAAY,EACb,MAAM,gBAAgB,CAAC;AAexB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA0ShD,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACvD,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;CAC7D;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,GACtB,UAAU,QAAQ,EAClB,WAAW,SAAS,aAAa,EAAE,EACnC,UAAU,gBAAgB,KACzB,IAsBF,CAAC"}
1
+ {"version":3,"file":"crosses.d.ts","sourceRoot":"","sources":["../src/crosses.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,QAAQ,EAER,mBAAmB,EACnB,YAAY,EACb,MAAM,gBAAgB,CAAC;AAgBxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAmVhD,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,iCAAiC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACrD,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;CAC7D;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,GACtB,UAAU,QAAQ,EAClB,WAAW,SAAS,aAAa,EAAE,EACnC,UAAU,gBAAgB,KACzB,IAsBF,CAAC"}
package/dist/crosses.js CHANGED
@@ -5,20 +5,20 @@
5
5
  * and supports failure injection from crossed trail examples.
6
6
  */
7
7
  import { describe, expect, test } from 'bun:test';
8
- import { executeTrail, InternalError, Result, ValidationError, validateInput, } from '@ontrails/core';
8
+ import { buildCrossValidationSchema, executeTrail, InternalError, Result, ValidationError, validateInput, } from '@ontrails/core';
9
9
  import { assertErrorMatch, assertFullMatch, assertSchemaMatch, } from './assertions.js';
10
- import { mergeProvisionOverrides, mergeTestContext } from './context.js';
11
- const collectDeclaredProvisions = (trailDef, trailsMap) => {
12
- const seenProvisionIds = new Set();
10
+ import { mergeResourceOverrides, mergeTestContext } from './context.js';
11
+ const collectDeclaredResources = (trailDef, trailsMap) => {
12
+ const seenResourceIds = new Set();
13
13
  const seenTrailIds = new Set();
14
- const provisions = [];
14
+ const resources = [];
15
15
  const collect = (candidate) => {
16
- for (const declaredProvision of candidate.provisions) {
17
- if (seenProvisionIds.has(declaredProvision.id)) {
16
+ for (const declaredResource of candidate.resources) {
17
+ if (seenResourceIds.has(declaredResource.id)) {
18
18
  continue;
19
19
  }
20
- seenProvisionIds.add(declaredProvision.id);
21
- provisions.push(declaredProvision);
20
+ seenResourceIds.add(declaredResource.id);
21
+ resources.push(declaredResource);
22
22
  }
23
23
  };
24
24
  const visit = (candidate) => {
@@ -35,17 +35,17 @@ const collectDeclaredProvisions = (trailDef, trailsMap) => {
35
35
  }
36
36
  };
37
37
  visit(trailDef);
38
- return provisions;
38
+ return resources;
39
39
  };
40
- const resolveCrossMockProvisions = async (trailDef, trailsMap) => {
41
- const provisions = {};
42
- for (const declaredProvision of collectDeclaredProvisions(trailDef, trailsMap)) {
43
- if (!declaredProvision.mock) {
40
+ const resolveCrossMockResources = async (trailDef, trailsMap) => {
41
+ const resources = {};
42
+ for (const declaredResource of collectDeclaredResources(trailDef, trailsMap)) {
43
+ if (!declaredResource.mock) {
44
44
  continue;
45
45
  }
46
- provisions[declaredProvision.id] = await declaredProvision.mock();
46
+ resources[declaredResource.id] = await declaredResource.mock();
47
47
  }
48
- return provisions;
48
+ return resources;
49
49
  };
50
50
  // ---------------------------------------------------------------------------
51
51
  // Injection helpers
@@ -77,10 +77,7 @@ const tryInjectError = (id, scenario, trailsMap) => {
77
77
  }
78
78
  return Result.err(new Error(errorName));
79
79
  };
80
- /**
81
- * Execute a trail from the map, validating input first.
82
- */
83
- const executeFromMap = (id, input, trailsMap, ctx, provisions, cross) => {
80
+ const executeFromMap = (id, input, trailsMap, ctx, resources, cross) => {
84
81
  const trailDef = trailsMap?.get(id);
85
82
  if (trailDef === undefined) {
86
83
  return undefined;
@@ -88,32 +85,45 @@ const executeFromMap = (id, input, trailsMap, ctx, provisions, cross) => {
88
85
  const nestedCtx = cross ? { ...ctx, cross } : ctx;
89
86
  return executeTrail(trailDef, input, {
90
87
  ctx: nestedCtx,
91
- provisions,
88
+ resources,
89
+ validationSchema: buildCrossValidationSchema(trailDef),
92
90
  });
93
91
  };
92
+ /** Extract trail ID from either a trail object or a string. */
93
+ const resolveCrossId = (idOrTrail) => typeof idOrTrail === 'string' ? idOrTrail : idOrTrail.id;
94
94
  // ---------------------------------------------------------------------------
95
95
  // Cross factory
96
96
  // ---------------------------------------------------------------------------
97
+ /** Delegate to baseCross, executeFromMap, or fall back to Result.ok(). */
98
+ const delegateCross = (id, input, baseCross, trailsMap, ctx, resources, self) => {
99
+ if (baseCross !== undefined) {
100
+ return baseCross(id, input);
101
+ }
102
+ const executed = executeFromMap(id, input, trailsMap, ctx, resources, self);
103
+ return Promise.resolve(executed ?? Result.ok());
104
+ };
97
105
  /**
98
106
  * Build a recording cross function that optionally injects errors.
99
107
  */
100
- const createRecordingCross = (trace, scenario, trailsMap, baseCross, ctx, provisions) => {
108
+ const createRecordingCross = (trace, scenario, trailsMap, baseCross, ctx, resources) => {
101
109
  // The generic O on CrossFn is erased at runtime; the cast is safe
102
110
  // because callers narrow via isOk/isErr before accessing the value.
103
- const cross = (id, input) => {
111
+ const invokeCross = async (idOrTrail, input, self) => {
112
+ const id = resolveCrossId(idOrTrail);
104
113
  trace.push({ id, input });
105
114
  const injected = tryInjectError(id, scenario, trailsMap);
106
115
  if (injected !== undefined) {
107
- return Promise.resolve(injected);
108
- }
109
- if (baseCross !== undefined) {
110
- return baseCross(id, input);
116
+ return injected;
111
117
  }
112
- const executed = executeFromMap(id, input, trailsMap, ctx, provisions, cross);
113
- if (executed !== undefined) {
114
- return Promise.resolve(executed);
118
+ return await delegateCross(id, input, baseCross, trailsMap, ctx, resources, self);
119
+ };
120
+ // Accepts either a trail object (typed cross), a string id (untyped),
121
+ // or a batch of `[target, input]` tuples.
122
+ const cross = async function cross(idOrTrail, input) {
123
+ if (Array.isArray(idOrTrail)) {
124
+ return await Promise.all(idOrTrail.map(([target, batchInput]) => invokeCross(target, batchInput, cross)));
115
125
  }
116
- return Promise.resolve(Result.ok());
126
+ return await invokeCross(idOrTrail, input, cross);
117
127
  };
118
128
  return cross;
119
129
  };
@@ -167,21 +177,21 @@ const handleValidationError = (validated, scenario) => {
167
177
  // ---------------------------------------------------------------------------
168
178
  // Scenario runner
169
179
  // ---------------------------------------------------------------------------
170
- const buildTestContext = (scenario, ctx, trailsMap, provisions) => {
180
+ const buildTestContext = (scenario, ctx, trailsMap, resources) => {
171
181
  const trace = [];
172
182
  const baseCtx = mergeTestContext(ctx);
173
- const cross = createRecordingCross(trace, scenario, trailsMap, baseCtx.cross, baseCtx, provisions);
183
+ const cross = createRecordingCross(trace, scenario, trailsMap, baseCtx.cross, baseCtx, resources);
174
184
  return { testCtx: { ...baseCtx, cross }, trace };
175
185
  };
176
- const runScenario = async (trailDef, scenario, ctx, trailsMap, provisions) => {
186
+ const runScenario = async (trailDef, scenario, ctx, trailsMap, resources) => {
177
187
  const validated = validateInput(trailDef.input, scenario.input);
178
188
  if (handleValidationError(validated, scenario)) {
179
189
  return;
180
190
  }
181
- const { trace, testCtx } = buildTestContext(scenario, ctx, trailsMap, provisions);
191
+ const { trace, testCtx } = buildTestContext(scenario, ctx, trailsMap, resources);
182
192
  const result = await executeTrail(trailDef, scenario.input, {
183
193
  ctx: testCtx,
184
- provisions,
194
+ resources,
185
195
  });
186
196
  assertCrossTrace(trace, scenario);
187
197
  assertScenarioResult(result, scenario, trailDef);
@@ -202,11 +212,11 @@ const runScenario = async (trailDef, scenario, ctx, trailsMap, provisions) => {
202
212
  * ```
203
213
  */
204
214
  export const testCrosses = (trailDef, scenarios, options) => {
205
- const explicitProvisions = options?.provisions;
215
+ const explicitResources = options?.resources;
206
216
  describe(trailDef.id, () => {
207
217
  test.each([...scenarios])('$description', async (scenario) => {
208
- const provisions = mergeProvisionOverrides(await resolveCrossMockProvisions(trailDef, options?.trails), options?.ctx, explicitProvisions);
209
- await runScenario(trailDef, scenario, options?.ctx, options?.trails, provisions);
218
+ const resources = mergeResourceOverrides(await resolveCrossMockResources(trailDef, options?.trails), options?.ctx, explicitResources);
219
+ await runScenario(trailDef, scenario, options?.ctx, options?.trails, resources);
210
220
  });
211
221
  });
212
222
  };
@@ -1 +1 @@
1
- {"version":3,"file":"crosses.js","sourceRoot":"","sources":["../src/crosses.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"crosses.js","sourceRoot":"","sources":["../src/crosses.ts"],"names":[],"mappings":"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"}
package/dist/detours.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  /**
2
- * testDetours — verify that all detour targets exist in the topo.
2
+ * testDetours — validate the live detour contract for every trail.
3
3
  *
4
- * Pure structural validation. No implementation execution needed.
4
+ * Pure structural validation. No blaze or detour recovery execution needed.
5
5
  */
6
6
  import type { Topo } from '@ontrails/core';
7
7
  /**
8
- * Verify that every trail's detour targets reference trails that
9
- * actually exist in the app's topo.
8
+ * Verify that every trail's detours match the live runtime contract:
9
+ * `on` must be an error constructor, `recover` must be callable, and
10
+ * later detours must not be shadowed by earlier broader `on` types.
10
11
  */
11
12
  export declare const testDetours: (app: Topo) => void;
12
13
  //# sourceMappingURL=detours.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"detours.d.ts","sourceRoot":"","sources":["../src/detours.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAS,MAAM,gBAAgB,CAAC;AAMlD;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,IAAI,KAAG,IAyBvC,CAAC"}
1
+ {"version":3,"file":"detours.d.ts","sourceRoot":"","sources":["../src/detours.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,KAAK,EAAE,IAAI,EAAS,MAAM,gBAAgB,CAAC;AA+HlD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,IAAI,KAAG,IAuCvC,CAAC"}
package/dist/detours.js CHANGED
@@ -1,28 +1,107 @@
1
1
  /**
2
- * testDetours — verify that all detour targets exist in the topo.
2
+ * testDetours — validate the live detour contract for every trail.
3
3
  *
4
- * Pure structural validation. No implementation execution needed.
4
+ * Pure structural validation. No blaze or detour recovery execution needed.
5
5
  */
6
- import { describe, expect, test } from 'bun:test';
7
- // ---------------------------------------------------------------------------
8
- // testDetours
9
- // ---------------------------------------------------------------------------
6
+ import { describe, test } from 'bun:test';
7
+ import { TrailsError } from '@ontrails/core';
8
+ const isErrorConstructor = (value) => {
9
+ if (typeof value !== 'function') {
10
+ return false;
11
+ }
12
+ const { prototype } = value;
13
+ return prototype instanceof Error;
14
+ };
15
+ const detourLabel = (trailId, index, detour) => {
16
+ if (typeof detour.on === 'function') {
17
+ const { name } = detour.on;
18
+ if (typeof name === 'string' && name.length > 0) {
19
+ return `${trailId} detour[${index}] on ${name}`;
20
+ }
21
+ }
22
+ return `${trailId} detour[${index}]`;
23
+ };
24
+ const assertValidOn = (trailId, index, detour) => {
25
+ if (isErrorConstructor(detour.on)) {
26
+ return;
27
+ }
28
+ throw new Error(`${detourLabel(trailId, index, detour)} must declare a real error constructor in on:`);
29
+ };
30
+ const assertCallableRecover = (trailId, index, detour) => {
31
+ if (typeof detour.recover === 'function') {
32
+ return;
33
+ }
34
+ throw new Error(`${detourLabel(trailId, index, detour)} must declare a callable recover function`);
35
+ };
36
+ const sameOrSubtype = (candidate, ancestor) => {
37
+ if (candidate === ancestor) {
38
+ return true;
39
+ }
40
+ let current = Object.getPrototypeOf(candidate.prototype);
41
+ while (current && typeof current === 'object') {
42
+ const ctor = current.constructor;
43
+ if (ctor === ancestor) {
44
+ return true;
45
+ }
46
+ current = Object.getPrototypeOf(current);
47
+ }
48
+ return false;
49
+ };
50
+ const getShadowingDetour = (detours, index) => {
51
+ const detour = detours[index];
52
+ if (!detour || !isErrorConstructor(detour.on)) {
53
+ return undefined;
54
+ }
55
+ for (let previousIndex = 0; previousIndex < index; previousIndex += 1) {
56
+ const previous = detours[previousIndex];
57
+ if (!previous || !isErrorConstructor(previous.on)) {
58
+ continue;
59
+ }
60
+ if (sameOrSubtype(detour.on, previous.on)) {
61
+ return { index: previousIndex, on: previous.on };
62
+ }
63
+ }
64
+ return undefined;
65
+ };
66
+ const assertNotShadowed = (trailId, detours, index) => {
67
+ const detour = detours[index];
68
+ if (!detour || !isErrorConstructor(detour.on)) {
69
+ return;
70
+ }
71
+ const shadowing = getShadowingDetour(detours, index);
72
+ if (!shadowing) {
73
+ return;
74
+ }
75
+ const previousName = shadowing.on.name || TrailsError.name;
76
+ const currentName = detour.on.name || TrailsError.name;
77
+ throw new Error(`${trailId} detour[${index}] on ${currentName} is shadowed by earlier detour[${shadowing.index}] on ${previousName}`);
78
+ };
10
79
  /**
11
- * Verify that every trail's detour targets reference trails that
12
- * actually exist in the app's topo.
80
+ * Verify that every trail's detours match the live runtime contract:
81
+ * `on` must be an error constructor, `recover` must be callable, and
82
+ * later detours must not be shadowed by earlier broader `on` types.
13
83
  */
14
84
  export const testDetours = (app) => {
15
85
  const trailEntries = [...app.trails];
16
86
  describe('detours', () => {
17
87
  describe.each(trailEntries)('%s', (_id, trailDef) => {
18
- const t = trailDef;
19
- if (t.detours === undefined) {
88
+ const trail = trailDef;
89
+ if (trail.detours.length === 0) {
20
90
  return;
21
91
  }
22
- const { detours } = t;
23
- const testCases = Object.entries(detours).flatMap(([detourName, targets]) => targets.map((targetId) => ({ detourName, targetId })));
24
- test.each(testCases)('detour "$detourName" -> "$targetId" exists', ({ targetId }) => {
25
- expect(app.has(targetId)).toBe(true);
92
+ const detourCases = trail.detours.map((detour, index) => ({
93
+ detour,
94
+ index,
95
+ trailId: trail.id,
96
+ }));
97
+ test.each(detourCases)('$trailId detour[$index] uses an error constructor', ({ detour, index, trailId }) => {
98
+ assertValidOn(trailId, index, detour);
99
+ });
100
+ test.each(detourCases)('$trailId detour[$index] provides a callable recover', ({ detour, index, trailId }) => {
101
+ assertCallableRecover(trailId, index, detour);
102
+ });
103
+ test.each(detourCases)('$trailId detour[$index] is not shadowed by an earlier detour', ({ index, trailId }) => {
104
+ assertNotShadowed(trailId, trail.detours, index);
26
105
  });
27
106
  });
28
107
  });
@@ -1 +1 @@
1
- {"version":3,"file":"detours.js","sourceRoot":"","sources":["../src/detours.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAIlD,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAS,EAAQ,EAAE;IAC7C,MAAM,YAAY,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAErC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;YAClD,MAAM,CAAC,GAAG,QAAmC,CAAC;YAE9C,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC5B,OAAO;YACT,CAAC;YAED,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;YACtB,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAC/C,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE,CACxB,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CACxD,CAAC;YAEF,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAClB,4CAA4C,EAC5C,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;gBACf,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvC,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
1
+ {"version":3,"file":"detours.js","sourceRoot":"","sources":["../src/detours.ts"],"names":[],"mappings":"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"}