@ontrails/core 1.0.0-beta.12 → 1.0.0-beta.14
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 +65 -35
- package/README.md +21 -20
- package/dist/context.d.ts +1 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +5 -4
- package/dist/context.js.map +1 -1
- package/dist/derive.d.ts +14 -3
- package/dist/derive.d.ts.map +1 -1
- package/dist/derive.js +36 -12
- package/dist/derive.js.map +1 -1
- package/dist/draft.d.ts +28 -0
- package/dist/draft.d.ts.map +1 -0
- package/dist/draft.js +156 -0
- package/dist/draft.js.map +1 -0
- package/dist/event.d.ts +4 -41
- package/dist/event.d.ts.map +1 -1
- package/dist/event.js +4 -14
- package/dist/event.js.map +1 -1
- package/dist/execute.d.ts +10 -10
- package/dist/execute.d.ts.map +1 -1
- package/dist/execute.js +35 -28
- package/dist/execute.js.map +1 -1
- package/dist/gate.d.ts +17 -0
- package/dist/gate.d.ts.map +1 -0
- package/dist/gate.js +21 -0
- package/dist/gate.js.map +1 -0
- package/dist/index.d.ts +16 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/dist/internal/topo-saves.d.ts +47 -0
- package/dist/internal/topo-saves.d.ts.map +1 -0
- package/dist/internal/topo-saves.js +310 -0
- package/dist/internal/topo-saves.js.map +1 -0
- package/dist/internal/topo-store-read.d.ts +67 -0
- package/dist/internal/topo-store-read.d.ts.map +1 -0
- package/dist/internal/topo-store-read.js +222 -0
- package/dist/internal/topo-store-read.js.map +1 -0
- package/dist/internal/topo-store.d.ts +12 -0
- package/dist/internal/topo-store.d.ts.map +1 -0
- package/dist/internal/topo-store.js +571 -0
- package/dist/internal/topo-store.js.map +1 -0
- package/dist/internal/trails-db.d.ts +16 -0
- package/dist/internal/trails-db.d.ts.map +1 -0
- package/dist/internal/trails-db.js +118 -0
- package/dist/internal/trails-db.js.map +1 -0
- package/dist/layer.d.ts +5 -16
- package/dist/layer.d.ts.map +1 -1
- package/dist/layer.js +3 -20
- package/dist/layer.js.map +1 -1
- package/dist/provision-config.d.ts +22 -0
- package/dist/provision-config.d.ts.map +1 -0
- package/dist/provision-config.js +210 -0
- package/dist/provision-config.js.map +1 -0
- package/dist/provision.d.ts +71 -0
- package/dist/provision.d.ts.map +1 -0
- package/dist/provision.js +56 -0
- package/dist/provision.js.map +1 -0
- package/dist/run.d.ts +27 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +34 -0
- package/dist/run.js.map +1 -0
- package/dist/service-config.d.ts +7 -7
- package/dist/service-config.d.ts.map +1 -1
- package/dist/service-config.js +75 -73
- package/dist/service-config.js.map +1 -1
- package/dist/service.d.ts +32 -36
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +21 -21
- package/dist/service.js.map +1 -1
- package/dist/signal.d.ts +33 -0
- package/dist/signal.d.ts.map +1 -0
- package/dist/signal.js +17 -0
- package/dist/signal.js.map +1 -0
- package/dist/topo-store.d.ts +48 -0
- package/dist/topo-store.d.ts.map +1 -0
- package/dist/topo-store.js +175 -0
- package/dist/topo-store.js.map +1 -0
- package/dist/topo.d.ts +10 -10
- package/dist/topo.d.ts.map +1 -1
- package/dist/topo.js +48 -35
- package/dist/topo.js.map +1 -1
- package/dist/trail.d.ts +16 -16
- package/dist/trail.d.ts.map +1 -1
- package/dist/trail.js +5 -4
- package/dist/trail.js.map +1 -1
- package/dist/types.d.ts +10 -10
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -2
- package/dist/types.js.map +1 -1
- package/dist/validate-established-topo.d.ts +76 -0
- package/dist/validate-established-topo.d.ts.map +1 -0
- package/dist/validate-established-topo.js +43 -0
- package/dist/validate-established-topo.js.map +1 -0
- package/dist/validate-topo.d.ts +2 -2
- package/dist/validate-topo.d.ts.map +1 -1
- package/dist/validate-topo.js +34 -32
- package/dist/validate-topo.js.map +1 -1
- package/package.json +4 -1
- package/src/__tests__/context.test.ts +8 -8
- package/src/__tests__/derive.test.ts +58 -1
- package/src/__tests__/execute.test.ts +124 -122
- package/src/__tests__/{layer.test.ts → gate.test.ts} +26 -26
- package/src/__tests__/{dispatch.test.ts → run.test.ts} +39 -39
- package/src/__tests__/service-config.test.ts +41 -37
- package/src/__tests__/service.test.ts +71 -71
- package/src/__tests__/{event.test.ts → signal.test.ts} +15 -15
- package/src/__tests__/topo-store-read.test.ts +251 -0
- package/src/__tests__/topo-store.test.ts +469 -0
- package/src/__tests__/topo.test.ts +54 -54
- package/src/__tests__/trail-permit.test.ts +4 -4
- package/src/__tests__/trail.test.ts +58 -58
- package/src/__tests__/trails-db.test.ts +191 -0
- package/src/__tests__/type-utils.test.ts +3 -3
- package/src/__tests__/validate-topo.test.ts +205 -38
- package/src/context.ts +5 -4
- package/src/derive.ts +47 -16
- package/src/draft.ts +334 -0
- package/src/event.ts +11 -73
- package/src/execute.ts +56 -40
- package/src/{layer.ts → gate.ts} +13 -13
- package/src/index.ts +54 -23
- package/src/internal/topo-saves.ts +429 -0
- package/src/internal/topo-store-read.ts +473 -0
- package/src/internal/topo-store.ts +1087 -0
- package/src/internal/trails-db.ts +189 -0
- package/src/{service-config.ts → provision-config.ts} +124 -105
- package/src/provision.ts +148 -0
- package/src/{dispatch.ts → run.ts} +8 -8
- package/src/signal.ts +65 -0
- package/src/topo-store.ts +301 -0
- package/src/topo.ts +74 -52
- package/src/trail.ts +23 -22
- package/src/types.ts +11 -11
- package/src/validate-established-topo.ts +63 -0
- package/src/validate-topo.ts +38 -34
- package/tsconfig.tsbuildinfo +1 -1
- package/src/service.ts +0 -145
package/dist/types.d.ts
CHANGED
|
@@ -7,9 +7,9 @@ import type { Result } from './result.js';
|
|
|
7
7
|
*/
|
|
8
8
|
export type Implementation<I, O> = (input: I, ctx: TrailContext) => Result<O, Error> | Promise<Result<O, Error>>;
|
|
9
9
|
/** Invoke another trail by id — used for trail composition */
|
|
10
|
-
export type
|
|
11
|
-
/** Resolve a
|
|
12
|
-
export type
|
|
10
|
+
export type CrossFn = <O>(id: string, input: unknown) => Promise<Result<O, Error>>;
|
|
11
|
+
/** Resolve a provision instance from the current trail context. */
|
|
12
|
+
export type ProvisionLookup = <T = unknown>(provisionOrId: {
|
|
13
13
|
readonly id: string;
|
|
14
14
|
} | string) => T;
|
|
15
15
|
/** Callback for reporting progress from long-running trails */
|
|
@@ -33,8 +33,8 @@ export interface Logger {
|
|
|
33
33
|
fatal(message: string, data?: Record<string, unknown>): void;
|
|
34
34
|
child(context: Record<string, unknown>): Logger;
|
|
35
35
|
}
|
|
36
|
-
/** Context extension key for the invoking
|
|
37
|
-
export declare const
|
|
36
|
+
/** Context extension key for the invoking trailhead name. */
|
|
37
|
+
export declare const TRAILHEAD_KEY: "__trails_trailhead";
|
|
38
38
|
/** Minimal permit shape available on TrailContext. Permits extends this. */
|
|
39
39
|
export interface BasePermit {
|
|
40
40
|
readonly id: string;
|
|
@@ -43,8 +43,8 @@ export interface BasePermit {
|
|
|
43
43
|
/** Runtime context threaded through every trail execution */
|
|
44
44
|
export interface TrailContext {
|
|
45
45
|
readonly requestId: string;
|
|
46
|
-
readonly
|
|
47
|
-
readonly
|
|
46
|
+
readonly abortSignal: AbortSignal;
|
|
47
|
+
readonly cross?: CrossFn | undefined;
|
|
48
48
|
readonly permit?: BasePermit;
|
|
49
49
|
readonly workspaceRoot?: string | undefined;
|
|
50
50
|
readonly logger?: Logger | undefined;
|
|
@@ -52,7 +52,7 @@ export interface TrailContext {
|
|
|
52
52
|
readonly cwd?: string | undefined;
|
|
53
53
|
readonly env?: Record<string, string | undefined> | undefined;
|
|
54
54
|
readonly extensions?: Readonly<Record<string, unknown>> | undefined;
|
|
55
|
-
readonly
|
|
55
|
+
readonly provision?: ProvisionLookup | undefined;
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
58
|
* Permit requirement declared on a trail spec.
|
|
@@ -65,7 +65,7 @@ export type PermitRequirement = {
|
|
|
65
65
|
readonly scopes: readonly string[];
|
|
66
66
|
} | 'public';
|
|
67
67
|
/** Input shape used to seed a runtime TrailContext before resolution. */
|
|
68
|
-
export type TrailContextInit = Omit<TrailContext, '
|
|
69
|
-
readonly
|
|
68
|
+
export type TrailContextInit = Omit<TrailContext, 'provision'> & {
|
|
69
|
+
readonly provision?: ProvisionLookup | undefined;
|
|
70
70
|
};
|
|
71
71
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,EAAE,CAAC,IAAI,CACjC,KAAK,EAAE,CAAC,EACR,GAAG,EAAE,YAAY,KACd,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAElD,8DAA8D;AAC9D,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
/** Context extension key for the invoking
|
|
2
|
-
export const
|
|
1
|
+
/** Context extension key for the invoking trailhead name. */
|
|
2
|
+
export const TRAILHEAD_KEY = '__trails_trailhead';
|
|
3
3
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAgDA,
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAgDA,6DAA6D;AAC7D,MAAM,CAAC,MAAM,aAAa,GAAG,oBAA6B,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { ValidationError } from './errors.js';
|
|
2
|
+
import { Result } from './result.js';
|
|
3
|
+
import type { Topo } from './topo.js';
|
|
4
|
+
/**
|
|
5
|
+
* Validate that a topo is ready for established outputs.
|
|
6
|
+
*
|
|
7
|
+
* Established surfaces still require the authored graph to be structurally
|
|
8
|
+
* valid, and they must also reject any remaining draft state.
|
|
9
|
+
*/
|
|
10
|
+
export declare const validateEstablishedTopo: (topo: Topo) => {
|
|
11
|
+
readonly error: ValidationError;
|
|
12
|
+
isOk(): this is {
|
|
13
|
+
readonly value: never;
|
|
14
|
+
isOk(): this is /*elided*/ any;
|
|
15
|
+
isErr(): this is /*elided*/ any;
|
|
16
|
+
map<U>(fn: (value: never) => U): Result<U, ValidationError>;
|
|
17
|
+
flatMap<U, F = ValidationError>(fn: (value: never) => Result<U, F>): Result<U, ValidationError | F>;
|
|
18
|
+
mapErr<F>(_fn: (error: ValidationError) => F): Result<never, F>;
|
|
19
|
+
match<U>(handlers: {
|
|
20
|
+
ok: (value: never) => U;
|
|
21
|
+
err: (error: ValidationError) => U;
|
|
22
|
+
}): U;
|
|
23
|
+
unwrap(): never;
|
|
24
|
+
unwrapOr(_fallback: never): never;
|
|
25
|
+
};
|
|
26
|
+
isErr(): this is /*elided*/ any;
|
|
27
|
+
map<U>(_fn: (value: never) => U): Result<U, ValidationError>;
|
|
28
|
+
flatMap<U, F = ValidationError>(_fn: (value: never) => Result<U, F>): Result<U, ValidationError | F>;
|
|
29
|
+
mapErr<F>(fn: (error: ValidationError) => F): Result<never, F>;
|
|
30
|
+
match<U>(handlers: {
|
|
31
|
+
ok: (value: never) => U;
|
|
32
|
+
err: (error: ValidationError) => U;
|
|
33
|
+
}): U;
|
|
34
|
+
unwrap(): never;
|
|
35
|
+
unwrapOr<T>(fallback: T): T;
|
|
36
|
+
} | {
|
|
37
|
+
readonly value: void;
|
|
38
|
+
isOk(): this is /*elided*/ any;
|
|
39
|
+
isErr(): this is {
|
|
40
|
+
readonly error: never;
|
|
41
|
+
isOk(): this is {
|
|
42
|
+
readonly value: never;
|
|
43
|
+
isOk(): this is /*elided*/ any;
|
|
44
|
+
isErr(): this is /*elided*/ any;
|
|
45
|
+
map<U>(fn: (value: never) => U): Result<U, never>;
|
|
46
|
+
flatMap<U, F = never>(fn: (value: never) => Result<U, F>): Result<U, F>;
|
|
47
|
+
mapErr<F>(_fn: (error: never) => F): Result<never, F>;
|
|
48
|
+
match<U>(handlers: {
|
|
49
|
+
ok: (value: never) => U;
|
|
50
|
+
err: (error: never) => U;
|
|
51
|
+
}): U;
|
|
52
|
+
unwrap(): never;
|
|
53
|
+
unwrapOr(_fallback: never): never;
|
|
54
|
+
};
|
|
55
|
+
isErr(): this is /*elided*/ any;
|
|
56
|
+
map<U>(_fn: (value: never) => U): Result<U, never>;
|
|
57
|
+
flatMap<U, F = never>(_fn: (value: never) => Result<U, F>): Result<U, F>;
|
|
58
|
+
mapErr<F>(fn: (error: never) => F): Result<never, F>;
|
|
59
|
+
match<U>(handlers: {
|
|
60
|
+
ok: (value: never) => U;
|
|
61
|
+
err: (error: never) => U;
|
|
62
|
+
}): U;
|
|
63
|
+
unwrap(): never;
|
|
64
|
+
unwrapOr<T>(fallback: T): T;
|
|
65
|
+
};
|
|
66
|
+
map<U>(fn: (value: void) => U): Result<U, never>;
|
|
67
|
+
flatMap<U, F = never>(fn: (value: void) => Result<U, F>): Result<U, F>;
|
|
68
|
+
mapErr<F>(_fn: (error: never) => F): Result<void, F>;
|
|
69
|
+
match<U>(handlers: {
|
|
70
|
+
ok: (value: void) => U;
|
|
71
|
+
err: (error: never) => U;
|
|
72
|
+
}): U;
|
|
73
|
+
unwrap(): void;
|
|
74
|
+
unwrapOr(_fallback: void): void;
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=validate-established-topo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-established-topo.d.ts","sourceRoot":"","sources":["../src/validate-established-topo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AA0CtC;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYjD,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ValidationError } from './errors.js';
|
|
2
|
+
import { Result } from './result.js';
|
|
3
|
+
import { validateEstablishedTopo as validateDraftFreeTopo } from './draft.js';
|
|
4
|
+
import { validateTopo } from './validate-topo.js';
|
|
5
|
+
const PROJECTION_BLOCKING_RULES = new Set([
|
|
6
|
+
'cross-cycle',
|
|
7
|
+
'cross-exists',
|
|
8
|
+
'no-self-cross',
|
|
9
|
+
'provision-exists',
|
|
10
|
+
'signal-origin-exists',
|
|
11
|
+
]);
|
|
12
|
+
const keepProjectionBlockingIssues = (result) => {
|
|
13
|
+
if (result.isOk()) {
|
|
14
|
+
return result;
|
|
15
|
+
}
|
|
16
|
+
const issues = result.error.context?.issues;
|
|
17
|
+
const remainingIssues = issues?.filter((issue) => PROJECTION_BLOCKING_RULES.has(issue.rule));
|
|
18
|
+
if (remainingIssues === undefined || remainingIssues.length === 0) {
|
|
19
|
+
return Result.ok();
|
|
20
|
+
}
|
|
21
|
+
return Result.err(new ValidationError(`Topo validation failed with ${remainingIssues.length} issue(s)`, {
|
|
22
|
+
cause: result.error,
|
|
23
|
+
context: { issues: remainingIssues },
|
|
24
|
+
}));
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Validate that a topo is ready for established outputs.
|
|
28
|
+
*
|
|
29
|
+
* Established surfaces still require the authored graph to be structurally
|
|
30
|
+
* valid, and they must also reject any remaining draft state.
|
|
31
|
+
*/
|
|
32
|
+
export const validateEstablishedTopo = (topo) => {
|
|
33
|
+
const structural = keepProjectionBlockingIssues(validateTopo(topo));
|
|
34
|
+
if (structural.isErr()) {
|
|
35
|
+
return structural;
|
|
36
|
+
}
|
|
37
|
+
const established = validateDraftFreeTopo(topo);
|
|
38
|
+
if (established.isErr()) {
|
|
39
|
+
return established;
|
|
40
|
+
}
|
|
41
|
+
return Result.ok();
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=validate-established-topo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-established-topo.js","sourceRoot":"","sources":["../src/validate-established-topo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,uBAAuB,IAAI,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,yBAAyB,GAAG,IAAI,GAAG,CAAC;IACxC,aAAa;IACb,cAAc;IACd,eAAe;IACf,kBAAkB;IAClB,sBAAsB;CACvB,CAAC,CAAC;AAEH,MAAM,4BAA4B,GAAG,CACnC,MAAuC,EACvC,EAAE;IACF,IAAI,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QAClB,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,MAAM,GACV,MAAM,CAAC,KAAK,CAAC,OACd,EAAE,MAAM,CAAC;IACV,MAAM,eAAe,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAC/C,yBAAyB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAC1C,CAAC;IAEF,IAAI,eAAe,KAAK,SAAS,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClE,OAAO,MAAM,CAAC,EAAE,EAAE,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC,GAAG,CACf,IAAI,eAAe,CACjB,+BAA+B,eAAe,CAAC,MAAM,WAAW,EAChE;QACE,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,OAAO,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE;KACrC,CACF,CACF,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,IAAU,EAAE,EAAE;IACpD,MAAM,UAAU,GAAG,4BAA4B,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IACpE,IAAI,UAAU,CAAC,KAAK,EAAE,EAAE,CAAC;QACvB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,MAAM,WAAW,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAChD,IAAI,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC;QACxB,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC,EAAE,EAAE,CAAC;AACrB,CAAC,CAAC"}
|
package/dist/validate-topo.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Structural validation for a Topo graph.
|
|
3
3
|
*
|
|
4
|
-
* Checks trail
|
|
4
|
+
* Checks trail crossing references, example input validity, event origin
|
|
5
5
|
* references, and output schema completeness. Returns a Result with all
|
|
6
6
|
* issues collected into a single ValidationError.
|
|
7
7
|
*/
|
|
@@ -16,7 +16,7 @@ export interface TopoIssue {
|
|
|
16
16
|
/**
|
|
17
17
|
* Validate the structural integrity of a Topo graph.
|
|
18
18
|
*
|
|
19
|
-
* Checks
|
|
19
|
+
* Checks crossing references, example inputs, event origins, and output
|
|
20
20
|
* schema presence. Returns `Result.ok()` when no issues are found, or
|
|
21
21
|
* `Result.err(ValidationError)` with all issues in the error context.
|
|
22
22
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-topo.d.ts","sourceRoot":"","sources":["../src/validate-topo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"validate-topo.d.ts","sourceRoot":"","sources":["../src/validate-topo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAQtC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAyLD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,IAAI,KAAG,MAAM,CAAC,IAAI,EAAE,eAAe,CAoBrE,CAAC"}
|
package/dist/validate-topo.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Structural validation for a Topo graph.
|
|
3
3
|
*
|
|
4
|
-
* Checks trail
|
|
4
|
+
* Checks trail crossing references, example input validity, event origin
|
|
5
5
|
* references, and output schema completeness. Returns a Result with all
|
|
6
6
|
* issues collected into a single ValidationError.
|
|
7
7
|
*/
|
|
8
8
|
import { ValidationError } from './errors.js';
|
|
9
|
+
import { isDraftId } from './draft.js';
|
|
9
10
|
import { Result } from './result.js';
|
|
10
11
|
import { validateInput } from './validation.js';
|
|
11
12
|
// ---------------------------------------------------------------------------
|
|
@@ -14,12 +15,12 @@ import { validateInput } from './validation.js';
|
|
|
14
15
|
const WHITE = 0;
|
|
15
16
|
const GRAY = 1;
|
|
16
17
|
const BLACK = 2;
|
|
17
|
-
/** Build an adjacency list and initial color map from trails with
|
|
18
|
-
const
|
|
18
|
+
/** Build an adjacency list and initial color map from trails with crossings. */
|
|
19
|
+
const buildCrossGraph = (trails) => {
|
|
19
20
|
const graph = new Map();
|
|
20
21
|
for (const [id, t] of trails) {
|
|
21
|
-
if (t.
|
|
22
|
-
graph.set(id, t.
|
|
22
|
+
if (t.crosses.length > 0) {
|
|
23
|
+
graph.set(id, t.crosses);
|
|
23
24
|
}
|
|
24
25
|
}
|
|
25
26
|
const color = new Map();
|
|
@@ -28,10 +29,10 @@ const buildFollowGraph = (trails) => {
|
|
|
28
29
|
}
|
|
29
30
|
return { color, graph };
|
|
30
31
|
};
|
|
31
|
-
/** Detect multi-node cycles in the trail
|
|
32
|
-
const
|
|
32
|
+
/** Detect multi-node cycles in the trail crossing graph via DFS. */
|
|
33
|
+
const detectCrossCycles = (trails) => {
|
|
33
34
|
const issues = [];
|
|
34
|
-
const { color, graph } =
|
|
35
|
+
const { color, graph } = buildCrossGraph(trails);
|
|
35
36
|
const dfs = (node, path) => {
|
|
36
37
|
color.set(node, GRAY);
|
|
37
38
|
for (const next of graph.get(node) ?? []) {
|
|
@@ -43,7 +44,7 @@ const detectFollowCycles = (trails) => {
|
|
|
43
44
|
const cycle = [...path.slice(path.indexOf(next)), next];
|
|
44
45
|
issues.push({
|
|
45
46
|
message: `Cycle detected: ${cycle.join(' → ')}`,
|
|
46
|
-
rule: '
|
|
47
|
+
rule: 'cross-cycle',
|
|
47
48
|
trailId: next,
|
|
48
49
|
});
|
|
49
50
|
}
|
|
@@ -60,37 +61,38 @@ const detectFollowCycles = (trails) => {
|
|
|
60
61
|
}
|
|
61
62
|
return issues;
|
|
62
63
|
};
|
|
63
|
-
const
|
|
64
|
+
const checkCrosses = (trails, topo) => {
|
|
64
65
|
const issues = [];
|
|
65
66
|
for (const [id, trail] of trails) {
|
|
66
|
-
for (const
|
|
67
|
-
if (
|
|
67
|
+
for (const crossedId of trail.crosses) {
|
|
68
|
+
if (crossedId === id) {
|
|
68
69
|
issues.push({
|
|
69
|
-
message: `Trail
|
|
70
|
-
rule: 'no-self-
|
|
70
|
+
message: `Trail crosses itself`,
|
|
71
|
+
rule: 'no-self-cross',
|
|
71
72
|
trailId: id,
|
|
72
73
|
});
|
|
73
74
|
}
|
|
74
|
-
else if (!topo.has(
|
|
75
|
+
else if (!topo.has(crossedId) && !isDraftId(crossedId)) {
|
|
75
76
|
issues.push({
|
|
76
|
-
message: `
|
|
77
|
-
rule: '
|
|
77
|
+
message: `Crosses "${crossedId}" which is not in the topo`,
|
|
78
|
+
rule: 'cross-exists',
|
|
78
79
|
trailId: id,
|
|
79
80
|
});
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
|
-
issues.push(...
|
|
84
|
+
issues.push(...detectCrossCycles(trails));
|
|
84
85
|
return issues;
|
|
85
86
|
};
|
|
86
|
-
const
|
|
87
|
+
const checkProvisions = (trails, topo) => {
|
|
87
88
|
const issues = [];
|
|
88
89
|
for (const [id, trail] of trails) {
|
|
89
|
-
for (const
|
|
90
|
-
if (!topo.
|
|
90
|
+
for (const declaredProvision of trail.provisions) {
|
|
91
|
+
if (!topo.hasProvision(declaredProvision.id) &&
|
|
92
|
+
!isDraftId(declaredProvision.id)) {
|
|
91
93
|
issues.push({
|
|
92
|
-
message: `
|
|
93
|
-
rule: '
|
|
94
|
+
message: `Provision "${declaredProvision.id}" is not in the topo`,
|
|
95
|
+
rule: 'provision-exists',
|
|
94
96
|
trailId: id,
|
|
95
97
|
});
|
|
96
98
|
}
|
|
@@ -129,17 +131,17 @@ const checkExamples = (trails) => {
|
|
|
129
131
|
}
|
|
130
132
|
return issues;
|
|
131
133
|
};
|
|
132
|
-
const
|
|
134
|
+
const checkSignalOrigins = (signals, topo) => {
|
|
133
135
|
const issues = [];
|
|
134
|
-
for (const [id, evt] of
|
|
136
|
+
for (const [id, evt] of signals) {
|
|
135
137
|
if (!evt.from) {
|
|
136
138
|
continue;
|
|
137
139
|
}
|
|
138
140
|
for (const originId of evt.from) {
|
|
139
|
-
if (!topo.has(originId)) {
|
|
141
|
+
if (!topo.has(originId) && !isDraftId(originId)) {
|
|
140
142
|
issues.push({
|
|
141
|
-
message: `
|
|
142
|
-
rule: '
|
|
143
|
+
message: `Signal origin "${originId}" is not in the topo`,
|
|
144
|
+
rule: 'signal-origin-exists',
|
|
143
145
|
trailId: id,
|
|
144
146
|
});
|
|
145
147
|
}
|
|
@@ -153,16 +155,16 @@ const checkEventOrigins = (events, topo) => {
|
|
|
153
155
|
/**
|
|
154
156
|
* Validate the structural integrity of a Topo graph.
|
|
155
157
|
*
|
|
156
|
-
* Checks
|
|
158
|
+
* Checks crossing references, example inputs, event origins, and output
|
|
157
159
|
* schema presence. Returns `Result.ok()` when no issues are found, or
|
|
158
160
|
* `Result.err(ValidationError)` with all issues in the error context.
|
|
159
161
|
*/
|
|
160
162
|
export const validateTopo = (topo) => {
|
|
161
163
|
const issues = [
|
|
162
|
-
...
|
|
163
|
-
...
|
|
164
|
+
...checkCrosses(topo.trails, topo),
|
|
165
|
+
...checkProvisions(topo.trails, topo),
|
|
164
166
|
...checkExamples(topo.trails),
|
|
165
|
-
...
|
|
167
|
+
...checkSignalOrigins(topo.signals, topo),
|
|
166
168
|
];
|
|
167
169
|
if (issues.length === 0) {
|
|
168
170
|
return Result.ok();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-topo.js","sourceRoot":"","sources":["../src/validate-topo.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"validate-topo.js","sourceRoot":"","sources":["../src/validate-topo.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/core",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./src/index.ts",
|
|
7
|
+
"./internal/topo-saves": "./src/internal/topo-saves.ts",
|
|
8
|
+
"./internal/topo-store": "./src/internal/topo-store.ts",
|
|
9
|
+
"./internal/trails-db": "./src/internal/trails-db.ts",
|
|
7
10
|
"./patterns": "./src/patterns/index.ts",
|
|
8
11
|
"./redaction": "./src/redaction/index.ts",
|
|
9
12
|
"./package.json": "./package.json"
|
|
@@ -23,10 +23,10 @@ describe('createTrailContext', () => {
|
|
|
23
23
|
expect(ctx.env).toBe(process.env);
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
test('provides a non-aborted
|
|
26
|
+
test('provides a non-aborted abortSignal by default', () => {
|
|
27
27
|
const ctx = createTrailContext();
|
|
28
|
-
expect(ctx.
|
|
29
|
-
expect(ctx.
|
|
28
|
+
expect(ctx.abortSignal).toBeInstanceOf(AbortSignal);
|
|
29
|
+
expect(ctx.abortSignal.aborted).toBe(false);
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
test('override values take precedence', () => {
|
|
@@ -34,17 +34,17 @@ describe('createTrailContext', () => {
|
|
|
34
34
|
ac.abort();
|
|
35
35
|
|
|
36
36
|
const ctx = createTrailContext({
|
|
37
|
+
abortSignal: ac.signal,
|
|
37
38
|
cwd: '/custom/dir',
|
|
38
39
|
env: { CUSTOM: 'yes' },
|
|
39
40
|
requestId: 'custom-id',
|
|
40
|
-
signal: ac.signal,
|
|
41
41
|
workspaceRoot: '/tmp',
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
expect(ctx.cwd).toBe('/custom/dir');
|
|
45
45
|
expect(ctx.env).toEqual({ CUSTOM: 'yes' });
|
|
46
46
|
expect(ctx.requestId).toBe('custom-id');
|
|
47
|
-
expect(ctx.
|
|
47
|
+
expect(ctx.abortSignal.aborted).toBe(true);
|
|
48
48
|
expect(ctx.workspaceRoot).toBe('/tmp');
|
|
49
49
|
});
|
|
50
50
|
|
|
@@ -57,14 +57,14 @@ describe('createTrailContext', () => {
|
|
|
57
57
|
expect(ctx.extensions?.['nested']).toEqual({ key: 'value' });
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
test('provides a
|
|
60
|
+
test('provides a provision accessor backed by extensions', () => {
|
|
61
61
|
const widget = { id: 'widget-1' };
|
|
62
62
|
const ctx = createTrailContext({
|
|
63
63
|
extensions: { 'widget.main': widget },
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
expect(ctx.
|
|
67
|
-
expect(ctx.
|
|
66
|
+
expect(ctx.provision('widget.main')).toBe(widget);
|
|
67
|
+
expect(ctx.provision<{ id: string }>({ id: 'widget.main' }).id).toBe(
|
|
68
68
|
'widget-1'
|
|
69
69
|
);
|
|
70
70
|
});
|
|
@@ -2,13 +2,45 @@ import { describe, test, expect } from 'bun:test';
|
|
|
2
2
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
|
-
import { deriveFields } from '../derive.js';
|
|
5
|
+
import { deriveCliPath, deriveFields } from '../derive.js';
|
|
6
6
|
|
|
7
7
|
// ---------------------------------------------------------------------------
|
|
8
8
|
// Tests
|
|
9
9
|
// ---------------------------------------------------------------------------
|
|
10
10
|
|
|
11
11
|
describe('derive', () => {
|
|
12
|
+
describe('cli paths', () => {
|
|
13
|
+
test('top-level trail IDs derive to a one-segment CLI path', () => {
|
|
14
|
+
expect(deriveCliPath('search')).toEqual(['search']);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('multi-dot trail IDs derive to the full ordered CLI path', () => {
|
|
18
|
+
expect(deriveCliPath('topo.pin.remove')).toEqual([
|
|
19
|
+
'topo',
|
|
20
|
+
'pin',
|
|
21
|
+
'remove',
|
|
22
|
+
]);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('trail IDs with consecutive dots throw a ValidationError', () => {
|
|
26
|
+
expect(() => deriveCliPath('topo..pin')).toThrow(
|
|
27
|
+
'Trail ID "topo..pin" contains an empty segment'
|
|
28
|
+
);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('trail IDs with a leading dot throw a ValidationError', () => {
|
|
32
|
+
expect(() => deriveCliPath('.pin')).toThrow(
|
|
33
|
+
'Trail ID ".pin" contains an empty segment'
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('trail IDs with a trailing dot throw a ValidationError', () => {
|
|
38
|
+
expect(() => deriveCliPath('pin.')).toThrow(
|
|
39
|
+
'Trail ID "pin." contains an empty segment'
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
12
44
|
describe('primitive types', () => {
|
|
13
45
|
test('z.string() derives string field', () => {
|
|
14
46
|
const schema = z.object({ name: z.string() });
|
|
@@ -119,6 +151,31 @@ describe('derive', () => {
|
|
|
119
151
|
expect(fields[0]?.type).toBe('string[]');
|
|
120
152
|
expect(fields[0]?.default).toEqual(['a', 'b']);
|
|
121
153
|
});
|
|
154
|
+
|
|
155
|
+
test('z.array(z.object(...)) is omitted when it cannot be represented faithfully', () => {
|
|
156
|
+
const schema = z.object({
|
|
157
|
+
files: z.array(
|
|
158
|
+
z.object({
|
|
159
|
+
content: z.string(),
|
|
160
|
+
filename: z.string(),
|
|
161
|
+
})
|
|
162
|
+
),
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
expect(deriveFields(schema)).toEqual([]);
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('unsupported shapes', () => {
|
|
170
|
+
test('nested objects are omitted when they cannot be represented faithfully', () => {
|
|
171
|
+
const schema = z.object({
|
|
172
|
+
filter: z.object({
|
|
173
|
+
query: z.string(),
|
|
174
|
+
}),
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
expect(deriveFields(schema)).toEqual([]);
|
|
178
|
+
});
|
|
122
179
|
});
|
|
123
180
|
|
|
124
181
|
describe('modifiers', () => {
|