@ontrails/core 1.0.0-beta.15 → 1.0.0-beta.16
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 +63 -0
- package/README.md +61 -16
- 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
package/src/internal/tracing.ts
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Intrinsic tracing primitives.
|
|
3
|
-
*
|
|
4
|
-
* This module is the home for the trace record type, the sink interface,
|
|
5
|
-
* the sink registry, and the helpers `executeTrail` uses to create root
|
|
6
|
-
* trace records and child spans. It is intentionally framework-internal —
|
|
7
|
-
* the `@ontrails/tracing` package re-exports the public surface so callers
|
|
8
|
-
* can continue to import from there.
|
|
9
|
-
*
|
|
10
|
-
* Tracing is intrinsic: every `executeTrail` call automatically produces a
|
|
11
|
-
* root `TraceRecord`, and `ctx.trace(label, fn)` creates nested child spans
|
|
12
|
-
* underneath it. A default no-op sink is installed at module load so core
|
|
13
|
-
* never crashes when no real sink has been registered.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/** Evidence of a single trail execution or manual span. */
|
|
17
|
-
export interface TraceRecord {
|
|
18
|
-
readonly id: string;
|
|
19
|
-
readonly traceId: string;
|
|
20
|
-
readonly rootId: string;
|
|
21
|
-
readonly parentId?: string | undefined;
|
|
22
|
-
readonly kind: 'trail' | 'span';
|
|
23
|
-
readonly name: string;
|
|
24
|
-
readonly trailId?: string | undefined;
|
|
25
|
-
readonly trailhead?: 'cli' | 'mcp' | 'http' | 'ws' | undefined;
|
|
26
|
-
readonly intent?: 'read' | 'write' | 'destroy' | undefined;
|
|
27
|
-
readonly startedAt: number;
|
|
28
|
-
readonly endedAt?: number | undefined;
|
|
29
|
-
readonly status: 'ok' | 'err' | 'cancelled';
|
|
30
|
-
readonly errorCategory?: string | undefined;
|
|
31
|
-
readonly permit?:
|
|
32
|
-
| { readonly id: string; readonly tenantId?: string }
|
|
33
|
-
| undefined;
|
|
34
|
-
readonly attrs: Readonly<Record<string, unknown>>;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Minimal shape a tracing sink must satisfy.
|
|
39
|
-
*
|
|
40
|
-
* Kept intentionally tiny so adapters in `@ontrails/tracing`,
|
|
41
|
-
* `@ontrails/observe`, and user code can all satisfy it without
|
|
42
|
-
* additional dependencies.
|
|
43
|
-
*/
|
|
44
|
-
export interface TraceSink {
|
|
45
|
-
readonly write: (record: TraceRecord) => void | Promise<void>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/** Trace context carried through trail execution via `ctx.extensions`. */
|
|
49
|
-
export interface TraceContext {
|
|
50
|
-
readonly traceId: string;
|
|
51
|
-
readonly spanId: string;
|
|
52
|
-
readonly rootId: string;
|
|
53
|
-
readonly sampled: boolean;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/** Key used to store trace context in `ctx.extensions`. */
|
|
57
|
-
export const TRACE_CONTEXT_KEY = '__trace_context';
|
|
58
|
-
|
|
59
|
-
/** Read trace context from trail context extensions. */
|
|
60
|
-
export const getTraceContext = (ctx: {
|
|
61
|
-
readonly extensions?: Readonly<Record<string, unknown>> | undefined;
|
|
62
|
-
}): TraceContext | undefined =>
|
|
63
|
-
ctx.extensions?.[TRACE_CONTEXT_KEY] as TraceContext | undefined;
|
|
64
|
-
|
|
65
|
-
// ---------------------------------------------------------------------------
|
|
66
|
-
// Default no-op sink + sink registry
|
|
67
|
-
// ---------------------------------------------------------------------------
|
|
68
|
-
|
|
69
|
-
/** No-op sink installed by default so core never crashes without configuration. */
|
|
70
|
-
export const NOOP_SINK: TraceSink = {
|
|
71
|
-
// oxlint-disable-next-line no-empty-function -- intentional no-op
|
|
72
|
-
write: () => {},
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
// oxlint-disable-next-line eslint-plugin-jest/require-hook -- module-level sink registry, not test setup
|
|
76
|
-
let currentSink: TraceSink = NOOP_SINK;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Register a trace sink globally.
|
|
80
|
-
*
|
|
81
|
-
* All trails executed via `executeTrail` will write their completed trace
|
|
82
|
-
* records to this sink, as will every `ctx.trace(label, fn)` child span.
|
|
83
|
-
* Registering `undefined` or calling {@link clearTraceSink} resets back to
|
|
84
|
-
* the default no-op sink.
|
|
85
|
-
*/
|
|
86
|
-
export const registerTraceSink = (sink: TraceSink | undefined): void => {
|
|
87
|
-
currentSink = sink ?? NOOP_SINK;
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/** Retrieve the currently registered sink (never undefined). */
|
|
91
|
-
export const getTraceSink = (): TraceSink => currentSink;
|
|
92
|
-
|
|
93
|
-
/** True when tracing is effectively disabled and executeTrail should skip allocation. */
|
|
94
|
-
export const isTracingDisabled = (sink: TraceSink = currentSink): boolean =>
|
|
95
|
-
sink === NOOP_SINK;
|
|
96
|
-
|
|
97
|
-
/** Reset the sink registry back to the default no-op sink. */
|
|
98
|
-
export const clearTraceSink = (): void => {
|
|
99
|
-
currentSink = NOOP_SINK;
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// ---------------------------------------------------------------------------
|
|
103
|
-
// Record + span helpers
|
|
104
|
-
// ---------------------------------------------------------------------------
|
|
105
|
-
|
|
106
|
-
/** Options for creating a trail-scoped {@link TraceRecord}. */
|
|
107
|
-
interface CreateTraceRecordOptions {
|
|
108
|
-
readonly trailId: string;
|
|
109
|
-
readonly traceId?: string | undefined;
|
|
110
|
-
readonly parentId?: string | undefined;
|
|
111
|
-
readonly rootId?: string | undefined;
|
|
112
|
-
readonly trailhead?: TraceRecord['trailhead'];
|
|
113
|
-
readonly intent?: TraceRecord['intent'];
|
|
114
|
-
readonly permit?:
|
|
115
|
-
| { readonly id: string; readonly tenantId?: string }
|
|
116
|
-
| undefined;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** Create a fresh trail-kind {@link TraceRecord}. */
|
|
120
|
-
export const createTraceRecord = (
|
|
121
|
-
options: CreateTraceRecordOptions
|
|
122
|
-
): TraceRecord => {
|
|
123
|
-
const id = Bun.randomUUIDv7();
|
|
124
|
-
const traceId = options.traceId ?? Bun.randomUUIDv7();
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
attrs: {},
|
|
128
|
-
endedAt: undefined,
|
|
129
|
-
id,
|
|
130
|
-
intent: options.intent,
|
|
131
|
-
kind: 'trail',
|
|
132
|
-
name: options.trailId,
|
|
133
|
-
parentId: options.parentId,
|
|
134
|
-
permit: options.permit,
|
|
135
|
-
rootId: options.rootId ?? id,
|
|
136
|
-
startedAt: Date.now(),
|
|
137
|
-
status: 'ok',
|
|
138
|
-
traceId,
|
|
139
|
-
trailId: options.trailId,
|
|
140
|
-
trailhead: options.trailhead,
|
|
141
|
-
};
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
/** Build a span record from a parent trace context. */
|
|
145
|
-
export const createSpanRecord = (
|
|
146
|
-
parent: TraceContext,
|
|
147
|
-
label: string
|
|
148
|
-
): TraceRecord => ({
|
|
149
|
-
attrs: {},
|
|
150
|
-
endedAt: undefined,
|
|
151
|
-
errorCategory: undefined,
|
|
152
|
-
id: Bun.randomUUIDv7(),
|
|
153
|
-
intent: undefined,
|
|
154
|
-
kind: 'span',
|
|
155
|
-
name: label,
|
|
156
|
-
parentId: parent.spanId,
|
|
157
|
-
rootId: parent.rootId,
|
|
158
|
-
startedAt: Date.now(),
|
|
159
|
-
status: 'ok',
|
|
160
|
-
traceId: parent.traceId,
|
|
161
|
-
trailId: undefined,
|
|
162
|
-
trailhead: undefined,
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
/** Mark a record as completed with timing and status. */
|
|
166
|
-
export const completeRecord = (
|
|
167
|
-
record: TraceRecord,
|
|
168
|
-
status: TraceRecord['status'],
|
|
169
|
-
errorCategory?: string | undefined
|
|
170
|
-
): TraceRecord => ({
|
|
171
|
-
...record,
|
|
172
|
-
endedAt: Date.now(),
|
|
173
|
-
errorCategory,
|
|
174
|
-
status,
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
/** Best-effort sink write that never throws. */
|
|
178
|
-
export const writeToSink = async (
|
|
179
|
-
sink: TraceSink,
|
|
180
|
-
record: TraceRecord
|
|
181
|
-
): Promise<void> => {
|
|
182
|
-
try {
|
|
183
|
-
await Promise.resolve(sink.write(record));
|
|
184
|
-
} catch {
|
|
185
|
-
// Sink failures must never affect trail result delivery.
|
|
186
|
-
}
|
|
187
|
-
};
|
package/src/topo-store.ts
DELETED
|
@@ -1,510 +0,0 @@
|
|
|
1
|
-
import type { SQLQueryBindings } from 'bun:sqlite';
|
|
2
|
-
import { existsSync, statSync } from 'node:fs';
|
|
3
|
-
|
|
4
|
-
import { NotFoundError } from './errors.js';
|
|
5
|
-
import type { Topo } from './topo.js';
|
|
6
|
-
import { resource } from './resource.js';
|
|
7
|
-
import { Result } from './result.js';
|
|
8
|
-
import {
|
|
9
|
-
TOPO_SCHEMA_VERSION,
|
|
10
|
-
ensureTopoSnapshotSchema,
|
|
11
|
-
listTopoSnapshots as listStoredTopoSnapshots,
|
|
12
|
-
pinTopoSnapshot as pinStoredTopoSnapshot,
|
|
13
|
-
unpinTopoSnapshot as unpinStoredTopoSnapshot,
|
|
14
|
-
} from './internal/topo-snapshots.js';
|
|
15
|
-
import type {
|
|
16
|
-
CreateTopoSnapshotInput,
|
|
17
|
-
ListTopoSnapshotsOptions,
|
|
18
|
-
TopoSnapshot,
|
|
19
|
-
} from './internal/topo-snapshots.js';
|
|
20
|
-
import type {
|
|
21
|
-
TopoStoreExportRecord,
|
|
22
|
-
TopoStoreResourceRecord,
|
|
23
|
-
TopoStoreRef,
|
|
24
|
-
TopoStoreTrailDetailRecord,
|
|
25
|
-
TopoStoreTrailRecord,
|
|
26
|
-
} from './internal/topo-store-read.js';
|
|
27
|
-
import {
|
|
28
|
-
getTopoStoreExport,
|
|
29
|
-
getTopoStoreResource,
|
|
30
|
-
getTopoStoreTrail,
|
|
31
|
-
listTopoStoreResources,
|
|
32
|
-
listTopoStoreSnapshots,
|
|
33
|
-
listTopoStoreTrails,
|
|
34
|
-
queryTopoStore,
|
|
35
|
-
readTopoStoreSnapshot,
|
|
36
|
-
} from './internal/topo-store-read.js';
|
|
37
|
-
import { createTopoSnapshot as storeTopoSnapshot } from './internal/topo-store.js';
|
|
38
|
-
import {
|
|
39
|
-
openReadTrailsDb,
|
|
40
|
-
openWriteTrailsDb,
|
|
41
|
-
deriveTrailsDbPath,
|
|
42
|
-
} from './internal/trails-db.js';
|
|
43
|
-
import type { TrailsDbLocationOptions } from './internal/trails-db.js';
|
|
44
|
-
|
|
45
|
-
interface MigratedDbIdentity {
|
|
46
|
-
readonly mtimeMs: number;
|
|
47
|
-
readonly size: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const migratedTopoDbPaths = new Map<string, MigratedDbIdentity>();
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Test-only instrumentation counters. Incremented by the read-path migration
|
|
54
|
-
* check to let tests assert that a current-schema store does not escalate to
|
|
55
|
-
* a write-mode open, and that cache invalidation re-runs the check when the
|
|
56
|
-
* underlying file is replaced.
|
|
57
|
-
*
|
|
58
|
-
* @internal
|
|
59
|
-
*/
|
|
60
|
-
export const __topoStoreMigrationStats = {
|
|
61
|
-
peekCalls: 0,
|
|
62
|
-
writeEscalations: 0,
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const peekTopoSchemaVersion = (
|
|
66
|
-
options: TrailsDbLocationOptions | undefined
|
|
67
|
-
): number | undefined => {
|
|
68
|
-
let db: ReturnType<typeof openReadTrailsDb> | undefined;
|
|
69
|
-
try {
|
|
70
|
-
db = openReadTrailsDb(options);
|
|
71
|
-
const row = db
|
|
72
|
-
.query<{ version: number }, [string]>(
|
|
73
|
-
'SELECT version FROM meta_schema_versions WHERE subsystem = ?'
|
|
74
|
-
)
|
|
75
|
-
.get('topo');
|
|
76
|
-
return row?.version ?? 0;
|
|
77
|
-
} catch {
|
|
78
|
-
// Table missing or unexpected shape: caller will escalate to a write-mode
|
|
79
|
-
// open and run the migration, which rebuilds the schema.
|
|
80
|
-
return undefined;
|
|
81
|
-
} finally {
|
|
82
|
-
db?.close();
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
const statIdentity = (dbPath: string): MigratedDbIdentity | undefined => {
|
|
87
|
-
try {
|
|
88
|
-
const info = statSync(dbPath);
|
|
89
|
-
return { mtimeMs: info.mtimeMs, size: info.size };
|
|
90
|
-
} catch {
|
|
91
|
-
return undefined;
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const identitiesEqual = (
|
|
96
|
-
a: MigratedDbIdentity,
|
|
97
|
-
b: MigratedDbIdentity
|
|
98
|
-
): boolean => a.mtimeMs === b.mtimeMs && a.size === b.size;
|
|
99
|
-
|
|
100
|
-
const runTopoMigrationEscalation = (
|
|
101
|
-
options: TrailsDbLocationOptions | undefined,
|
|
102
|
-
dbPath: string,
|
|
103
|
-
fallbackIdentity: MigratedDbIdentity
|
|
104
|
-
): void => {
|
|
105
|
-
__topoStoreMigrationStats.writeEscalations += 1;
|
|
106
|
-
const db = openWriteTrailsDb(options);
|
|
107
|
-
try {
|
|
108
|
-
ensureTopoSnapshotSchema(db);
|
|
109
|
-
} finally {
|
|
110
|
-
db.close();
|
|
111
|
-
}
|
|
112
|
-
// Re-stat after the migration so the cached identity matches the file we
|
|
113
|
-
// just touched, avoiding a spurious second escalation on the next read.
|
|
114
|
-
const postIdentity = statIdentity(dbPath) ?? fallbackIdentity;
|
|
115
|
-
migratedTopoDbPaths.set(dbPath, postIdentity);
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const resolveIdentityIfFresh = (
|
|
119
|
-
dbPath: string
|
|
120
|
-
): MigratedDbIdentity | undefined => {
|
|
121
|
-
if (!existsSync(dbPath)) {
|
|
122
|
-
return undefined;
|
|
123
|
-
}
|
|
124
|
-
const identity = statIdentity(dbPath);
|
|
125
|
-
if (identity === undefined) {
|
|
126
|
-
return undefined;
|
|
127
|
-
}
|
|
128
|
-
const cached = migratedTopoDbPaths.get(dbPath);
|
|
129
|
-
if (cached !== undefined && identitiesEqual(cached, identity)) {
|
|
130
|
-
return undefined;
|
|
131
|
-
}
|
|
132
|
-
return identity;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Ensure the topo snapshot schema is at the current version before any
|
|
137
|
-
* read-only access. Peeks the version through a read-only handle first and
|
|
138
|
-
* only escalates to a write-mode open + migration when the store is stale.
|
|
139
|
-
*
|
|
140
|
-
* Memoized per resolved DB path keyed on file identity (mtime + size) so a
|
|
141
|
-
* long-running process that deletes and recreates `trails.db` re-runs the
|
|
142
|
-
* migration check against the fresh file.
|
|
143
|
-
*
|
|
144
|
-
* If the DB file does not yet exist, this is a no-op — the downstream read
|
|
145
|
-
* path will surface its own NotFoundError.
|
|
146
|
-
*/
|
|
147
|
-
const ensureTopoMigratedIfExists = (
|
|
148
|
-
options?: TrailsDbLocationOptions
|
|
149
|
-
): void => {
|
|
150
|
-
const dbPath = deriveTrailsDbPath(options);
|
|
151
|
-
const identity = resolveIdentityIfFresh(dbPath);
|
|
152
|
-
if (identity === undefined) {
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
__topoStoreMigrationStats.peekCalls += 1;
|
|
157
|
-
const version = peekTopoSchemaVersion(options);
|
|
158
|
-
if (version !== undefined && version >= TOPO_SCHEMA_VERSION) {
|
|
159
|
-
// Already current — record identity and skip the write-mode open entirely,
|
|
160
|
-
// preserving the read-only contract for callers whose filesystem mounts
|
|
161
|
-
// `trails.db` read-only.
|
|
162
|
-
migratedTopoDbPaths.set(dbPath, identity);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
runTopoMigrationEscalation(options, dbPath, identity);
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
export type {
|
|
170
|
-
TopoStoreExportRecord,
|
|
171
|
-
TopoStoreResourceRecord,
|
|
172
|
-
TopoStoreRef,
|
|
173
|
-
TopoStoreTrailDetailRecord,
|
|
174
|
-
TopoStoreTrailRecord,
|
|
175
|
-
} from './internal/topo-store-read.js';
|
|
176
|
-
export type {
|
|
177
|
-
CreateTopoSnapshotInput,
|
|
178
|
-
ListTopoSnapshotsOptions,
|
|
179
|
-
TopoSnapshot,
|
|
180
|
-
} from './internal/topo-snapshots.js';
|
|
181
|
-
|
|
182
|
-
export interface ReadOnlyTopoStore {
|
|
183
|
-
readonly exports: {
|
|
184
|
-
get(ref?: TopoStoreRef): TopoStoreExportRecord | undefined;
|
|
185
|
-
};
|
|
186
|
-
query<TRow extends Record<string, unknown>>(
|
|
187
|
-
sql: string,
|
|
188
|
-
bindings?: readonly SQLQueryBindings[]
|
|
189
|
-
): readonly TRow[];
|
|
190
|
-
readonly resources: {
|
|
191
|
-
get(
|
|
192
|
-
id: string,
|
|
193
|
-
options?: { readonly snapshot?: TopoStoreRef }
|
|
194
|
-
): TopoStoreResourceRecord | undefined;
|
|
195
|
-
list(options?: {
|
|
196
|
-
readonly snapshot?: TopoStoreRef;
|
|
197
|
-
}): readonly TopoStoreResourceRecord[];
|
|
198
|
-
};
|
|
199
|
-
readonly snapshots: {
|
|
200
|
-
get(ref?: TopoStoreRef): TopoSnapshot | undefined;
|
|
201
|
-
latest(): TopoSnapshot | undefined;
|
|
202
|
-
list(options?: ListTopoSnapshotsOptions): readonly TopoSnapshot[];
|
|
203
|
-
};
|
|
204
|
-
readonly trails: {
|
|
205
|
-
get(
|
|
206
|
-
id: string,
|
|
207
|
-
options?: { readonly snapshot?: TopoStoreRef }
|
|
208
|
-
): TopoStoreTrailDetailRecord | undefined;
|
|
209
|
-
list(options?: {
|
|
210
|
-
readonly intent?: TopoStoreTrailRecord['intent'];
|
|
211
|
-
readonly snapshot?: TopoStoreRef;
|
|
212
|
-
}): readonly TopoStoreTrailRecord[];
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export interface MockTopoStoreSeed {
|
|
217
|
-
readonly exports?: readonly TopoStoreExportRecord[];
|
|
218
|
-
readonly resources?: readonly TopoStoreResourceRecord[];
|
|
219
|
-
readonly snapshots?: readonly TopoSnapshot[];
|
|
220
|
-
readonly trails?: readonly TopoStoreTrailDetailRecord[];
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const missingStoreMessage =
|
|
224
|
-
'No saved topo state found. Populate trails.db first or run a topo-backed surface.';
|
|
225
|
-
|
|
226
|
-
const resolveStoreRootDir = (options?: TrailsDbLocationOptions): string =>
|
|
227
|
-
options?.rootDir ?? process.cwd();
|
|
228
|
-
|
|
229
|
-
const requireReadDb = (
|
|
230
|
-
options?: TrailsDbLocationOptions
|
|
231
|
-
): ReturnType<typeof openReadTrailsDb> => {
|
|
232
|
-
const dbPath = deriveTrailsDbPath(options);
|
|
233
|
-
if (!existsSync(dbPath)) {
|
|
234
|
-
throw new NotFoundError(missingStoreMessage);
|
|
235
|
-
}
|
|
236
|
-
ensureTopoMigratedIfExists(options);
|
|
237
|
-
return openReadTrailsDb(options);
|
|
238
|
-
};
|
|
239
|
-
|
|
240
|
-
const requireSavedTopoState = (
|
|
241
|
-
db: ReturnType<typeof openReadTrailsDb>
|
|
242
|
-
): void => {
|
|
243
|
-
if (readTopoStoreSnapshot(db) === undefined) {
|
|
244
|
-
throw new NotFoundError(missingStoreMessage);
|
|
245
|
-
}
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
const withStoredTopoState = <T>(
|
|
249
|
-
options: TrailsDbLocationOptions | undefined,
|
|
250
|
-
run: (db: ReturnType<typeof openReadTrailsDb>) => T
|
|
251
|
-
): T => {
|
|
252
|
-
const db = requireReadDb(options);
|
|
253
|
-
try {
|
|
254
|
-
requireSavedTopoState(db);
|
|
255
|
-
return run(db);
|
|
256
|
-
} finally {
|
|
257
|
-
db.close();
|
|
258
|
-
}
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
const createSeedResolver = (seed?: MockTopoStoreSeed) => {
|
|
262
|
-
const snapshots = [...(seed?.snapshots ?? [])];
|
|
263
|
-
const trails = [...(seed?.trails ?? [])];
|
|
264
|
-
const resources = [...(seed?.resources ?? [])];
|
|
265
|
-
const exports = [...(seed?.exports ?? [])];
|
|
266
|
-
|
|
267
|
-
const resolveSnapshot = (ref?: TopoStoreRef): TopoSnapshot | undefined => {
|
|
268
|
-
if (ref?.snapshotId !== undefined) {
|
|
269
|
-
return snapshots.find((snapshot) => snapshot.id === ref.snapshotId);
|
|
270
|
-
}
|
|
271
|
-
if (ref?.pin !== undefined) {
|
|
272
|
-
return snapshots.find((snapshot) => snapshot.pinnedAs === ref.pin);
|
|
273
|
-
}
|
|
274
|
-
return snapshots[0];
|
|
275
|
-
};
|
|
276
|
-
|
|
277
|
-
return {
|
|
278
|
-
exports,
|
|
279
|
-
resolveSnapshot,
|
|
280
|
-
resources,
|
|
281
|
-
snapshots,
|
|
282
|
-
trails,
|
|
283
|
-
};
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
export const createMockTopoStore = (
|
|
287
|
-
seed?: MockTopoStoreSeed
|
|
288
|
-
): ReadOnlyTopoStore => {
|
|
289
|
-
const resolved = createSeedResolver(seed);
|
|
290
|
-
|
|
291
|
-
return {
|
|
292
|
-
exports: {
|
|
293
|
-
get(ref?: TopoStoreRef) {
|
|
294
|
-
const snapshot = resolved.resolveSnapshot(ref);
|
|
295
|
-
return snapshot === undefined
|
|
296
|
-
? undefined
|
|
297
|
-
: resolved.exports.find((entry) => entry.snapshot.id === snapshot.id);
|
|
298
|
-
},
|
|
299
|
-
},
|
|
300
|
-
query() {
|
|
301
|
-
throw new NotFoundError(
|
|
302
|
-
'Mock topoStore.query() is unsupported. Seed typed accessors instead.'
|
|
303
|
-
);
|
|
304
|
-
},
|
|
305
|
-
resources: {
|
|
306
|
-
get(id, options) {
|
|
307
|
-
const snapshot = resolved.resolveSnapshot(options?.snapshot);
|
|
308
|
-
return resolved.resources.find(
|
|
309
|
-
(item) =>
|
|
310
|
-
item.id === id &&
|
|
311
|
-
(snapshot === undefined || item.snapshotId === snapshot.id)
|
|
312
|
-
);
|
|
313
|
-
},
|
|
314
|
-
list(options) {
|
|
315
|
-
const snapshot = resolved.resolveSnapshot(options?.snapshot);
|
|
316
|
-
return snapshot === undefined
|
|
317
|
-
? []
|
|
318
|
-
: resolved.resources.filter(
|
|
319
|
-
(item) => item.snapshotId === snapshot.id
|
|
320
|
-
);
|
|
321
|
-
},
|
|
322
|
-
},
|
|
323
|
-
snapshots: {
|
|
324
|
-
get(ref?: TopoStoreRef) {
|
|
325
|
-
return resolved.resolveSnapshot(ref);
|
|
326
|
-
},
|
|
327
|
-
latest() {
|
|
328
|
-
return resolved.snapshots[0];
|
|
329
|
-
},
|
|
330
|
-
list(options) {
|
|
331
|
-
let snapshots =
|
|
332
|
-
options?.pinned === undefined
|
|
333
|
-
? resolved.snapshots
|
|
334
|
-
: resolved.snapshots.filter((snapshot) =>
|
|
335
|
-
options.pinned
|
|
336
|
-
? snapshot.pinnedAs !== undefined
|
|
337
|
-
: snapshot.pinnedAs === undefined
|
|
338
|
-
);
|
|
339
|
-
if (options?.before !== undefined) {
|
|
340
|
-
const target = snapshots.find((s) => s.id === options.before);
|
|
341
|
-
if (target !== undefined) {
|
|
342
|
-
snapshots = snapshots.filter(
|
|
343
|
-
(s) =>
|
|
344
|
-
s.createdAt < target.createdAt ||
|
|
345
|
-
(s.createdAt === target.createdAt && s.id < target.id)
|
|
346
|
-
);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
if (options?.limit !== undefined) {
|
|
350
|
-
snapshots = snapshots.slice(0, options.limit);
|
|
351
|
-
}
|
|
352
|
-
return snapshots;
|
|
353
|
-
},
|
|
354
|
-
},
|
|
355
|
-
trails: {
|
|
356
|
-
get(id, options) {
|
|
357
|
-
const snapshot = resolved.resolveSnapshot(options?.snapshot);
|
|
358
|
-
if (snapshot === undefined) {
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
return resolved.trails.find(
|
|
362
|
-
(trail) => trail.id === id && trail.snapshotId === snapshot.id
|
|
363
|
-
);
|
|
364
|
-
},
|
|
365
|
-
list(options) {
|
|
366
|
-
const snapshot = resolved.resolveSnapshot(options?.snapshot);
|
|
367
|
-
if (snapshot === undefined) {
|
|
368
|
-
return [];
|
|
369
|
-
}
|
|
370
|
-
return resolved.trails.filter(
|
|
371
|
-
(trail) =>
|
|
372
|
-
trail.snapshotId === snapshot.id &&
|
|
373
|
-
(options?.intent === undefined || trail.intent === options.intent)
|
|
374
|
-
);
|
|
375
|
-
},
|
|
376
|
-
},
|
|
377
|
-
};
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
export const createTopoStore = (
|
|
381
|
-
options?: TrailsDbLocationOptions
|
|
382
|
-
): ReadOnlyTopoStore => ({
|
|
383
|
-
exports: {
|
|
384
|
-
get(ref?: TopoStoreRef) {
|
|
385
|
-
return withStoredTopoState(options, (db) => getTopoStoreExport(db, ref));
|
|
386
|
-
},
|
|
387
|
-
},
|
|
388
|
-
query<TRow extends Record<string, unknown>>(
|
|
389
|
-
sql: string,
|
|
390
|
-
bindings?: readonly SQLQueryBindings[]
|
|
391
|
-
) {
|
|
392
|
-
return withStoredTopoState(options, (db) =>
|
|
393
|
-
queryTopoStore<TRow>(db, sql, bindings)
|
|
394
|
-
);
|
|
395
|
-
},
|
|
396
|
-
resources: {
|
|
397
|
-
get(id, queryOptions) {
|
|
398
|
-
return withStoredTopoState(options, (db) =>
|
|
399
|
-
getTopoStoreResource(db, id, queryOptions)
|
|
400
|
-
);
|
|
401
|
-
},
|
|
402
|
-
list(queryOptions) {
|
|
403
|
-
return withStoredTopoState(options, (db) =>
|
|
404
|
-
listTopoStoreResources(db, queryOptions)
|
|
405
|
-
);
|
|
406
|
-
},
|
|
407
|
-
},
|
|
408
|
-
snapshots: {
|
|
409
|
-
get(ref?: TopoStoreRef) {
|
|
410
|
-
return withStoredTopoState(options, (db) =>
|
|
411
|
-
readTopoStoreSnapshot(db, ref)
|
|
412
|
-
);
|
|
413
|
-
},
|
|
414
|
-
latest() {
|
|
415
|
-
return withStoredTopoState(options, (db) => readTopoStoreSnapshot(db));
|
|
416
|
-
},
|
|
417
|
-
list(snapshotOptions) {
|
|
418
|
-
return withStoredTopoState(options, (db) =>
|
|
419
|
-
listTopoStoreSnapshots(db, snapshotOptions)
|
|
420
|
-
);
|
|
421
|
-
},
|
|
422
|
-
},
|
|
423
|
-
trails: {
|
|
424
|
-
get(id, queryOptions) {
|
|
425
|
-
return withStoredTopoState(options, (db) =>
|
|
426
|
-
getTopoStoreTrail(db, id, queryOptions)
|
|
427
|
-
);
|
|
428
|
-
},
|
|
429
|
-
list(queryOptions) {
|
|
430
|
-
return withStoredTopoState(options, (db) =>
|
|
431
|
-
listTopoStoreTrails(db, queryOptions)
|
|
432
|
-
);
|
|
433
|
-
},
|
|
434
|
-
},
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
export const createTopoSnapshot = (
|
|
438
|
-
topo: Topo,
|
|
439
|
-
options?: TrailsDbLocationOptions & CreateTopoSnapshotInput
|
|
440
|
-
): Result<TopoSnapshot, Error> => {
|
|
441
|
-
const db = openWriteTrailsDb(options);
|
|
442
|
-
try {
|
|
443
|
-
return storeTopoSnapshot(db, topo, options);
|
|
444
|
-
} finally {
|
|
445
|
-
db.close();
|
|
446
|
-
}
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
export const listTopoSnapshots = (
|
|
450
|
-
options?: TrailsDbLocationOptions & ListTopoSnapshotsOptions
|
|
451
|
-
): readonly TopoSnapshot[] => {
|
|
452
|
-
const dbPath = deriveTrailsDbPath(options);
|
|
453
|
-
if (!existsSync(dbPath)) {
|
|
454
|
-
return [];
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
ensureTopoMigratedIfExists(options);
|
|
458
|
-
const db = openReadTrailsDb(options);
|
|
459
|
-
try {
|
|
460
|
-
return listStoredTopoSnapshots(db, options);
|
|
461
|
-
} finally {
|
|
462
|
-
db.close();
|
|
463
|
-
}
|
|
464
|
-
};
|
|
465
|
-
|
|
466
|
-
export const pinTopoSnapshot = (
|
|
467
|
-
id: string,
|
|
468
|
-
name: string,
|
|
469
|
-
options?: TrailsDbLocationOptions
|
|
470
|
-
): TopoSnapshot | undefined => {
|
|
471
|
-
const dbPath = deriveTrailsDbPath(options);
|
|
472
|
-
if (!existsSync(dbPath)) {
|
|
473
|
-
return undefined;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
const db = openWriteTrailsDb(options);
|
|
477
|
-
try {
|
|
478
|
-
return pinStoredTopoSnapshot(db, { id, name });
|
|
479
|
-
} finally {
|
|
480
|
-
db.close();
|
|
481
|
-
}
|
|
482
|
-
};
|
|
483
|
-
|
|
484
|
-
export const unpinTopoSnapshot = (
|
|
485
|
-
nameOrId: string,
|
|
486
|
-
options?: TrailsDbLocationOptions
|
|
487
|
-
): TopoSnapshot | undefined => {
|
|
488
|
-
const dbPath = deriveTrailsDbPath(options);
|
|
489
|
-
if (!existsSync(dbPath)) {
|
|
490
|
-
return undefined;
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
const db = openWriteTrailsDb(options);
|
|
494
|
-
try {
|
|
495
|
-
return unpinStoredTopoSnapshot(db, nameOrId);
|
|
496
|
-
} finally {
|
|
497
|
-
db.close();
|
|
498
|
-
}
|
|
499
|
-
};
|
|
500
|
-
|
|
501
|
-
export const topoStore = resource('topo.store', {
|
|
502
|
-
create: (svc) =>
|
|
503
|
-
Result.ok(
|
|
504
|
-
createTopoStore({
|
|
505
|
-
rootDir: svc.workspaceRoot ?? svc.cwd ?? resolveStoreRootDir(),
|
|
506
|
-
})
|
|
507
|
-
),
|
|
508
|
-
description: 'Read-only query access to saved topo state in trails.db',
|
|
509
|
-
mock: () => createMockTopoStore(),
|
|
510
|
-
});
|