@ontrails/testing 1.0.0-beta.1 → 1.0.0-beta.11
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 +166 -0
- package/README.md +25 -7
- package/dist/all.d.ts +2 -1
- package/dist/all.d.ts.map +1 -1
- package/dist/all.js.map +1 -1
- package/dist/context.d.ts +28 -2
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +70 -11
- package/dist/context.js.map +1 -1
- package/dist/contracts.d.ts +3 -2
- package/dist/contracts.d.ts.map +1 -1
- package/dist/contracts.js +25 -10
- package/dist/contracts.js.map +1 -1
- package/dist/examples.d.ts +4 -3
- package/dist/examples.d.ts.map +1 -1
- package/dist/examples.js +63 -68
- package/dist/examples.js.map +1 -1
- package/dist/follows.d.ts +38 -0
- package/dist/follows.d.ts.map +1 -0
- package/dist/{hike.js → follows.js} +71 -28
- package/dist/follows.js.map +1 -0
- package/dist/harness-mcp.d.ts.map +1 -1
- package/dist/harness-mcp.js +5 -2
- package/dist/harness-mcp.js.map +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/trail.js +1 -1
- package/dist/trail.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/__tests__/all.test.ts +64 -0
- package/src/__tests__/context.test.ts +92 -2
- package/src/__tests__/contracts.test.ts +122 -5
- package/src/__tests__/detours.test.ts +3 -3
- package/src/__tests__/examples.test.ts +285 -22
- package/src/__tests__/follows.test.ts +589 -0
- package/src/__tests__/trail.test.ts +4 -4
- package/src/all.ts +5 -1
- package/src/context.ts +121 -13
- package/src/contracts.ts +43 -12
- package/src/examples.ts +111 -105
- package/src/{hike.ts → follows.ts} +138 -43
- package/src/harness-mcp.ts +5 -2
- package/src/index.ts +6 -4
- package/src/trail.ts +1 -1
- package/src/types.ts +3 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/hike.d.ts +0 -32
- package/dist/hike.d.ts.map +0 -1
- package/dist/hike.js.map +0 -1
- package/src/__tests__/hike.test.ts +0 -164
package/dist/examples.js
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Iterates every trail in the app's topo. For each trail with examples,
|
|
5
5
|
* generates describe/test blocks using bun:test. Progressive assertion
|
|
6
|
-
* determines which check to run per example. For
|
|
6
|
+
* determines which check to run per example. For trails with `follow`
|
|
7
7
|
* declarations, checks that every declared follow was called at least once.
|
|
8
8
|
*/
|
|
9
9
|
import { describe, expect, test } from 'bun:test';
|
|
10
|
-
import { AlreadyExistsError, AmbiguousError, AssertionError, AuthError, CancelledError, ConflictError, InternalError, NetworkError, NotFoundError, PermissionError, RateLimitError, Result, TimeoutError, TrailsError, ValidationError, validateInput, } from '@ontrails/core';
|
|
11
|
-
import { assertErrorMatch, assertFullMatch, assertSchemaMatch,
|
|
12
|
-
import { mergeTestContext } from './context.js';
|
|
10
|
+
import { AlreadyExistsError, AmbiguousError, AssertionError, AuthError, CancelledError, ConflictError, InternalError, NetworkError, NotFoundError, PermissionError, RateLimitError, executeTrail, Result, TimeoutError, TrailsError, ValidationError, validateInput, } from '@ontrails/core';
|
|
11
|
+
import { assertErrorMatch, assertFullMatch, assertSchemaMatch, } from './assertions.js';
|
|
12
|
+
import { mergeServiceOverrides, mergeTestContext, normalizeTestExecutionOptions, resolveMockServices, } from './context.js';
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
// Error class name -> constructor map
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
@@ -69,17 +69,19 @@ const handleValidationError = (validated, example) => {
|
|
|
69
69
|
* Run a single example against a trail.
|
|
70
70
|
* Handles validation, execution, and assertions.
|
|
71
71
|
*/
|
|
72
|
-
const runExample = async (t, example, output, testCtx) => {
|
|
72
|
+
const runExample = async (t, example, output, testCtx, services) => {
|
|
73
73
|
const validated = validateInput(t.input, example.input);
|
|
74
74
|
if (handleValidationError(validated, example)) {
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
|
-
const
|
|
78
|
-
|
|
77
|
+
const result = await executeTrail(t, example.input, {
|
|
78
|
+
ctx: testCtx,
|
|
79
|
+
services,
|
|
80
|
+
});
|
|
79
81
|
assertProgressiveMatch(result, example, output);
|
|
80
82
|
};
|
|
81
83
|
// ---------------------------------------------------------------------------
|
|
82
|
-
//
|
|
84
|
+
// Follow coverage for composition trails
|
|
83
85
|
// ---------------------------------------------------------------------------
|
|
84
86
|
/**
|
|
85
87
|
* Build a recording follow function that tracks which trail IDs are called.
|
|
@@ -88,7 +90,7 @@ const runExample = async (t, example, output, testCtx) => {
|
|
|
88
90
|
* in the topo and executes it with validated input. Falls back to
|
|
89
91
|
* `Result.ok()` when neither is available.
|
|
90
92
|
*/
|
|
91
|
-
const createCoverageFollow = (called, baseFollow, topo, ctx) => {
|
|
93
|
+
const createCoverageFollow = (called, baseFollow, topo, ctx, services) => {
|
|
92
94
|
const follow = (id, input) => {
|
|
93
95
|
called.add(id);
|
|
94
96
|
if (baseFollow !== undefined) {
|
|
@@ -96,63 +98,30 @@ const createCoverageFollow = (called, baseFollow, topo, ctx) => {
|
|
|
96
98
|
}
|
|
97
99
|
const trailDef = topo.get(id);
|
|
98
100
|
if (trailDef !== undefined) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
return Promise.resolve(trailDef.implementation(validated.value, ctx));
|
|
101
|
+
return executeTrail(trailDef, input, {
|
|
102
|
+
ctx: { ...ctx, follow },
|
|
103
|
+
services,
|
|
104
|
+
});
|
|
104
105
|
}
|
|
105
106
|
return Promise.resolve(Result.ok());
|
|
106
107
|
};
|
|
107
108
|
return follow;
|
|
108
109
|
};
|
|
109
110
|
/**
|
|
110
|
-
* Run a single example against a
|
|
111
|
+
* Run a single example against a composition trail, recording follow calls.
|
|
111
112
|
*/
|
|
112
|
-
const
|
|
113
|
-
const validated = validateInput(
|
|
113
|
+
const runCompositionExample = async (trailDef, example, output, baseCtx, called, topo, services) => {
|
|
114
|
+
const validated = validateInput(trailDef.input, example.input);
|
|
114
115
|
if (handleValidationError(validated, example)) {
|
|
115
116
|
return;
|
|
116
117
|
}
|
|
117
|
-
const
|
|
118
|
-
const follow = createCoverageFollow(called, baseCtx.follow, topo, baseCtx);
|
|
118
|
+
const follow = createCoverageFollow(called, baseCtx.follow, topo, baseCtx, services);
|
|
119
119
|
const testCtx = { ...baseCtx, follow };
|
|
120
|
-
const result = await
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const collectHikesWithExamples = (app) => [...app.hikes]
|
|
124
|
-
.filter(([, h]) => h.examples !== undefined && h.examples.length > 0)
|
|
125
|
-
.map(([hikeId, hikeDef]) => ({
|
|
126
|
-
examples: hikeDef.examples,
|
|
127
|
-
hikeDef,
|
|
128
|
-
hikeId,
|
|
129
|
-
}));
|
|
130
|
-
// ---------------------------------------------------------------------------
|
|
131
|
-
// Hike example describe blocks
|
|
132
|
-
// ---------------------------------------------------------------------------
|
|
133
|
-
/**
|
|
134
|
-
* Generate describe/test blocks for hikes with follows coverage.
|
|
135
|
-
*
|
|
136
|
-
* Always uses a recording follow so that follows coverage can be checked.
|
|
137
|
-
* Hikes without `follows` still run their examples but skip the coverage test.
|
|
138
|
-
*/
|
|
139
|
-
const describeHikeExamples = (hikesWithExamples, resolveCtx, topo) => {
|
|
140
|
-
if (hikesWithExamples.length === 0) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
describe.each([...hikesWithExamples])('$hikeId', ({ hikeDef, examples }) => {
|
|
144
|
-
const called = new Set();
|
|
145
|
-
test.each([...examples])('example: $name', async (example) => {
|
|
146
|
-
const baseCtx = mergeTestContext(resolveCtx());
|
|
147
|
-
await runHikeExample(hikeDef, example, hikeDef.output, baseCtx, called, topo);
|
|
148
|
-
});
|
|
149
|
-
if (hikeDef.follows.length > 0) {
|
|
150
|
-
test('follows coverage', () => {
|
|
151
|
-
const uncovered = hikeDef.follows.filter((id) => !called.has(id));
|
|
152
|
-
expect(uncovered).toEqual([]);
|
|
153
|
-
});
|
|
154
|
-
}
|
|
120
|
+
const result = await executeTrail(trailDef, example.input, {
|
|
121
|
+
ctx: testCtx,
|
|
122
|
+
services,
|
|
155
123
|
});
|
|
124
|
+
assertProgressiveMatch(result, example, output);
|
|
156
125
|
};
|
|
157
126
|
// ---------------------------------------------------------------------------
|
|
158
127
|
// testExamples
|
|
@@ -160,7 +129,7 @@ const describeHikeExamples = (hikesWithExamples, resolveCtx, topo) => {
|
|
|
160
129
|
/**
|
|
161
130
|
* Generate describe/test blocks for every trail example in the app.
|
|
162
131
|
*
|
|
163
|
-
* For
|
|
132
|
+
* For trails with `follow` declarations and examples, also verifies that
|
|
164
133
|
* every declared follow ID was called at least once across all examples.
|
|
165
134
|
*
|
|
166
135
|
* One line in your test file:
|
|
@@ -169,19 +138,45 @@ const describeHikeExamples = (hikesWithExamples, resolveCtx, topo) => {
|
|
|
169
138
|
* ```
|
|
170
139
|
*/
|
|
171
140
|
export const testExamples = (app, ctxOrFactory) => {
|
|
172
|
-
const
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
141
|
+
const resolveInput = typeof ctxOrFactory === 'function' ? ctxOrFactory : () => ctxOrFactory;
|
|
142
|
+
const allTrails = app.list();
|
|
143
|
+
const withExamples = allTrails.filter((t) => t.examples !== undefined && t.examples.length > 0);
|
|
144
|
+
const simpleTrails = withExamples.filter((t) => t.follow.length === 0);
|
|
145
|
+
const compositionTrails = withExamples.filter((t) => t.follow.length > 0);
|
|
146
|
+
// Simple trails: run examples directly
|
|
147
|
+
if (simpleTrails.length > 0) {
|
|
148
|
+
describe.each(simpleTrails)('$id', (t) => {
|
|
149
|
+
const { examples, output } = t;
|
|
150
|
+
if (!examples) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
test.each([...examples])('example: $name', async (example) => {
|
|
154
|
+
const resolved = normalizeTestExecutionOptions(resolveInput());
|
|
155
|
+
const services = mergeServiceOverrides(await resolveMockServices(app), resolved.ctx, resolved.services);
|
|
156
|
+
const testCtx = mergeTestContext(resolved.ctx);
|
|
157
|
+
await runExample(t, example, output, testCtx, services);
|
|
158
|
+
});
|
|
183
159
|
});
|
|
184
|
-
}
|
|
185
|
-
|
|
160
|
+
}
|
|
161
|
+
// Composition trails: use recording follow and check coverage
|
|
162
|
+
if (compositionTrails.length > 0) {
|
|
163
|
+
describe.each(compositionTrails)('$id', (t) => {
|
|
164
|
+
const { examples, output } = t;
|
|
165
|
+
if (!examples) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const called = new Set();
|
|
169
|
+
test.each([...examples])('example: $name', async (example) => {
|
|
170
|
+
const resolved = normalizeTestExecutionOptions(resolveInput());
|
|
171
|
+
const services = mergeServiceOverrides(await resolveMockServices(app), resolved.ctx, resolved.services);
|
|
172
|
+
const baseCtx = mergeTestContext(resolved.ctx);
|
|
173
|
+
await runCompositionExample(t, example, output, baseCtx, called, app, services);
|
|
174
|
+
});
|
|
175
|
+
test('follow coverage', () => {
|
|
176
|
+
const uncovered = t.follow.filter((id) => !called.has(id));
|
|
177
|
+
expect(uncovered).toEqual([]);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
186
181
|
};
|
|
187
182
|
//# sourceMappingURL=examples.js.map
|
package/dist/examples.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"examples.js","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAWlD,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,MAAM,EACN,YAAY,EACZ,WAAW,EACX,eAAe,EACf,aAAa,GACd,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,
|
|
1
|
+
{"version":3,"file":"examples.js","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* testFollows — composition-aware scenario testing for trails with follow.
|
|
3
|
+
*
|
|
4
|
+
* Tests the follow graph: which trails were followed, in what order,
|
|
5
|
+
* and supports failure injection from followed trail examples.
|
|
6
|
+
*/
|
|
7
|
+
import type { AnyTrail, ServiceOverrideMap, TrailContext } from '@ontrails/core';
|
|
8
|
+
import type { FollowScenario } from './types.js';
|
|
9
|
+
/** Options for testFollows that provide trail definitions for injection. */
|
|
10
|
+
export interface TestFollowOptions {
|
|
11
|
+
/** Partial context overrides. */
|
|
12
|
+
readonly ctx?: Partial<TrailContext> | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Explicit service overrides merged on top of auto-resolved mocks for every
|
|
15
|
+
* scenario. Values are passed by reference — provide immutable objects, or
|
|
16
|
+
* use `mock()` on the service definition to get a fresh instance per run.
|
|
17
|
+
*/
|
|
18
|
+
readonly services?: ServiceOverrideMap | undefined;
|
|
19
|
+
/** Map of trail ID to trail definition, used for injectFromExample. */
|
|
20
|
+
readonly trails?: ReadonlyMap<string, AnyTrail> | undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Generate a describe block for a composition trail with one test per scenario.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* testFollows(onboardTrail, [
|
|
28
|
+
* {
|
|
29
|
+
* description: "follows add then relate",
|
|
30
|
+
* input: { name: "Alpha" },
|
|
31
|
+
* expectOk: true,
|
|
32
|
+
* expectFollowed: ["entity.add", "entity.relate"],
|
|
33
|
+
* },
|
|
34
|
+
* ]);
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare const testFollows: (trailDef: AnyTrail, scenarios: readonly FollowScenario[], options?: TestFollowOptions) => void;
|
|
38
|
+
//# sourceMappingURL=follows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follows.d.ts","sourceRoot":"","sources":["../src/follows.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,QAAQ,EAER,kBAAkB,EAClB,YAAY,EACb,MAAM,gBAAgB,CAAC;AAexB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAuSjD,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACnD,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,cAAc,EAAE,EACpC,UAAU,iBAAiB,KAC1B,IAoBF,CAAC"}
|
|
@@ -1,13 +1,52 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* testFollows — composition-aware scenario testing for trails with follow.
|
|
3
3
|
*
|
|
4
|
-
* Tests the
|
|
4
|
+
* Tests the follow graph: which trails were followed, in what order,
|
|
5
5
|
* and supports failure injection from followed trail examples.
|
|
6
6
|
*/
|
|
7
7
|
import { describe, expect, test } from 'bun:test';
|
|
8
|
-
import { InternalError, Result, ValidationError, validateInput, } from '@ontrails/core';
|
|
9
|
-
import { assertErrorMatch, assertFullMatch, assertSchemaMatch,
|
|
10
|
-
import { mergeTestContext } from './context.js';
|
|
8
|
+
import { executeTrail, InternalError, Result, ValidationError, validateInput, } from '@ontrails/core';
|
|
9
|
+
import { assertErrorMatch, assertFullMatch, assertSchemaMatch, } from './assertions.js';
|
|
10
|
+
import { mergeServiceOverrides, mergeTestContext } from './context.js';
|
|
11
|
+
const collectDeclaredServices = (trailDef, trailsMap) => {
|
|
12
|
+
const seenServiceIds = new Set();
|
|
13
|
+
const seenTrailIds = new Set();
|
|
14
|
+
const services = [];
|
|
15
|
+
const collect = (candidate) => {
|
|
16
|
+
for (const declaredService of candidate.services) {
|
|
17
|
+
if (seenServiceIds.has(declaredService.id)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
seenServiceIds.add(declaredService.id);
|
|
21
|
+
services.push(declaredService);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const visit = (candidate) => {
|
|
25
|
+
if (seenTrailIds.has(candidate.id)) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
seenTrailIds.add(candidate.id);
|
|
29
|
+
collect(candidate);
|
|
30
|
+
for (const followedId of candidate.follow) {
|
|
31
|
+
const followedTrail = trailsMap?.get(followedId);
|
|
32
|
+
if (followedTrail) {
|
|
33
|
+
visit(followedTrail);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
visit(trailDef);
|
|
38
|
+
return services;
|
|
39
|
+
};
|
|
40
|
+
const resolveMockServices = async (trailDef, trailsMap) => {
|
|
41
|
+
const services = {};
|
|
42
|
+
for (const declaredService of collectDeclaredServices(trailDef, trailsMap)) {
|
|
43
|
+
if (!declaredService.mock) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
services[declaredService.id] = await declaredService.mock();
|
|
47
|
+
}
|
|
48
|
+
return services;
|
|
49
|
+
};
|
|
11
50
|
// ---------------------------------------------------------------------------
|
|
12
51
|
// Injection helpers
|
|
13
52
|
// ---------------------------------------------------------------------------
|
|
@@ -41,16 +80,16 @@ const tryInjectError = (id, scenario, trailsMap) => {
|
|
|
41
80
|
/**
|
|
42
81
|
* Execute a trail from the map, validating input first.
|
|
43
82
|
*/
|
|
44
|
-
const executeFromMap = (id, input, trailsMap, ctx) => {
|
|
83
|
+
const executeFromMap = (id, input, trailsMap, ctx, services, follow) => {
|
|
45
84
|
const trailDef = trailsMap?.get(id);
|
|
46
85
|
if (trailDef === undefined) {
|
|
47
86
|
return undefined;
|
|
48
87
|
}
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
88
|
+
const nestedCtx = follow ? { ...ctx, follow } : ctx;
|
|
89
|
+
return executeTrail(trailDef, input, {
|
|
90
|
+
ctx: nestedCtx,
|
|
91
|
+
services,
|
|
92
|
+
});
|
|
54
93
|
};
|
|
55
94
|
// ---------------------------------------------------------------------------
|
|
56
95
|
// Follow factory
|
|
@@ -58,7 +97,7 @@ const executeFromMap = (id, input, trailsMap, ctx) => {
|
|
|
58
97
|
/**
|
|
59
98
|
* Build a recording follow function that optionally injects errors.
|
|
60
99
|
*/
|
|
61
|
-
const createRecordingFollow = (trace, scenario, trailsMap, baseFollow, ctx) => {
|
|
100
|
+
const createRecordingFollow = (trace, scenario, trailsMap, baseFollow, ctx, services) => {
|
|
62
101
|
// The generic O on FollowFn is erased at runtime; the cast is safe
|
|
63
102
|
// because callers narrow via isOk/isErr before accessing the value.
|
|
64
103
|
const follow = (id, input) => {
|
|
@@ -70,7 +109,7 @@ const createRecordingFollow = (trace, scenario, trailsMap, baseFollow, ctx) => {
|
|
|
70
109
|
if (baseFollow !== undefined) {
|
|
71
110
|
return baseFollow(id, input);
|
|
72
111
|
}
|
|
73
|
-
const executed = executeFromMap(id, input, trailsMap, ctx);
|
|
112
|
+
const executed = executeFromMap(id, input, trailsMap, ctx, services, follow);
|
|
74
113
|
if (executed !== undefined) {
|
|
75
114
|
return Promise.resolve(executed);
|
|
76
115
|
}
|
|
@@ -81,7 +120,7 @@ const createRecordingFollow = (trace, scenario, trailsMap, baseFollow, ctx) => {
|
|
|
81
120
|
// ---------------------------------------------------------------------------
|
|
82
121
|
// Scenario assertions
|
|
83
122
|
// ---------------------------------------------------------------------------
|
|
84
|
-
const assertScenarioResult = (result, scenario,
|
|
123
|
+
const assertScenarioResult = (result, scenario, trailDef) => {
|
|
85
124
|
if (scenario.expectValue !== undefined) {
|
|
86
125
|
assertFullMatch(result, scenario.expectValue);
|
|
87
126
|
}
|
|
@@ -96,7 +135,7 @@ const assertScenarioResult = (result, scenario, hikeDef) => {
|
|
|
96
135
|
}
|
|
97
136
|
else if (scenario.expectOk === true) {
|
|
98
137
|
expect(result.isOk()).toBe(true);
|
|
99
|
-
assertSchemaMatch(result,
|
|
138
|
+
assertSchemaMatch(result, trailDef.output);
|
|
100
139
|
}
|
|
101
140
|
};
|
|
102
141
|
const assertFollowTrace = (trace, scenario) => {
|
|
@@ -128,28 +167,31 @@ const handleValidationError = (validated, scenario) => {
|
|
|
128
167
|
// ---------------------------------------------------------------------------
|
|
129
168
|
// Scenario runner
|
|
130
169
|
// ---------------------------------------------------------------------------
|
|
131
|
-
const buildTestContext = (scenario, ctx, trailsMap) => {
|
|
170
|
+
const buildTestContext = (scenario, ctx, trailsMap, services) => {
|
|
132
171
|
const trace = [];
|
|
133
172
|
const baseCtx = mergeTestContext(ctx);
|
|
134
|
-
const follow = createRecordingFollow(trace, scenario, trailsMap, baseCtx.follow, baseCtx);
|
|
173
|
+
const follow = createRecordingFollow(trace, scenario, trailsMap, baseCtx.follow, baseCtx, services);
|
|
135
174
|
return { testCtx: { ...baseCtx, follow }, trace };
|
|
136
175
|
};
|
|
137
|
-
const runScenario = async (
|
|
138
|
-
const validated = validateInput(
|
|
176
|
+
const runScenario = async (trailDef, scenario, ctx, trailsMap, services) => {
|
|
177
|
+
const validated = validateInput(trailDef.input, scenario.input);
|
|
139
178
|
if (handleValidationError(validated, scenario)) {
|
|
140
179
|
return;
|
|
141
180
|
}
|
|
142
|
-
const { trace, testCtx } = buildTestContext(scenario, ctx, trailsMap);
|
|
143
|
-
const result = await
|
|
181
|
+
const { trace, testCtx } = buildTestContext(scenario, ctx, trailsMap, services);
|
|
182
|
+
const result = await executeTrail(trailDef, scenario.input, {
|
|
183
|
+
ctx: testCtx,
|
|
184
|
+
services,
|
|
185
|
+
});
|
|
144
186
|
assertFollowTrace(trace, scenario);
|
|
145
|
-
assertScenarioResult(result, scenario,
|
|
187
|
+
assertScenarioResult(result, scenario, trailDef);
|
|
146
188
|
};
|
|
147
189
|
/**
|
|
148
|
-
* Generate a describe block for a
|
|
190
|
+
* Generate a describe block for a composition trail with one test per scenario.
|
|
149
191
|
*
|
|
150
192
|
* @example
|
|
151
193
|
* ```ts
|
|
152
|
-
*
|
|
194
|
+
* testFollows(onboardTrail, [
|
|
153
195
|
* {
|
|
154
196
|
* description: "follows add then relate",
|
|
155
197
|
* input: { name: "Alpha" },
|
|
@@ -159,11 +201,12 @@ const runScenario = async (hikeDef, scenario, ctx, trailsMap) => {
|
|
|
159
201
|
* ]);
|
|
160
202
|
* ```
|
|
161
203
|
*/
|
|
162
|
-
export const
|
|
163
|
-
describe(
|
|
204
|
+
export const testFollows = (trailDef, scenarios, options) => {
|
|
205
|
+
describe(trailDef.id, () => {
|
|
164
206
|
test.each([...scenarios])('$description', async (scenario) => {
|
|
165
|
-
await
|
|
207
|
+
const services = mergeServiceOverrides(await resolveMockServices(trailDef, options?.trails), options?.ctx, options?.services);
|
|
208
|
+
await runScenario(trailDef, scenario, options?.ctx, options?.trails, services);
|
|
166
209
|
});
|
|
167
210
|
});
|
|
168
211
|
};
|
|
169
|
-
//# sourceMappingURL=
|
|
212
|
+
//# sourceMappingURL=follows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follows.js","sourceRoot":"","sources":["../src/follows.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-mcp.d.ts","sourceRoot":"","sources":["../src/harness-mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAMpB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,iBAAiB,KAAG,
|
|
1
|
+
{"version":3,"file":"harness-mcp.d.ts","sourceRoot":"","sources":["../src/harness-mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAMpB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,iBAAiB,KAAG,UAmC7D,CAAC"}
|
package/dist/harness-mcp.js
CHANGED
|
@@ -21,9 +21,12 @@ import { buildMcpTools } from '@ontrails/mcp';
|
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
23
|
export const createMcpHarness = (options) => {
|
|
24
|
-
const
|
|
24
|
+
const toolsResult = buildMcpTools(options.app);
|
|
25
|
+
if (toolsResult.isErr()) {
|
|
26
|
+
throw toolsResult.error;
|
|
27
|
+
}
|
|
25
28
|
const toolMap = new Map();
|
|
26
|
-
for (const tool of
|
|
29
|
+
for (const tool of toolsResult.value) {
|
|
27
30
|
toolMap.set(tool.name, tool);
|
|
28
31
|
}
|
|
29
32
|
return {
|
package/dist/harness-mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness-mcp.js","sourceRoot":"","sources":["../src/harness-mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAS9C,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAA0B,EAAc,EAAE;IACzE,MAAM,
|
|
1
|
+
{"version":3,"file":"harness-mcp.js","sourceRoot":"","sources":["../src/harness-mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAS9C,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAA0B,EAAc,EAAE;IACzE,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC;QACxB,MAAM,WAAW,CAAC,KAAK,CAAC;IAC1B,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,EAA6B,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO;QACL,KAAK,CAAC,QAAQ,CACZ,IAAY,EACZ,IAA6B;YAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oBAC1D,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;gBACtC,aAAa,EAAE,SAAS;gBACxB,YAAY,EAAE,SAAS;gBACvB,MAAM,EAAE,SAAS;aAClB,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;aACjC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
export { testAll } from './all.js';
|
|
2
2
|
export { testExamples } from './examples.js';
|
|
3
|
-
export {
|
|
3
|
+
export { testFollows } from './follows.js';
|
|
4
4
|
export { testTrail } from './trail.js';
|
|
5
5
|
export { testContracts } from './contracts.js';
|
|
6
6
|
export { testDetours } from './detours.js';
|
|
7
7
|
export { assertErrorMatch, assertFullMatch, assertSchemaMatch, expectErr, expectOk, } from './assertions.js';
|
|
8
|
-
export { createTestContext } from './context.js';
|
|
8
|
+
export { createFollowContext, createTestContext } from './context.js';
|
|
9
9
|
export { createTestLogger } from './logger.js';
|
|
10
10
|
export { createCliHarness } from './harness-cli.js';
|
|
11
11
|
export { createMcpHarness } from './harness-mcp.js';
|
|
12
|
-
export type {
|
|
13
|
-
export type {
|
|
12
|
+
export type { CreateFollowContextOptions } from './context.js';
|
|
13
|
+
export type { TestExecutionOptions } from './context.js';
|
|
14
|
+
export type { TestFollowOptions } from './follows.js';
|
|
15
|
+
export type { FollowScenario, TestScenario, TestLogger, TestTrailContextOptions, CliHarness, CliHarnessOptions, CliHarnessResult, McpHarness, McpHarnessOptions, McpHarnessResult, } from './types.js';
|
|
14
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGpD,YAAY,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,uBAAuB,EACvB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
// Contract-driven testing
|
|
2
2
|
export { testAll } from './all.js';
|
|
3
3
|
export { testExamples } from './examples.js';
|
|
4
|
-
export {
|
|
4
|
+
export { testFollows } from './follows.js';
|
|
5
5
|
export { testTrail } from './trail.js';
|
|
6
6
|
export { testContracts } from './contracts.js';
|
|
7
7
|
export { testDetours } from './detours.js';
|
|
8
8
|
// Assertions
|
|
9
9
|
export { assertErrorMatch, assertFullMatch, assertSchemaMatch, expectErr, expectOk, } from './assertions.js';
|
|
10
10
|
// Mock factories
|
|
11
|
-
export { createTestContext } from './context.js';
|
|
11
|
+
export { createFollowContext, createTestContext } from './context.js';
|
|
12
12
|
export { createTestLogger } from './logger.js';
|
|
13
13
|
// Surface harnesses
|
|
14
14
|
export { createCliHarness } from './harness-cli.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,aAAa;AACb,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,iBAAiB;AACjB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,oBAAoB;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/trail.js
CHANGED
|
@@ -54,7 +54,7 @@ const runScenario = async (trailDef, scenario, ctx) => {
|
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
const validatedInput = expectOk(validated);
|
|
57
|
-
const result = await trailDef.
|
|
57
|
+
const result = await trailDef.run(validatedInput, testCtx);
|
|
58
58
|
assertScenarioResult(result, scenario, trailDef);
|
|
59
59
|
};
|
|
60
60
|
// ---------------------------------------------------------------------------
|
package/dist/trail.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trail.js","sourceRoot":"","sources":["../src/trail.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGlD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,oBAAoB,GAAG,CAC3B,MAA8B,EAC9B,QAAsB,EACtB,QAAkB,EACZ,EAAE;IACR,IAAI,QAAQ,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACvC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IAChD,CAAC;SAAM,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5C,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC1E,CAAC;SAAM,IAAI,QAAQ,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC;YACnB,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;SAAM,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjC,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,CAC5B,SAAiC,EACjC,QAAsB,EACb,EAAE;IACX,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,QAAQ,CAAC,SAAS,KAAK,eAAe,EAAE,CAAC;QAC3C,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QACxD,IAAI,QAAQ,CAAC,gBAAgB,KAAK,SAAS,EAAE,CAAC;YAC5C,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,KAAK,CACb,yCAAyC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,CACnE,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,KAAK,EACvB,QAAkB,EAClB,QAAsB,EACtB,GAAsC,EACvB,EAAE;IACjB,MAAM,OAAO,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhE,IAAI,qBAAqB,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC/C,OAAO;IACT,CAAC;IACD,MAAM,cAAc,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"trail.js","sourceRoot":"","sources":["../src/trail.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -18,8 +18,8 @@ export interface TestScenario {
|
|
|
18
18
|
/** Input to pass to the implementation. */
|
|
19
19
|
readonly input: unknown;
|
|
20
20
|
}
|
|
21
|
-
/** A test scenario for a
|
|
22
|
-
export interface
|
|
21
|
+
/** A test scenario for a trail's composition graph. */
|
|
22
|
+
export interface FollowScenario extends TestScenario {
|
|
23
23
|
/** Assert these trail IDs were followed, in order. */
|
|
24
24
|
readonly expectFollowed?: readonly string[] | undefined;
|
|
25
25
|
/** Assert follow counts per trail ID. */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAM7D,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,wCAAwC;IACxC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,kEAAkE;IAClE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,kDAAkD;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,KAAK,CAAC,GAAG,SAAS,CAAC;IACnE,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACxC,2CAA2C;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC3C,2CAA2C;IAC3C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAMD,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|