@ontrails/core 1.0.0-beta.15 → 1.0.0-beta.17
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/CHANGELOG.md +69 -0
- package/README.md +64 -19
- package/package.json +9 -8
- package/src/activation-provenance.ts +111 -0
- package/src/activation-source-compatibility.ts +430 -0
- package/src/activation-source-projection.ts +221 -0
- package/src/activation-source.ts +91 -0
- package/src/blob-ref.ts +51 -0
- package/src/context.ts +4 -0
- package/src/{internal/cross-batch.ts → cross-batch.ts} +3 -11
- package/src/detours.ts +8 -0
- package/src/draft.ts +4 -0
- package/src/error-projection.ts +51 -0
- package/src/errors.ts +192 -39
- package/src/execute.ts +443 -44
- package/src/fire.ts +965 -91
- package/src/index.ts +285 -38
- package/src/layer-projection.ts +192 -0
- package/src/layer.ts +32 -1
- package/src/observe.ts +361 -0
- package/src/permits.ts +12 -0
- package/src/redaction/patterns.ts +6 -3
- package/src/resilience.ts +8 -8
- package/src/resource-config.ts +477 -44
- package/src/resource.ts +21 -1
- package/src/result.ts +18 -0
- package/src/run.ts +2 -2
- package/src/schedule-runtime.ts +689 -0
- package/src/schedule.ts +324 -0
- package/src/serialization.ts +90 -57
- package/src/signal-diagnostics.ts +633 -0
- package/src/{internal/signal-ref.ts → signal-ref.ts} +1 -1
- package/src/signal.ts +37 -0
- package/src/store/accessor-protocol.ts +5 -5
- package/src/structured-examples.ts +245 -0
- package/src/surface-derivation.ts +91 -0
- package/src/surface-filter.ts +7 -13
- package/src/topo.ts +386 -6
- package/src/tracing.ts +345 -0
- package/src/trail.ts +168 -22
- package/src/trails/derive-trail.ts +1 -1
- package/src/trails/ingest.ts +7 -15
- package/src/{internal/trails-db.ts → trails-db.ts} +42 -21
- package/src/transport-error-map.ts +146 -28
- package/src/types.ts +82 -28
- package/src/validate-established-topo.ts +6 -0
- package/src/validate-topo.ts +212 -5
- package/src/validation.ts +58 -1
- package/src/webhook.ts +276 -0
- package/src/{internal/zod-wrappers.ts → zod-wrappers.ts} +0 -6
- package/.turbo/turbo-build.log +0 -1
- package/.turbo/turbo-lint.log +0 -3
- package/.turbo/turbo-typecheck.log +0 -1
- package/dist/blob-ref.d.ts +0 -20
- package/dist/blob-ref.d.ts.map +0 -1
- package/dist/blob-ref.js +0 -22
- package/dist/blob-ref.js.map +0 -1
- package/dist/branded.d.ts +0 -36
- package/dist/branded.d.ts.map +0 -1
- package/dist/branded.js +0 -89
- package/dist/branded.js.map +0 -1
- package/dist/collections.d.ts +0 -31
- package/dist/collections.d.ts.map +0 -1
- package/dist/collections.js +0 -60
- package/dist/collections.js.map +0 -1
- package/dist/context.d.ts +0 -22
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -37
- package/dist/context.js.map +0 -1
- package/dist/contour.d.ts +0 -81
- package/dist/contour.d.ts.map +0 -1
- package/dist/contour.js +0 -176
- package/dist/contour.js.map +0 -1
- package/dist/cross-schema.d.ts +0 -18
- package/dist/cross-schema.d.ts.map +0 -1
- package/dist/cross-schema.js +0 -29
- package/dist/cross-schema.js.map +0 -1
- package/dist/derive.d.ts +0 -44
- package/dist/derive.d.ts.map +0 -1
- package/dist/derive.js +0 -149
- package/dist/derive.js.map +0 -1
- package/dist/draft.d.ts +0 -28
- package/dist/draft.d.ts.map +0 -1
- package/dist/draft.js +0 -157
- package/dist/draft.js.map +0 -1
- package/dist/errors.d.ts +0 -141
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -185
- package/dist/errors.js.map +0 -1
- package/dist/execute.d.ts +0 -52
- package/dist/execute.d.ts.map +0 -1
- package/dist/execute.js +0 -511
- package/dist/execute.js.map +0 -1
- package/dist/fetch.d.ts +0 -15
- package/dist/fetch.d.ts.map +0 -1
- package/dist/fetch.js +0 -102
- package/dist/fetch.js.map +0 -1
- package/dist/fire.d.ts +0 -43
- package/dist/fire.d.ts.map +0 -1
- package/dist/fire.js +0 -185
- package/dist/fire.js.map +0 -1
- package/dist/guards.d.ts +0 -17
- package/dist/guards.d.ts.map +0 -1
- package/dist/guards.js +0 -25
- package/dist/guards.js.map +0 -1
- package/dist/index.d.ts +0 -59
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -61
- package/dist/index.js.map +0 -1
- package/dist/internal/cross-batch.d.ts +0 -44
- package/dist/internal/cross-batch.d.ts.map +0 -1
- package/dist/internal/cross-batch.js +0 -58
- package/dist/internal/cross-batch.js.map +0 -1
- package/dist/internal/fork-ctx.d.ts +0 -41
- package/dist/internal/fork-ctx.d.ts.map +0 -1
- package/dist/internal/fork-ctx.js +0 -47
- package/dist/internal/fork-ctx.js.map +0 -1
- package/dist/internal/signal-ref.d.ts +0 -15
- package/dist/internal/signal-ref.d.ts.map +0 -1
- package/dist/internal/signal-ref.js +0 -41
- package/dist/internal/signal-ref.js.map +0 -1
- package/dist/internal/topo-saves.d.ts +0 -53
- package/dist/internal/topo-saves.d.ts.map +0 -1
- package/dist/internal/topo-saves.js +0 -449
- package/dist/internal/topo-saves.js.map +0 -1
- package/dist/internal/topo-snapshots.d.ts +0 -57
- package/dist/internal/topo-snapshots.d.ts.map +0 -1
- package/dist/internal/topo-snapshots.js +0 -372
- package/dist/internal/topo-snapshots.js.map +0 -1
- package/dist/internal/topo-store-read.d.ts +0 -70
- package/dist/internal/topo-store-read.d.ts.map +0 -1
- package/dist/internal/topo-store-read.js +0 -221
- package/dist/internal/topo-store-read.js.map +0 -1
- package/dist/internal/topo-store.d.ts +0 -26
- package/dist/internal/topo-store.d.ts.map +0 -1
- package/dist/internal/topo-store.js +0 -621
- package/dist/internal/topo-store.js.map +0 -1
- package/dist/internal/tracing.d.ts +0 -98
- package/dist/internal/tracing.d.ts.map +0 -1
- package/dist/internal/tracing.js +0 -102
- package/dist/internal/tracing.js.map +0 -1
- package/dist/internal/trails-db.d.ts +0 -16
- package/dist/internal/trails-db.d.ts.map +0 -1
- package/dist/internal/trails-db.js +0 -118
- package/dist/internal/trails-db.js.map +0 -1
- package/dist/internal/zod-wrappers.d.ts +0 -40
- package/dist/internal/zod-wrappers.d.ts.map +0 -1
- package/dist/internal/zod-wrappers.js +0 -59
- package/dist/internal/zod-wrappers.js.map +0 -1
- package/dist/layer.d.ts +0 -23
- package/dist/layer.d.ts.map +0 -1
- package/dist/layer.js +0 -21
- package/dist/layer.js.map +0 -1
- package/dist/path-security.d.ts +0 -28
- package/dist/path-security.d.ts.map +0 -1
- package/dist/path-security.js +0 -63
- package/dist/path-security.js.map +0 -1
- package/dist/patterns/bulk.d.ts +0 -15
- package/dist/patterns/bulk.d.ts.map +0 -1
- package/dist/patterns/bulk.js +0 -14
- package/dist/patterns/bulk.js.map +0 -1
- package/dist/patterns/change.d.ts +0 -10
- package/dist/patterns/change.d.ts.map +0 -1
- package/dist/patterns/change.js +0 -10
- package/dist/patterns/change.js.map +0 -1
- package/dist/patterns/date-range.d.ts +0 -10
- package/dist/patterns/date-range.d.ts.map +0 -1
- package/dist/patterns/date-range.js +0 -10
- package/dist/patterns/date-range.js.map +0 -1
- package/dist/patterns/index.d.ts +0 -9
- package/dist/patterns/index.d.ts.map +0 -1
- package/dist/patterns/index.js +0 -9
- package/dist/patterns/index.js.map +0 -1
- package/dist/patterns/pagination.d.ts +0 -18
- package/dist/patterns/pagination.d.ts.map +0 -1
- package/dist/patterns/pagination.js +0 -18
- package/dist/patterns/pagination.js.map +0 -1
- package/dist/patterns/progress.d.ts +0 -11
- package/dist/patterns/progress.d.ts.map +0 -1
- package/dist/patterns/progress.js +0 -11
- package/dist/patterns/progress.js.map +0 -1
- package/dist/patterns/sorting.d.ts +0 -13
- package/dist/patterns/sorting.d.ts.map +0 -1
- package/dist/patterns/sorting.js +0 -10
- package/dist/patterns/sorting.js.map +0 -1
- package/dist/patterns/status.d.ts +0 -15
- package/dist/patterns/status.d.ts.map +0 -1
- package/dist/patterns/status.js +0 -9
- package/dist/patterns/status.js.map +0 -1
- package/dist/patterns/timestamps.d.ts +0 -10
- package/dist/patterns/timestamps.d.ts.map +0 -1
- package/dist/patterns/timestamps.js +0 -10
- package/dist/patterns/timestamps.js.map +0 -1
- package/dist/redaction/index.d.ts +0 -4
- package/dist/redaction/index.d.ts.map +0 -1
- package/dist/redaction/index.js +0 -3
- package/dist/redaction/index.js.map +0 -1
- package/dist/redaction/patterns.d.ts +0 -9
- package/dist/redaction/patterns.d.ts.map +0 -1
- package/dist/redaction/patterns.js +0 -39
- package/dist/redaction/patterns.js.map +0 -1
- package/dist/redaction/redactor.d.ts +0 -27
- package/dist/redaction/redactor.d.ts.map +0 -1
- package/dist/redaction/redactor.js +0 -89
- package/dist/redaction/redactor.js.map +0 -1
- package/dist/resilience.d.ts +0 -34
- package/dist/resilience.d.ts.map +0 -1
- package/dist/resilience.js +0 -164
- package/dist/resilience.js.map +0 -1
- package/dist/resource-config.d.ts +0 -22
- package/dist/resource-config.d.ts.map +0 -1
- package/dist/resource-config.js +0 -210
- package/dist/resource-config.js.map +0 -1
- package/dist/resource.d.ts +0 -74
- package/dist/resource.d.ts.map +0 -1
- package/dist/resource.js +0 -61
- package/dist/resource.js.map +0 -1
- package/dist/result.d.ts +0 -57
- package/dist/result.d.ts.map +0 -1
- package/dist/result.js +0 -156
- package/dist/result.js.map +0 -1
- package/dist/run.d.ts +0 -28
- package/dist/run.d.ts.map +0 -1
- package/dist/run.js +0 -35
- package/dist/run.js.map +0 -1
- package/dist/serialization.d.ts +0 -27
- package/dist/serialization.d.ts.map +0 -1
- package/dist/serialization.js +0 -154
- package/dist/serialization.js.map +0 -1
- package/dist/signal.d.ts +0 -33
- package/dist/signal.d.ts.map +0 -1
- package/dist/signal.js +0 -17
- package/dist/signal.js.map +0 -1
- package/dist/store/accessor-protocol.d.ts +0 -51
- package/dist/store/accessor-protocol.d.ts.map +0 -1
- package/dist/store/accessor-protocol.js +0 -2
- package/dist/store/accessor-protocol.js.map +0 -1
- package/dist/store/index.d.ts +0 -2
- package/dist/store/index.d.ts.map +0 -1
- package/dist/store/index.js +0 -2
- package/dist/store/index.js.map +0 -1
- package/dist/surface-filter.d.ts +0 -13
- package/dist/surface-filter.d.ts.map +0 -1
- package/dist/surface-filter.js +0 -76
- package/dist/surface-filter.js.map +0 -1
- package/dist/topo-store.d.ts +0 -62
- package/dist/topo-store.d.ts.map +0 -1
- package/dist/topo-store.js +0 -319
- package/dist/topo-store.js.map +0 -1
- package/dist/topo.d.ts +0 -39
- package/dist/topo.d.ts.map +0 -1
- package/dist/topo.js +0 -241
- package/dist/topo.js.map +0 -1
- package/dist/trail.d.ts +0 -163
- package/dist/trail.d.ts.map +0 -1
- package/dist/trail.js +0 -75
- package/dist/trail.js.map +0 -1
- package/dist/trails/derive-trail.d.ts +0 -66
- package/dist/trails/derive-trail.d.ts.map +0 -1
- package/dist/trails/derive-trail.js +0 -378
- package/dist/trails/derive-trail.js.map +0 -1
- package/dist/trails/index.d.ts +0 -5
- package/dist/trails/index.d.ts.map +0 -1
- package/dist/trails/index.js +0 -3
- package/dist/trails/index.js.map +0 -1
- package/dist/trails/ingest.d.ts +0 -24
- package/dist/trails/ingest.d.ts.map +0 -1
- package/dist/trails/ingest.js +0 -63
- package/dist/trails/ingest.js.map +0 -1
- package/dist/transport-error-map.d.ts +0 -106
- package/dist/transport-error-map.d.ts.map +0 -1
- package/dist/transport-error-map.js +0 -24
- package/dist/transport-error-map.js.map +0 -1
- package/dist/type-checks.test-d.d.ts +0 -71
- package/dist/type-checks.test-d.d.ts.map +0 -1
- package/dist/type-checks.test-d.js +0 -12
- package/dist/type-checks.test-d.js.map +0 -1
- package/dist/type-utils.d.ts +0 -33
- package/dist/type-utils.d.ts.map +0 -1
- package/dist/type-utils.js +0 -12
- package/dist/type-utils.js.map +0 -1
- package/dist/types.d.ts +0 -177
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/validate-established-topo.d.ts +0 -76
- package/dist/validate-established-topo.d.ts.map +0 -1
- package/dist/validate-established-topo.js +0 -43
- package/dist/validate-established-topo.js.map +0 -1
- package/dist/validate-topo.d.ts +0 -24
- package/dist/validate-topo.d.ts.map +0 -1
- package/dist/validate-topo.js +0 -193
- package/dist/validate-topo.js.map +0 -1
- package/dist/validation.d.ts +0 -27
- package/dist/validation.d.ts.map +0 -1
- package/dist/validation.js +0 -165
- package/dist/validation.js.map +0 -1
- package/dist/workspace.d.ts +0 -25
- package/dist/workspace.d.ts.map +0 -1
- package/dist/workspace.js +0 -57
- package/dist/workspace.js.map +0 -1
- package/src/__tests__/blob-ref.test.ts +0 -103
- package/src/__tests__/branded.test.ts +0 -148
- package/src/__tests__/collections.test.ts +0 -126
- package/src/__tests__/context.test.ts +0 -77
- package/src/__tests__/contour.test.ts +0 -263
- package/src/__tests__/derive-trail.test.ts +0 -668
- package/src/__tests__/derive.test.ts +0 -260
- package/src/__tests__/errors.test.ts +0 -427
- package/src/__tests__/execute.test.ts +0 -1563
- package/src/__tests__/fetch.test.ts +0 -217
- package/src/__tests__/fire.test.ts +0 -1056
- package/src/__tests__/fork-ctx.test.ts +0 -83
- package/src/__tests__/guards.test.ts +0 -102
- package/src/__tests__/ingest.test.ts +0 -191
- package/src/__tests__/layer.test.ts +0 -125
- package/src/__tests__/path-security.test.ts +0 -114
- package/src/__tests__/patterns.test.ts +0 -273
- package/src/__tests__/redaction.test.ts +0 -244
- package/src/__tests__/resilience.test.ts +0 -246
- package/src/__tests__/resource.test.ts +0 -204
- package/src/__tests__/result.test.ts +0 -155
- package/src/__tests__/run.test.ts +0 -181
- package/src/__tests__/serialization.test.ts +0 -401
- package/src/__tests__/service-config.test.ts +0 -224
- package/src/__tests__/signal.test.ts +0 -82
- package/src/__tests__/surface-filter.test.ts +0 -196
- package/src/__tests__/topo-store-read.test.ts +0 -256
- package/src/__tests__/topo-store.test.ts +0 -869
- package/src/__tests__/topo.test.ts +0 -573
- package/src/__tests__/trail-permit.test.ts +0 -60
- package/src/__tests__/trail.test.ts +0 -426
- package/src/__tests__/trails-db.test.ts +0 -198
- package/src/__tests__/transport-error-map.test.ts +0 -82
- package/src/__tests__/type-utils.test.ts +0 -118
- package/src/__tests__/validate-topo.test.ts +0 -611
- package/src/__tests__/validation.test.ts +0 -336
- package/src/__tests__/workspace.test.ts +0 -183
- package/src/__tests__/zod-wrappers.test.ts +0 -62
- package/src/internal/topo-snapshots.ts +0 -517
- package/src/internal/topo-store-read.ts +0 -481
- package/src/internal/topo-store.ts +0 -1192
- package/src/internal/tracing.ts +0 -187
- package/src/topo-store.ts +0 -510
- package/src/type-checks.test-d.ts +0 -106
- package/tsconfig.json +0 -9
- package/tsconfig.tests.json +0 -10
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
import type { AnySignal } from './signal.js';
|
|
4
|
+
|
|
5
|
+
export const activationSourceKinds = Object.freeze([
|
|
6
|
+
'signal',
|
|
7
|
+
'schedule',
|
|
8
|
+
'webhook',
|
|
9
|
+
] as const);
|
|
10
|
+
|
|
11
|
+
export type BuiltinActivationSourceKind =
|
|
12
|
+
(typeof activationSourceKinds)[number];
|
|
13
|
+
|
|
14
|
+
export type ActivationSourceKind = string;
|
|
15
|
+
|
|
16
|
+
export type ActivationSourceMeta = Readonly<Record<string, unknown>>;
|
|
17
|
+
|
|
18
|
+
export type ActivationSourceParse<TPayload = unknown> =
|
|
19
|
+
| z.ZodType<TPayload>
|
|
20
|
+
| {
|
|
21
|
+
readonly output?: z.ZodType<TPayload> | undefined;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export interface ActivationSource {
|
|
25
|
+
readonly id: string;
|
|
26
|
+
readonly kind: ActivationSourceKind;
|
|
27
|
+
readonly cron?: string | undefined;
|
|
28
|
+
readonly input?: unknown;
|
|
29
|
+
readonly meta?: ActivationSourceMeta | undefined;
|
|
30
|
+
readonly method?: string | undefined;
|
|
31
|
+
readonly parse?: ActivationSourceParse | undefined;
|
|
32
|
+
readonly path?: string | undefined;
|
|
33
|
+
readonly payload?: z.ZodType<unknown> | undefined;
|
|
34
|
+
readonly timezone?: string | undefined;
|
|
35
|
+
readonly verify?: unknown;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ActivationWhereExample {
|
|
39
|
+
readonly input?: unknown;
|
|
40
|
+
readonly on: boolean;
|
|
41
|
+
readonly payload?: unknown;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* oxlint-disable no-explicit-any -- contextual predicate authoring needs source-specific payload inference; unknown would make inline predicates unusable until a helper API exists. */
|
|
45
|
+
export type ActivationWherePredicate<TPayload = any> = (
|
|
46
|
+
payload: TPayload
|
|
47
|
+
) => boolean | Promise<boolean>;
|
|
48
|
+
|
|
49
|
+
export interface ActivationWhere<TPayload = any> {
|
|
50
|
+
readonly examples?: readonly ActivationWhereExample[] | undefined;
|
|
51
|
+
readonly predicate: ActivationWherePredicate<TPayload>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type ActivationWhereSpec<TPayload = any> =
|
|
55
|
+
| ActivationWhere<TPayload>
|
|
56
|
+
| ActivationWherePredicate<TPayload>;
|
|
57
|
+
|
|
58
|
+
export type ActivationSourceRef = string | AnySignal | ActivationSource;
|
|
59
|
+
|
|
60
|
+
export interface ActivationEntrySpec {
|
|
61
|
+
readonly source: ActivationSourceRef;
|
|
62
|
+
readonly meta?: ActivationSourceMeta | undefined;
|
|
63
|
+
readonly where?: ActivationWhereSpec | undefined;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface ActivationEntry {
|
|
67
|
+
readonly source: ActivationSource;
|
|
68
|
+
readonly meta?: ActivationSourceMeta | undefined;
|
|
69
|
+
readonly where?: ActivationWhereSpec | undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const getActivationWherePredicate = (
|
|
73
|
+
where: ActivationWhereSpec | undefined
|
|
74
|
+
): ActivationWherePredicate | undefined =>
|
|
75
|
+
typeof where === 'function' ? where : where?.predicate;
|
|
76
|
+
|
|
77
|
+
export const isKnownActivationSourceKind = (
|
|
78
|
+
kind: string
|
|
79
|
+
): kind is BuiltinActivationSourceKind =>
|
|
80
|
+
(activationSourceKinds as readonly string[]).includes(kind);
|
|
81
|
+
|
|
82
|
+
export const isActivationEntrySpec = (
|
|
83
|
+
value: unknown
|
|
84
|
+
): value is ActivationEntrySpec =>
|
|
85
|
+
typeof value === 'object' && value !== null && 'source' in value;
|
|
86
|
+
|
|
87
|
+
export const isActivationSource = (value: unknown): value is ActivationSource =>
|
|
88
|
+
typeof value === 'object' &&
|
|
89
|
+
value !== null &&
|
|
90
|
+
'id' in value &&
|
|
91
|
+
'kind' in value;
|
package/src/blob-ref.ts
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
* BlobRef — a frozen reference to binary data for @ontrails/core.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
|
|
7
|
+
/** Metadata key used to recognize BlobRef schemas during JSON Schema projection. */
|
|
8
|
+
export const BLOB_REF_SCHEMA_META_KEY = 'ontrails/blob-ref';
|
|
9
|
+
|
|
5
10
|
/** Immutable reference to a blob of binary data. */
|
|
6
11
|
export interface BlobRef {
|
|
7
12
|
readonly name: string;
|
|
@@ -10,6 +15,37 @@ export interface BlobRef {
|
|
|
10
15
|
readonly data: Uint8Array | ReadableStream<Uint8Array>;
|
|
11
16
|
}
|
|
12
17
|
|
|
18
|
+
/** Schema-projected metadata for a BlobRef value. */
|
|
19
|
+
export interface BlobRefDescriptor {
|
|
20
|
+
readonly kind: 'blob';
|
|
21
|
+
readonly mimeType: string;
|
|
22
|
+
readonly name: string;
|
|
23
|
+
readonly size: number;
|
|
24
|
+
readonly uri: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Public descriptor schema emitted to transport clients instead of raw bytes. */
|
|
28
|
+
export const blobRefDescriptorSchema = z.object({
|
|
29
|
+
kind: z.literal('blob'),
|
|
30
|
+
mimeType: z.string(),
|
|
31
|
+
name: z.string(),
|
|
32
|
+
size: z.number(),
|
|
33
|
+
uri: z.string(),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
/** Canonical JSON Schema for BlobRef descriptors across derived surfaces. */
|
|
37
|
+
export const blobRefJsonSchema = Object.freeze({
|
|
38
|
+
properties: Object.freeze({
|
|
39
|
+
kind: Object.freeze({ const: 'blob' }),
|
|
40
|
+
mimeType: Object.freeze({ type: 'string' }),
|
|
41
|
+
name: Object.freeze({ type: 'string' }),
|
|
42
|
+
size: Object.freeze({ type: 'number' }),
|
|
43
|
+
uri: Object.freeze({ type: 'string' }),
|
|
44
|
+
}),
|
|
45
|
+
required: Object.freeze(['kind', 'mimeType', 'name', 'size', 'uri']),
|
|
46
|
+
type: 'object',
|
|
47
|
+
});
|
|
48
|
+
|
|
13
49
|
/** Creates a frozen BlobRef. */
|
|
14
50
|
export const createBlobRef = (options: {
|
|
15
51
|
name: string;
|
|
@@ -37,3 +73,18 @@ export const isBlobRef = (value: unknown): value is BlobRef => {
|
|
|
37
73
|
(obj['data'] instanceof Uint8Array || obj['data'] instanceof ReadableStream)
|
|
38
74
|
);
|
|
39
75
|
};
|
|
76
|
+
|
|
77
|
+
/** Zod schema for runtime BlobRef values with metadata for descriptor projection. */
|
|
78
|
+
export const blobRefSchema = z
|
|
79
|
+
.custom<BlobRef>(isBlobRef, { error: 'Expected BlobRef' })
|
|
80
|
+
.meta({ [BLOB_REF_SCHEMA_META_KEY]: true });
|
|
81
|
+
|
|
82
|
+
/** Convert a runtime BlobRef into its schema-aware transport descriptor. */
|
|
83
|
+
export const toBlobRefDescriptor = (blob: BlobRef): BlobRefDescriptor =>
|
|
84
|
+
Object.freeze({
|
|
85
|
+
kind: 'blob',
|
|
86
|
+
mimeType: blob.mimeType,
|
|
87
|
+
name: blob.name,
|
|
88
|
+
size: blob.size,
|
|
89
|
+
uri: `blob://${blob.name}`,
|
|
90
|
+
});
|
package/src/context.ts
CHANGED
|
@@ -34,6 +34,7 @@ export const createTrailContext = (
|
|
|
34
34
|
const ctx = {
|
|
35
35
|
abortSignal: new AbortController().signal,
|
|
36
36
|
cwd: process.cwd(),
|
|
37
|
+
dryRun: false,
|
|
37
38
|
env: process.env as Record<string, string | undefined>,
|
|
38
39
|
requestId: Bun.randomUUIDv7(),
|
|
39
40
|
trace: passthroughTrace,
|
|
@@ -44,5 +45,8 @@ export const createTrailContext = (
|
|
|
44
45
|
if (ctx.trace === undefined) {
|
|
45
46
|
ctx.trace = passthroughTrace;
|
|
46
47
|
}
|
|
48
|
+
if (ctx.dryRun === undefined) {
|
|
49
|
+
ctx.dryRun = false;
|
|
50
|
+
}
|
|
47
51
|
return ctx;
|
|
48
52
|
};
|
|
@@ -7,13 +7,11 @@
|
|
|
7
7
|
* runner in `@ontrails/testing`. Extracting them here keeps the validation
|
|
8
8
|
* rule, error message, and worker-pool semantics authored in one place so
|
|
9
9
|
* the two call sites cannot drift.
|
|
10
|
-
*
|
|
11
|
-
* @internal
|
|
12
10
|
*/
|
|
13
11
|
|
|
14
|
-
import { ValidationError } from '
|
|
15
|
-
import { Result } from '
|
|
16
|
-
import type { CrossBatchOptions } from '
|
|
12
|
+
import { ValidationError } from './errors.js';
|
|
13
|
+
import { Result } from './result.js';
|
|
14
|
+
import type { CrossBatchOptions } from './types.js';
|
|
17
15
|
|
|
18
16
|
/**
|
|
19
17
|
* Validate the `concurrency` option on a batch `ctx.cross()` call.
|
|
@@ -22,8 +20,6 @@ import type { CrossBatchOptions } from '../types.js';
|
|
|
22
20
|
* positive integer is supplied, and `Err(ValidationError)` for any other
|
|
23
21
|
* value. The error message is load-bearing: callers and tests depend on
|
|
24
22
|
* the exact string.
|
|
25
|
-
*
|
|
26
|
-
* @internal
|
|
27
23
|
*/
|
|
28
24
|
export const normalizeCrossBatchConcurrency = (
|
|
29
25
|
options: CrossBatchOptions | undefined
|
|
@@ -48,8 +44,6 @@ export const normalizeCrossBatchConcurrency = (
|
|
|
48
44
|
* Produce one validation-error result per call, preserving the original
|
|
49
45
|
* call order. Used when `normalizeCrossBatchConcurrency` fails so the caller
|
|
50
46
|
* can surface a uniform batch shape to the trail implementation.
|
|
51
|
-
*
|
|
52
|
-
* @internal
|
|
53
47
|
*/
|
|
54
48
|
export const createCrossBatchValidationResults = <TCall>(
|
|
55
49
|
calls: readonly TCall[],
|
|
@@ -60,8 +54,6 @@ export const createCrossBatchValidationResults = <TCall>(
|
|
|
60
54
|
* Claim the next branch index from a shared counter. Safe to call from
|
|
61
55
|
* multiple worker coroutines because JavaScript is single-threaded between
|
|
62
56
|
* awaits — the read/increment pair runs without interleaving.
|
|
63
|
-
*
|
|
64
|
-
* @internal
|
|
65
57
|
*/
|
|
66
58
|
export const claimNextCrossBatchIndex = <TCall>(
|
|
67
59
|
nextIndex: { value: number },
|
package/src/detours.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hard upper bound for detour recovery attempts.
|
|
3
|
+
*
|
|
4
|
+
* Execution and derived surface/topo projections both clamp declared detour
|
|
5
|
+
* attempts to this value so runtime behavior and inspectable contracts stay in
|
|
6
|
+
* lockstep.
|
|
7
|
+
*/
|
|
8
|
+
export const DETOUR_MAX_ATTEMPTS_CAP = 5;
|
package/src/draft.ts
CHANGED
|
@@ -15,6 +15,8 @@ export type DraftDependencyKind =
|
|
|
15
15
|
| 'resource'
|
|
16
16
|
| 'replaced-by'
|
|
17
17
|
| 'schema-reference'
|
|
18
|
+
| 'signal-fire'
|
|
19
|
+
| 'signal-on'
|
|
18
20
|
| 'signal-from';
|
|
19
21
|
|
|
20
22
|
export interface DraftDependency {
|
|
@@ -92,6 +94,8 @@ const trailDependencies = (trail: AnyTrail): DraftDependency[] => [
|
|
|
92
94
|
trail.resources.map(({ id }) => id),
|
|
93
95
|
'resource'
|
|
94
96
|
),
|
|
97
|
+
...dependenciesFromIds(trail.id, trail.fires ?? [], 'signal-fire'),
|
|
98
|
+
...dependenciesFromIds(trail.id, trail.on ?? [], 'signal-on'),
|
|
95
99
|
...dependencyFromTarget(trail.id, replacedByTarget(trail), 'replaced-by'),
|
|
96
100
|
];
|
|
97
101
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { ErrorCategory } from './errors.js';
|
|
2
|
+
import { isTrailsError } from './errors.js';
|
|
3
|
+
import { createRedactor } from './redaction/index.js';
|
|
4
|
+
|
|
5
|
+
const errorRedactor = createRedactor();
|
|
6
|
+
|
|
7
|
+
export const INTERNAL_ERROR_PUBLIC_MESSAGE = 'Internal server error';
|
|
8
|
+
|
|
9
|
+
export interface ErrorDiagnosticsProjection {
|
|
10
|
+
readonly category?: ErrorCategory | undefined;
|
|
11
|
+
readonly context?: Record<string, unknown> | undefined;
|
|
12
|
+
readonly message: string;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
readonly retryable?: boolean | undefined;
|
|
15
|
+
readonly stack?: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const redactErrorString = (value: string): string =>
|
|
19
|
+
errorRedactor.redact(value);
|
|
20
|
+
|
|
21
|
+
export const redactErrorContext = (
|
|
22
|
+
context: Record<string, unknown> | undefined
|
|
23
|
+
): Record<string, unknown> | undefined =>
|
|
24
|
+
context === undefined ? undefined : errorRedactor.redactObject(context);
|
|
25
|
+
|
|
26
|
+
export const redactErrorStack = (
|
|
27
|
+
stack: string | undefined
|
|
28
|
+
): string | undefined =>
|
|
29
|
+
stack === undefined ? undefined : redactErrorString(stack);
|
|
30
|
+
|
|
31
|
+
export const projectErrorDiagnostics = (
|
|
32
|
+
error: Error
|
|
33
|
+
): ErrorDiagnosticsProjection => {
|
|
34
|
+
const context = isTrailsError(error)
|
|
35
|
+
? redactErrorContext(error.context)
|
|
36
|
+
: undefined;
|
|
37
|
+
const stack = redactErrorStack(error.stack);
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
...(isTrailsError(error)
|
|
41
|
+
? {
|
|
42
|
+
category: error.category,
|
|
43
|
+
retryable: error.retryable,
|
|
44
|
+
}
|
|
45
|
+
: {}),
|
|
46
|
+
...(context === undefined ? {} : { context }),
|
|
47
|
+
message: redactErrorString(error.message),
|
|
48
|
+
name: error.name || error.constructor.name || 'Error',
|
|
49
|
+
...(stack === undefined ? {} : { stack }),
|
|
50
|
+
};
|
|
51
|
+
};
|
package/src/errors.ts
CHANGED
|
@@ -83,6 +83,16 @@ export class PermissionError extends TrailsError {
|
|
|
83
83
|
readonly retryable = false as const;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
export class PermitError extends PermissionError {
|
|
87
|
+
constructor(
|
|
88
|
+
message: string,
|
|
89
|
+
options?: { cause?: Error; context?: Record<string, unknown> }
|
|
90
|
+
) {
|
|
91
|
+
super(message, options);
|
|
92
|
+
this.name = 'PermitError';
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
86
96
|
export class TimeoutError extends TrailsError {
|
|
87
97
|
readonly category = 'timeout' as const;
|
|
88
98
|
readonly retryable = true as const;
|
|
@@ -121,6 +131,8 @@ export class DerivationError extends TrailsError {
|
|
|
121
131
|
readonly retryable = false as const;
|
|
122
132
|
}
|
|
123
133
|
|
|
134
|
+
export class RecoverableCompletionError extends InternalError {}
|
|
135
|
+
|
|
124
136
|
export class AuthError extends TrailsError {
|
|
125
137
|
readonly category = 'auth' as const;
|
|
126
138
|
readonly retryable = false as const;
|
|
@@ -134,7 +146,7 @@ export class CancelledError extends TrailsError {
|
|
|
134
146
|
/**
|
|
135
147
|
* Returned when a detour exhausts all recovery attempts.
|
|
136
148
|
*
|
|
137
|
-
* Inherits the wrapped error's category for
|
|
149
|
+
* Inherits the wrapped error's category for surface mapping (e.g. a
|
|
138
150
|
* `RetryExhaustedError<ConflictError>` maps to HTTP 409), but always
|
|
139
151
|
* sets `retryable = false` to prevent amplification across `ctx.cross()`
|
|
140
152
|
* boundaries or stacked layers.
|
|
@@ -167,48 +179,189 @@ export class RetryExhaustedError<
|
|
|
167
179
|
}
|
|
168
180
|
}
|
|
169
181
|
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// Class registry
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
|
|
186
|
+
export type ErrorClassConstructor = new (...args: never[]) => TrailsError;
|
|
187
|
+
|
|
188
|
+
export interface FixedErrorClassRegistryEntry {
|
|
189
|
+
readonly category: ErrorCategory;
|
|
190
|
+
readonly ctor: ErrorClassConstructor;
|
|
191
|
+
readonly name: string;
|
|
192
|
+
readonly retryable: boolean;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export interface DynamicErrorClassRegistryEntry {
|
|
196
|
+
readonly category: 'dynamic';
|
|
197
|
+
readonly ctor: ErrorClassConstructor;
|
|
198
|
+
readonly inheritsCategoryFrom: 'wrapped-error';
|
|
199
|
+
readonly name: string;
|
|
200
|
+
readonly retryable: false;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export type ErrorClassRegistryEntry =
|
|
204
|
+
| DynamicErrorClassRegistryEntry
|
|
205
|
+
| FixedErrorClassRegistryEntry;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Authored registry of concrete TrailsError classes.
|
|
209
|
+
*
|
|
210
|
+
* JavaScript cannot enumerate subclasses at runtime, so rule and projection
|
|
211
|
+
* tooling should walk this owner-held list instead of hardcoding parallel
|
|
212
|
+
* class-name tables. `RetryExhaustedError` is marked dynamic because it
|
|
213
|
+
* inherits its runtime category from the wrapped error rather than always
|
|
214
|
+
* mapping as `internal`.
|
|
215
|
+
*/
|
|
216
|
+
export const errorClasses = [
|
|
217
|
+
{
|
|
218
|
+
category: 'validation',
|
|
219
|
+
ctor: ValidationError,
|
|
220
|
+
name: 'ValidationError',
|
|
221
|
+
retryable: false,
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
category: 'validation',
|
|
225
|
+
ctor: AmbiguousError,
|
|
226
|
+
name: 'AmbiguousError',
|
|
227
|
+
retryable: false,
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
category: 'internal',
|
|
231
|
+
ctor: AssertionError,
|
|
232
|
+
name: 'AssertionError',
|
|
233
|
+
retryable: false,
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
category: 'not_found',
|
|
237
|
+
ctor: NotFoundError,
|
|
238
|
+
name: 'NotFoundError',
|
|
239
|
+
retryable: false,
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
category: 'conflict',
|
|
243
|
+
ctor: AlreadyExistsError,
|
|
244
|
+
name: 'AlreadyExistsError',
|
|
245
|
+
retryable: false,
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
category: 'conflict',
|
|
249
|
+
ctor: ConflictError,
|
|
250
|
+
name: 'ConflictError',
|
|
251
|
+
retryable: false,
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
category: 'permission',
|
|
255
|
+
ctor: PermissionError,
|
|
256
|
+
name: 'PermissionError',
|
|
257
|
+
retryable: false,
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
category: 'permission',
|
|
261
|
+
ctor: PermitError,
|
|
262
|
+
name: 'PermitError',
|
|
263
|
+
retryable: false,
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
category: 'timeout',
|
|
267
|
+
ctor: TimeoutError,
|
|
268
|
+
name: 'TimeoutError',
|
|
269
|
+
retryable: true,
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
category: 'rate_limit',
|
|
273
|
+
ctor: RateLimitError,
|
|
274
|
+
name: 'RateLimitError',
|
|
275
|
+
retryable: true,
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
category: 'network',
|
|
279
|
+
ctor: NetworkError,
|
|
280
|
+
name: 'NetworkError',
|
|
281
|
+
retryable: true,
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
category: 'internal',
|
|
285
|
+
ctor: InternalError,
|
|
286
|
+
name: 'InternalError',
|
|
287
|
+
retryable: false,
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
category: 'internal',
|
|
291
|
+
ctor: DerivationError,
|
|
292
|
+
name: 'DerivationError',
|
|
293
|
+
retryable: false,
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
category: 'internal',
|
|
297
|
+
ctor: RecoverableCompletionError,
|
|
298
|
+
name: 'RecoverableCompletionError',
|
|
299
|
+
retryable: false,
|
|
300
|
+
},
|
|
301
|
+
{ category: 'auth', ctor: AuthError, name: 'AuthError', retryable: false },
|
|
302
|
+
{
|
|
303
|
+
category: 'cancelled',
|
|
304
|
+
ctor: CancelledError,
|
|
305
|
+
name: 'CancelledError',
|
|
306
|
+
retryable: false,
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
category: 'dynamic',
|
|
310
|
+
ctor: RetryExhaustedError,
|
|
311
|
+
inheritsCategoryFrom: 'wrapped-error',
|
|
312
|
+
name: 'RetryExhaustedError',
|
|
313
|
+
retryable: false,
|
|
314
|
+
},
|
|
315
|
+
] as const satisfies readonly ErrorClassRegistryEntry[];
|
|
316
|
+
|
|
170
317
|
// ---------------------------------------------------------------------------
|
|
171
318
|
// Taxonomy maps
|
|
172
319
|
// ---------------------------------------------------------------------------
|
|
173
320
|
|
|
174
|
-
export
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
321
|
+
export interface ErrorCategoryCodes {
|
|
322
|
+
readonly exit: number;
|
|
323
|
+
readonly http: number;
|
|
324
|
+
readonly jsonRpc: number;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export const codesByCategory = {
|
|
328
|
+
auth: { exit: 9, http: 401, jsonRpc: -32_600 },
|
|
329
|
+
cancelled: { exit: 130, http: 499, jsonRpc: -32_603 },
|
|
330
|
+
conflict: { exit: 3, http: 409, jsonRpc: -32_603 },
|
|
331
|
+
internal: { exit: 8, http: 500, jsonRpc: -32_603 },
|
|
332
|
+
network: { exit: 7, http: 502, jsonRpc: -32_603 },
|
|
333
|
+
not_found: { exit: 2, http: 404, jsonRpc: -32_601 },
|
|
334
|
+
permission: { exit: 4, http: 403, jsonRpc: -32_600 },
|
|
335
|
+
rate_limit: { exit: 6, http: 429, jsonRpc: -32_603 },
|
|
336
|
+
timeout: { exit: 5, http: 504, jsonRpc: -32_603 },
|
|
337
|
+
validation: { exit: 1, http: 400, jsonRpc: -32_602 },
|
|
338
|
+
} as const satisfies Record<ErrorCategory, ErrorCategoryCodes>;
|
|
339
|
+
|
|
340
|
+
const deriveCodeMap = <TCode extends keyof ErrorCategoryCodes>(
|
|
341
|
+
code: TCode
|
|
342
|
+
): {
|
|
343
|
+
readonly [TCategory in ErrorCategory]: (typeof codesByCategory)[TCategory][TCode];
|
|
344
|
+
} => ({
|
|
345
|
+
auth: codesByCategory.auth[code],
|
|
346
|
+
cancelled: codesByCategory.cancelled[code],
|
|
347
|
+
conflict: codesByCategory.conflict[code],
|
|
348
|
+
internal: codesByCategory.internal[code],
|
|
349
|
+
network: codesByCategory.network[code],
|
|
350
|
+
not_found: codesByCategory.not_found[code],
|
|
351
|
+
permission: codesByCategory.permission[code],
|
|
352
|
+
rate_limit: codesByCategory.rate_limit[code],
|
|
353
|
+
timeout: codesByCategory.timeout[code],
|
|
354
|
+
validation: codesByCategory.validation[code],
|
|
355
|
+
});
|
|
356
|
+
|
|
357
|
+
/** @deprecated Prefer `codesByCategory[category].exit`. */
|
|
358
|
+
export const exitCodeMap = deriveCodeMap('exit');
|
|
359
|
+
|
|
360
|
+
/** @deprecated Prefer `codesByCategory[category].http`. */
|
|
361
|
+
export const statusCodeMap = deriveCodeMap('http');
|
|
362
|
+
|
|
363
|
+
/** @deprecated Prefer `codesByCategory[category].jsonRpc`. */
|
|
364
|
+
export const jsonRpcCodeMap = deriveCodeMap('jsonRpc');
|
|
212
365
|
|
|
213
366
|
export const retryableMap: Record<ErrorCategory, boolean> = {
|
|
214
367
|
auth: false,
|