@graphrefly/ts 0.0.0
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/LICENSE +21 -0
- package/dist/adapters/index.cjs +9015 -0
- package/dist/adapters/index.cjs.map +1 -0
- package/dist/adapters/index.d.cts +678 -0
- package/dist/adapters/index.d.ts +678 -0
- package/dist/adapters/index.js +2894 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/observe-storage.cjs +260 -0
- package/dist/adapters/observe-storage.cjs.map +1 -0
- package/dist/adapters/observe-storage.d.cts +77 -0
- package/dist/adapters/observe-storage.d.ts +77 -0
- package/dist/adapters/observe-storage.js +161 -0
- package/dist/adapters/observe-storage.js.map +1 -0
- package/dist/append-log-DisvEReb.d.cts +189 -0
- package/dist/append-log-DzKMmjxx.d.ts +189 -0
- package/dist/chunk-2ILL7HQI.js +1189 -0
- package/dist/chunk-2ILL7HQI.js.map +1 -0
- package/dist/chunk-4VLAQHZI.js +330 -0
- package/dist/chunk-4VLAQHZI.js.map +1 -0
- package/dist/chunk-6PHB5CJS.js +229 -0
- package/dist/chunk-6PHB5CJS.js.map +1 -0
- package/dist/chunk-COHO25CZ.js +2449 -0
- package/dist/chunk-COHO25CZ.js.map +1 -0
- package/dist/chunk-D6BG7U6A.js +161 -0
- package/dist/chunk-D6BG7U6A.js.map +1 -0
- package/dist/chunk-DJC4CHLQ.js +818 -0
- package/dist/chunk-DJC4CHLQ.js.map +1 -0
- package/dist/chunk-DK554R7P.js +67 -0
- package/dist/chunk-DK554R7P.js.map +1 -0
- package/dist/chunk-DKP56CSW.js +322 -0
- package/dist/chunk-DKP56CSW.js.map +1 -0
- package/dist/chunk-G4M3NHRJ.js +688 -0
- package/dist/chunk-G4M3NHRJ.js.map +1 -0
- package/dist/chunk-GAJW5I5P.js +1 -0
- package/dist/chunk-GAJW5I5P.js.map +1 -0
- package/dist/chunk-GDL26N2T.js +282 -0
- package/dist/chunk-GDL26N2T.js.map +1 -0
- package/dist/chunk-GTPCOEOZ.js +741 -0
- package/dist/chunk-GTPCOEOZ.js.map +1 -0
- package/dist/chunk-H2HTHFVN.js +1 -0
- package/dist/chunk-H2HTHFVN.js.map +1 -0
- package/dist/chunk-HDRL4VQQ.js +218 -0
- package/dist/chunk-HDRL4VQQ.js.map +1 -0
- package/dist/chunk-I3IHOHCJ.js +2267 -0
- package/dist/chunk-I3IHOHCJ.js.map +1 -0
- package/dist/chunk-JIMUDQN3.js +965 -0
- package/dist/chunk-JIMUDQN3.js.map +1 -0
- package/dist/chunk-JR4IKCR2.js +462 -0
- package/dist/chunk-JR4IKCR2.js.map +1 -0
- package/dist/chunk-K3FXTC3I.js +165 -0
- package/dist/chunk-K3FXTC3I.js.map +1 -0
- package/dist/chunk-OOEN33FB.js +65 -0
- package/dist/chunk-OOEN33FB.js.map +1 -0
- package/dist/chunk-PKVBHGBM.js +554 -0
- package/dist/chunk-PKVBHGBM.js.map +1 -0
- package/dist/chunk-RIIOUTGM.js +1857 -0
- package/dist/chunk-RIIOUTGM.js.map +1 -0
- package/dist/chunk-SCRFRCGR.js +33 -0
- package/dist/chunk-SCRFRCGR.js.map +1 -0
- package/dist/chunk-SWTLEQL6.js +53 -0
- package/dist/chunk-SWTLEQL6.js.map +1 -0
- package/dist/chunk-SZAETNNA.js +1 -0
- package/dist/chunk-SZAETNNA.js.map +1 -0
- package/dist/chunk-TEW47IVR.js +49 -0
- package/dist/chunk-TEW47IVR.js.map +1 -0
- package/dist/chunk-Y3ZLRGHC.js +1482 -0
- package/dist/chunk-Y3ZLRGHC.js.map +1 -0
- package/dist/chunk-Z2ANQ6JW.js +149 -0
- package/dist/chunk-Z2ANQ6JW.js.map +1 -0
- package/dist/codec-BB7p8fJc.d.cts +38 -0
- package/dist/codec-BB7p8fJc.d.ts +38 -0
- package/dist/composition/index.cjs +2505 -0
- package/dist/composition/index.cjs.map +1 -0
- package/dist/composition/index.d.cts +95 -0
- package/dist/composition/index.d.ts +95 -0
- package/dist/composition/index.js +19 -0
- package/dist/composition/index.js.map +1 -0
- package/dist/core/index.cjs +2475 -0
- package/dist/core/index.cjs.map +1 -0
- package/dist/core/index.d.cts +25 -0
- package/dist/core/index.d.ts +25 -0
- package/dist/core/index.js +74 -0
- package/dist/core/index.js.map +1 -0
- package/dist/cqrs/index.cjs +595 -0
- package/dist/cqrs/index.cjs.map +1 -0
- package/dist/cqrs/index.d.cts +200 -0
- package/dist/cqrs/index.d.ts +200 -0
- package/dist/cqrs/index.js +557 -0
- package/dist/cqrs/index.js.map +1 -0
- package/dist/data-structures/index.cjs +4277 -0
- package/dist/data-structures/index.cjs.map +1 -0
- package/dist/data-structures/index.d.cts +22 -0
- package/dist/data-structures/index.d.ts +22 -0
- package/dist/data-structures/index.js +31 -0
- package/dist/data-structures/index.js.map +1 -0
- package/dist/describe-BZb7AS2y.d.ts +57 -0
- package/dist/describe-Ciu8SUnN.d.cts +57 -0
- package/dist/graph/index.cjs +7832 -0
- package/dist/graph/index.cjs.map +1 -0
- package/dist/graph/index.d.cts +251 -0
- package/dist/graph/index.d.ts +251 -0
- package/dist/graph/index.js +131 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph-DfdF9zy4.d.ts +666 -0
- package/dist/graph-s23RbbFO.d.cts +666 -0
- package/dist/index-CAEmLCYF.d.cts +166 -0
- package/dist/index-SnzZu3x7.d.ts +166 -0
- package/dist/index.cjs +15409 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +23 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +582 -0
- package/dist/index.js.map +1 -0
- package/dist/messages-BZqrGGm1.d.cts +55 -0
- package/dist/messages-BZqrGGm1.d.ts +55 -0
- package/dist/messaging/index.cjs +818 -0
- package/dist/messaging/index.cjs.map +1 -0
- package/dist/messaging/index.d.cts +235 -0
- package/dist/messaging/index.d.ts +235 -0
- package/dist/messaging/index.js +767 -0
- package/dist/messaging/index.js.map +1 -0
- package/dist/observe-event-log-0SVsx7JG.d.cts +88 -0
- package/dist/observe-event-log-Dnm76owp.d.ts +88 -0
- package/dist/operators/index.cjs +3774 -0
- package/dist/operators/index.cjs.map +1 -0
- package/dist/operators/index.d.cts +308 -0
- package/dist/operators/index.d.ts +308 -0
- package/dist/operators/index.js +112 -0
- package/dist/operators/index.js.map +1 -0
- package/dist/orchestration/index.cjs +3541 -0
- package/dist/orchestration/index.cjs.map +1 -0
- package/dist/orchestration/index.d.cts +302 -0
- package/dist/orchestration/index.d.ts +302 -0
- package/dist/orchestration/index.js +1004 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/patterns/index.cjs +1045 -0
- package/dist/patterns/index.cjs.map +1 -0
- package/dist/patterns/index.d.cts +39 -0
- package/dist/patterns/index.d.ts +39 -0
- package/dist/patterns/index.js +33 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/reactive-collection-BxBqtIOE.d.cts +344 -0
- package/dist/reactive-collection-Cb1II1Fi.d.ts +344 -0
- package/dist/reactive-collection-storage-BNiEc-Gd.d.ts +217 -0
- package/dist/reactive-collection-storage-D-KmjE0J.d.cts +217 -0
- package/dist/reactive-map-BcB4KsQR.d.ts +256 -0
- package/dist/reactive-map-D-g3dv8I.d.cts +256 -0
- package/dist/read-through-B1CYPfq_.d.cts +82 -0
- package/dist/read-through-DwyJhGs1.d.ts +82 -0
- package/dist/render/index.cjs +250 -0
- package/dist/render/index.cjs.map +1 -0
- package/dist/render/index.d.cts +58 -0
- package/dist/render/index.d.ts +58 -0
- package/dist/render/index.js +20 -0
- package/dist/render/index.js.map +1 -0
- package/dist/resilience-Dig3Q7n0.d.cts +45 -0
- package/dist/resilience-Dig3Q7n0.d.ts +45 -0
- package/dist/semantic-memory-graph-BYoIlP35.d.cts +356 -0
- package/dist/semantic-memory-graph-CxyXLms3.d.ts +356 -0
- package/dist/solutions/index.cjs +3249 -0
- package/dist/solutions/index.cjs.map +1 -0
- package/dist/solutions/index.d.cts +520 -0
- package/dist/solutions/index.d.ts +520 -0
- package/dist/solutions/index.js +31 -0
- package/dist/solutions/index.js.map +1 -0
- package/dist/sources/browser.cjs +3095 -0
- package/dist/sources/browser.cjs.map +1 -0
- package/dist/sources/browser.d.cts +39 -0
- package/dist/sources/browser.d.ts +39 -0
- package/dist/sources/browser.js +137 -0
- package/dist/sources/browser.js.map +1 -0
- package/dist/sources/index.cjs +3021 -0
- package/dist/sources/index.cjs.map +1 -0
- package/dist/sources/index.d.cts +7 -0
- package/dist/sources/index.d.ts +7 -0
- package/dist/sources/index.js +63 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/sources/node.cjs +675 -0
- package/dist/sources/node.cjs.map +1 -0
- package/dist/sources/node.d.cts +109 -0
- package/dist/sources/node.d.ts +109 -0
- package/dist/sources/node.js +639 -0
- package/dist/sources/node.js.map +1 -0
- package/dist/storage/browser.cjs +777 -0
- package/dist/storage/browser.cjs.map +1 -0
- package/dist/storage/browser.d.cts +40 -0
- package/dist/storage/browser.d.ts +40 -0
- package/dist/storage/browser.js +275 -0
- package/dist/storage/browser.js.map +1 -0
- package/dist/storage/index.cjs +1989 -0
- package/dist/storage/index.cjs.map +1 -0
- package/dist/storage/index.d.cts +92 -0
- package/dist/storage/index.d.ts +92 -0
- package/dist/storage/index.js +161 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/node.cjs +898 -0
- package/dist/storage/node.cjs.map +1 -0
- package/dist/storage/node.d.cts +66 -0
- package/dist/storage/node.d.ts +66 -0
- package/dist/storage/node.js +402 -0
- package/dist/storage/node.js.map +1 -0
- package/dist/testing/index.cjs +95 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +20 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.js +8 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/types-bNMSWKqF.d.cts +732 -0
- package/dist/types-h12mNYbq.d.ts +732 -0
- package/package.json +250 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/graph/higher-order.ts","../src/graph/time.ts"],"sourcesContent":["/**\n * Higher-order operators — switchMap / mergeMap / concatMap / exhaustMap / flatMap\n * (D47 / R-rewire-deferred / CSP-2.7; per-language sugar, D6/D24, never in parity).\n *\n * Each projects every outer value to an INNER source and flattens the inners' emissions. The\n * inner sources are wired as runtime DEPS via the deferred-self-rewire substrate affordance\n * (`ctx.rewireNext`, D47) — NOT an internal subscribe (D45 bans that; it would create a describe\n * island). Growing/shrinking the dep set is deferred to the committed wave boundary, so a fn\n * never mutates its own topology mid-run (that is the D37 feedback-cycle ERROR). An inner that\n * COMPLETEs is `unsubscribeDep`'d → its source `_deactivate`s + fires `onDeactivation`: that is the\n * cancellation / abortInFlight basis (switchMap drops the superseded inner's WORK, not just its\n * output; mergeMap bounds memory). Built on the bare `node` primitive via the {@link Operator}\n * factory shape + the `g.initNode` funnel (D43), so the real factory name shows in describe.\n *\n * Lifecycle folding (D47/D81): completeWhenDepsComplete:false + terminalAsRealInput:true +\n * errorWhenDepsError:false — the operator owns completion (emit COMPLETE only when the SOURCE is\n * done AND no inner is live / pending), and observes source/inner ERROR so it can remove every live\n * inner before emitting ERROR. Those removals drain after terminal via D62: terminal seals output,\n * while helper-owned upstream work still sees unsubscribeDep->_deactivate->onDeactivation teardown.\n *\n * Alignment: each run issues REMOVES before ADDS so the per-node FIFO drain keeps the operator's\n * tracked inner list aligned with the live dep order across the intermediate boundary waves (a\n * removed dep is silent — no settle — and applies before any added dep's push-on-subscribe wave).\n */\n\nimport {\n\tCTX_NODE_BINDING,\n\ttype Ctx,\n\tdepBatch,\n\tdepCount,\n\tdepTerminal,\n\tisTerminalComplete,\n\tisTerminalError,\n\ttype NodeFn,\n\tterminalErrorValue,\n} from \"../ctx/types.js\";\nimport type { Node } from \"../node/node.js\";\nimport { errorPayload } from \"../protocol/messages.js\";\nimport { initNode, type Operator } from \"./operators.js\";\nimport { fromAsyncIter, fromIter, fromPromise, type NodeInput, of } from \"./sources.js\";\n\n/** Project an outer value to an inner source (a Node, Promise, (a)sync iterable, or scalar). */\nexport type Project<TIn, TOut> = (value: TIn) => NodeInput<TOut>;\n\ntype Mode = \"merge\" | \"switch\" | \"concat\" | \"exhaust\";\n\n/** Options for {@link mergeMap}. */\nexport interface MergeMapOptions {\n\t/**\n\t * Maximum number of live inner deps at once. `undefined`/`Infinity` keeps the default\n\t * unbounded mergeMap behavior; finite values queue outer values until an inner COMPLETEs.\n\t */\n\treadonly concurrent?: number;\n}\n\n/** Per-node bookkeeping (ctx.state): the live inner deps (aligned with deps[1..]) + pending queue. */\ninterface MapState<TIn> {\n\tinners: Node<unknown>[];\n\tqueue: TIn[]; // concatMap / bounded mergeMap pending values (lazy projection)\n\tsourceDone: boolean;\n}\n\nfunction uniqueNodes(nodes: readonly Node<unknown>[]): Node<unknown>[] {\n\tconst seen = new Set<Node<unknown>>();\n\tconst out: Node<unknown>[] = [];\n\tfor (const n of nodes) {\n\t\tif (seen.has(n)) continue;\n\t\tseen.add(n);\n\t\tout.push(n);\n\t}\n\treturn out;\n}\n\nfunction cleanupAllInners<TIn>(ctx: Ctx, st: MapState<TIn>, body: NodeFn): void {\n\tfor (const inner of uniqueNodes(st.inners)) ctx.rewireNext.unsubscribeDep(inner, body);\n\tst.inners = [];\n\tst.queue.length = 0;\n\tst.sourceDone = true;\n\tctx.state.set(st);\n}\n\nfunction firstErrorTerminal(ctx: Ctx): unknown {\n\tfor (let i = 0; i < depCount(ctx); i++) {\n\t\tconst terminal = depTerminal(ctx, i);\n\t\tif (isTerminalError(terminal)) return terminalErrorValue(terminal);\n\t}\n\treturn undefined;\n}\n\nfunction fromAnyInCtx<T>(ctx: Ctx, input: NodeInput<T>): Node<unknown> {\n\tconst binding = ctx[CTX_NODE_BINDING];\n\tif (isNode(input)) return input as Node<unknown>;\n\n\tconst nodeOpts = binding ? { dispatcher: binding.dispatcher } : {};\n\tconst make = (op: Operator<never, T>) =>\n\t\t(binding\n\t\t\t? binding.create(() => initNode(op, [], nodeOpts))\n\t\t\t: initNode(op, [], nodeOpts)) as Node<unknown>;\n\n\tif (isThenable(input)) return make(fromPromise(input as PromiseLike<T>));\n\tif (input !== null && input !== undefined) {\n\t\tconst candidate = input as {\n\t\t\t[Symbol.asyncIterator]?: unknown;\n\t\t\t[Symbol.iterator]?: unknown;\n\t\t};\n\t\tif (typeof candidate[Symbol.asyncIterator] === \"function\") {\n\t\t\treturn make(fromAsyncIter(input as AsyncIterable<T>));\n\t\t}\n\t\tif (typeof candidate[Symbol.iterator] === \"function\") {\n\t\t\treturn make(fromIter(input as Iterable<T>));\n\t\t}\n\t}\n\treturn make(of(input as T));\n}\n\nfunction isNode(x: unknown): x is Node {\n\treturn (\n\t\tx != null &&\n\t\ttypeof x === \"object\" &&\n\t\t\"cache\" in x &&\n\t\ttypeof (x as Node).subscribe === \"function\"\n\t);\n}\n\nfunction isThenable(x: unknown): x is PromiseLike<unknown> {\n\treturn x != null && typeof (x as PromiseLike<unknown>).then === \"function\";\n}\n\nfunction normalizeConcurrent(factory: string, concurrent: number | undefined): number {\n\tif (concurrent === undefined || concurrent === Number.POSITIVE_INFINITY) {\n\t\treturn Number.POSITIVE_INFINITY;\n\t}\n\tif (!Number.isInteger(concurrent) || concurrent < 1) {\n\t\tthrow new RangeError(`${factory}: concurrent must be a positive integer or Infinity`);\n\t}\n\treturn concurrent;\n}\n\n/**\n * The shared higher-order machinery. The operator depends on the source S at index 0; inner\n * sources occupy indices 1.. (added/removed at runtime via ctx.rewireNext). The body is\n * SELF-CATCHING (D30) and re-supplies itself on every rewire (the initNode wrap covers only the\n * first run; the re-supplied fn must stay self-catching).\n */\nfunction mapOperator<TIn, TOut>(\n\tfactory: string,\n\tproject: Project<TIn, TOut>,\n\tmode: Mode,\n\topts: { concurrent?: number } = {},\n): Operator<TIn, TOut> {\n\tconst maxConcurrent = normalizeConcurrent(factory, opts.concurrent);\n\tconst body: NodeFn = (ctx: Ctx) => {\n\t\tlet st: MapState<TIn> | undefined;\n\t\ttry {\n\t\t\tst = (ctx.state.get<MapState<TIn>>() ?? {\n\t\t\t\tinners: [],\n\t\t\t\tqueue: [],\n\t\t\t\tsourceDone: false,\n\t\t\t}) as MapState<TIn>;\n\t\t\tlet inners = st.inners;\n\t\t\tconst queue = st.queue;\n\n\t\t\t// 1. forward any inner DATA this wave (index-independent — flatten whichever inner fired).\n\t\t\tfor (let i = 1; i < depCount(ctx); i++) {\n\t\t\t\tconst b = depBatch(ctx, i);\n\t\t\t\tif (b && b.length > 0) for (const v of b) ctx.down([[\"DATA\", v]]);\n\t\t\t}\n\n\t\t\t// D81: source ERROR / inner ERROR are terminal operator edges. Detach live inners first,\n\t\t\t// then emit ERROR. Same-wave inner DATA that preceded the terminal is forwarded above.\n\t\t\t// Do not send COMPLETE/ERROR to those inner sources.\n\t\t\tconst terminalError = firstErrorTerminal(ctx);\n\t\t\tif (terminalError !== undefined) {\n\t\t\t\tcleanupAllInners(ctx, st, body);\n\t\t\t\tctx.down([[\"ERROR\", terminalError]]);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (isTerminalComplete(depTerminal(ctx, 0))) st.sourceDone = true;\n\n\t\t\t// 2. drop inners that terminated this/any wave (bounding); `inners` aligns with deps[1..].\n\t\t\tconst toRemove: Node<unknown>[] = [];\n\t\t\tconst survivors: Node<unknown>[] = [];\n\t\t\tfor (let i = 0; i < inners.length; i++) {\n\t\t\t\tif (isTerminalComplete(depTerminal(ctx, i + 1))) toRemove.push(inners[i]);\n\t\t\t\telse survivors.push(inners[i]);\n\t\t\t}\n\t\t\tinners = survivors;\n\n\t\t\t// 3. project the source's new value(s) per mode.\n\t\t\tconst toAdd: Node<unknown>[] = [];\n\t\t\tconst make = (v: TIn): Node<unknown> => fromAnyInCtx(ctx, project(v));\n\t\t\tconst isRemovedThisWave = (inner: Node<unknown>): boolean => toRemove.includes(inner);\n\t\t\tconst canTrackInner = (inner: Node<unknown>): boolean =>\n\t\t\t\t!inners.includes(inner) && !isRemovedThisWave(inner);\n\t\t\tconst enqueueMerge = (v: TIn) => {\n\t\t\t\tif (maxConcurrent === Number.POSITIVE_INFINITY && queue.length === 0) {\n\t\t\t\t\tconst inner = make(v);\n\t\t\t\t\t// a projector returning an ALREADY-LIVE Node is already merged: subscribeDep is\n\t\t\t\t\t// set-idempotent, so double-tracking it in `inners` would desync the\n\t\t\t\t\t// inners[i] <-> deps[i+1] map permanently. Skip the duplicate.\n\t\t\t\t\tif (!canTrackInner(inner)) return;\n\t\t\t\t\tinners.push(inner);\n\t\t\t\t\ttoAdd.push(inner);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tqueue.push(v);\n\t\t\t};\n\t\t\tconst drainMergeQueue = () => {\n\t\t\t\twhile (queue.length > 0 && inners.length < maxConcurrent) {\n\t\t\t\t\tconst inner = make(queue.shift() as TIn);\n\t\t\t\t\tif (!canTrackInner(inner)) continue;\n\t\t\t\t\tinners.push(inner);\n\t\t\t\t\ttoAdd.push(inner);\n\t\t\t\t}\n\t\t\t};\n\t\t\tconst sb = depBatch(ctx, 0) as readonly TIn[] | null;\n\t\t\tif (sb && sb.length > 0) {\n\t\t\t\tif (mode === \"switch\") {\n\t\t\t\t\t// switch to the latest value: cancel every current inner EXCEPT a (re-projected)\n\t\t\t\t\t// already-live one — the dep set is unique, so removing+re-adding the same Node\n\t\t\t\t\t// would needlessly tear down + re-subscribe it. Superseded sources torn down.\n\t\t\t\t\tconst inner = make(sb[sb.length - 1]);\n\t\t\t\t\tfor (const live of inners) if (live !== inner) toRemove.push(live);\n\t\t\t\t\tif (isRemovedThisWave(inner)) {\n\t\t\t\t\t\tinners = [];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (!inners.includes(inner)) toAdd.push(inner);\n\t\t\t\t\t\tinners = [inner];\n\t\t\t\t\t}\n\t\t\t\t} else if (mode === \"merge\") {\n\t\t\t\t\tfor (const v of sb) {\n\t\t\t\t\t\tenqueueMerge(v);\n\t\t\t\t\t}\n\t\t\t\t} else if (mode === \"concat\") {\n\t\t\t\t\tfor (const v of sb) queue.push(v); // lazy: project on activation\n\t\t\t\t} else {\n\t\t\t\t\t// exhaust: ignore the source while an inner is active.\n\t\t\t\t\tif (inners.length === 0) {\n\t\t\t\t\t\tconst inner = make(sb[0]);\n\t\t\t\t\t\tif (canTrackInner(inner)) {\n\t\t\t\t\t\t\tinners.push(inner);\n\t\t\t\t\t\t\ttoAdd.push(inner);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 3a. bounded mergeMap: drain queued outer values as inner COMPLETEs free slots.\n\t\t\tif (mode === \"merge\" && queue.length > 0) drainMergeQueue();\n\n\t\t\t// 3b. concat: activate the queue head when the single slot is free.\n\t\t\tif (mode === \"concat\" && inners.length === 0 && toAdd.length === 0 && queue.length > 0) {\n\t\t\t\tconst inner = make(queue.shift() as TIn);\n\t\t\t\tif (canTrackInner(inner)) {\n\t\t\t\t\tinners.push(inner);\n\t\t\t\t\ttoAdd.push(inner);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tctx.state.set({ inners, queue, sourceDone: st.sourceDone });\n\n\t\t\t// 4. issue REMOVES before ADDS (alignment): a removed dep is silent + applies before the\n\t\t\t// added dep's push-on-subscribe settle wave, so the tracked list stays aligned.\n\t\t\tfor (const r of toRemove) ctx.rewireNext.unsubscribeDep(r, body);\n\t\t\tfor (const a of toAdd) ctx.rewireNext.subscribeDep(a, body);\n\n\t\t\t// 5. completion: the SOURCE is done AND nothing is live or pending → COMPLETE (D47 folding;\n\t\t\t// a queued/just-added inner keeps it open). If terminal output happens in a wave that\n\t\t\t// also queued cleanup rewire, D62 still drains that queue after terminal.\n\t\t\tif (st.sourceDone && inners.length === 0 && toAdd.length === 0 && queue.length === 0) {\n\t\t\t\tctx.down([[\"COMPLETE\"]]);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tif (st) cleanupAllInners(ctx, st, body);\n\t\t\tctx.down([[\"ERROR\", errorPayload(e, \"projector threw without a valid error payload\")]]); // D30/D81: a throwing projector → cleanup inners, then ERROR\n\t\t}\n\t};\n\n\treturn {\n\t\tfactory,\n\t\tbody,\n\t\t// D47/D81 folding: the operator owns completion + terminal ERROR cleanup.\n\t\topts: { completeWhenDepsComplete: false, terminalAsRealInput: true, errorWhenDepsError: false },\n\t};\n}\n\n/**\n * switchMap: project each source value to an inner; on a new source value, CANCEL the in-flight\n * inner (its source `_deactivate`s — abortInFlight) and switch to the new one. Only the current\n * inner's emissions are forwarded.\n */\nexport function switchMap<TIn, TOut>(project: Project<TIn, TOut>): Operator<TIn, TOut> {\n\treturn mapOperator(\"switchMap\", project, \"switch\");\n}\n\n/**\n * mergeMap (a.k.a. flatMap): project each source value to an inner and keep ALL inners live,\n * interleaving their emissions. A completed inner is removed (memory bounding). On source/inner\n * ERROR or projector failure, every live inner is removed before the operator emits ERROR (D81).\n */\nexport function mergeMap<TIn, TOut>(\n\tproject: Project<TIn, TOut>,\n\topts: MergeMapOptions = {},\n): Operator<TIn, TOut> {\n\treturn mapOperator(\"mergeMap\", project, \"merge\", opts);\n}\n\n/** flatMap: alias of {@link mergeMap} (RxJS naming parity). */\nexport function flatMap<TIn, TOut>(\n\tproject: Project<TIn, TOut>,\n\topts: MergeMapOptions = {},\n): Operator<TIn, TOut> {\n\treturn mapOperator(\"flatMap\", project, \"merge\", opts);\n}\n\n/**\n * concatMap: project each source value to an inner, but run AT MOST ONE inner at a time — queue\n * later source values (lazy projection) and activate the next only when the active inner COMPLETEs.\n * Preserves source order.\n */\nexport function concatMap<TIn, TOut>(project: Project<TIn, TOut>): Operator<TIn, TOut> {\n\treturn mapOperator(\"concatMap\", project, \"concat\");\n}\n\n/**\n * exhaustMap: while an inner is active, DROP new source values; project the next source value only\n * after the active inner COMPLETEs.\n */\nexport function exhaustMap<TIn, TOut>(project: Project<TIn, TOut>): Operator<TIn, TOut> {\n\treturn mapOperator(\"exhaustMap\", project, \"exhaust\");\n}\n\n/** Per-node bookkeeping for {@link repeat}: the round index + the current live inner. */\ninterface RepeatState {\n\tstarted: boolean;\n\tround: number;\n\tinner: Node<unknown> | null;\n}\n\n/**\n * repeat: play a source `count` times in sequence (RxJS `repeat`). A DEPLESS self-driving operator\n * (Operator<never, S>, instantiate via `g.initNode(repeat(factory, count), [])`) — NOT a dep-operator.\n *\n * It takes a `factory: () => NodeInput<S>` (a RECIPE), not a source Node, because clean-slate Nodes\n * are HOT/shared (multicast + cache): re-subscribing the SAME node replays its cache, it does not\n * re-RUN the source. RxJS `repeat` re-subscribes the COLD source = a fresh subscription each round;\n * the clean-slate analogue is a fresh node per round → a factory. (A `repeat(count)`-over-a-Node\n * shape remains deferred: D47's no-net-change-is-a-no-op makes\n * `unsubscribeDep(S)+subscribeDep(S)` on the SAME boundary cancel out. D115 keeps the model to\n * ordinary unsubscribe plus a later subscribe, so same-node repeat needs a separate future design.)\n *\n * Mechanism (reuses the D47 self-rewire substrate, like the *Map family; NOT an internal subscribe,\n * D45): on activation it mints round 0's inner via `ctx.rewireNext.subscribeDep`; each round's inner DATA\n * is forwarded; on the inner's COMPLETE (`completeWhenDepsComplete:false + terminalAsRealInput:true`)\n * it unsubscribeDep's the finished inner and, if rounds remain, subscribeDep's a FRESH `factory()` inner (a\n * distinct node → a real net change, not the no-op same-node case); after the last round it emits\n * COMPLETE. An inner ERROR auto-forwards (errorWhenDepsError default → repeat errors). The body is\n * SELF-CATCHING (D30) and re-supplied on every rewire. The factory MUST mint a FRESH node per call\n * (a factory returning the same Node makes unsubscribeDep+subscribeDep a net-zero no-op → repeat wedges).\n */\nexport function repeat<S>(factory: () => NodeInput<S>, count: number): Operator<never, S> {\n\tif (!Number.isInteger(count) || count < 1) {\n\t\tthrow new RangeError(`repeat: count must be a positive integer (got ${count})`);\n\t}\n\tconst body: NodeFn = (ctx: Ctx) => {\n\t\ttry {\n\t\t\tconst st = (ctx.state.get<RepeatState>() ?? {\n\t\t\t\tstarted: false,\n\t\t\t\tround: 0,\n\t\t\t\tinner: null,\n\t\t\t}) as RepeatState;\n\t\t\t// 1. forward the current inner's DATA this wave (the inner is the sole dep once wired).\n\t\t\tfor (let i = 0; i < depCount(ctx); i++) {\n\t\t\t\tconst b = depBatch(ctx, i);\n\t\t\t\tif (b && b.length > 0) for (const v of b) ctx.down([[\"DATA\", v]]);\n\t\t\t}\n\t\t\t// 2. activation: mint round 0's inner.\n\t\t\tif (!st.started) {\n\t\t\t\tst.started = true;\n\t\t\t\tst.round = 0;\n\t\t\t\tconst inner = fromAnyInCtx(ctx, factory());\n\t\t\t\tst.inner = inner;\n\t\t\t\tctx.state.set(st);\n\t\t\t\tctx.rewireNext.subscribeDep(inner, body);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// 3. inner COMPLETE → next round or terminal COMPLETE.\n\t\t\tif (st.inner !== null && isTerminalComplete(depTerminal(ctx, 0))) {\n\t\t\t\tconst old = st.inner;\n\t\t\t\tctx.rewireNext.unsubscribeDep(old, body); // bound the finished round's inner\n\t\t\t\tif (st.round + 1 < count) {\n\t\t\t\t\tst.round += 1;\n\t\t\t\t\tconst next = fromAnyInCtx(ctx, factory());\n\t\t\t\t\tst.inner = next;\n\t\t\t\t\tctx.state.set(st);\n\t\t\t\t\tctx.rewireNext.subscribeDep(next, body);\n\t\t\t\t} else {\n\t\t\t\t\tst.inner = null;\n\t\t\t\t\tctx.state.set(st);\n\t\t\t\t\tctx.down([[\"COMPLETE\"]]);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tctx.down([[\"ERROR\", errorPayload(e, \"repeat threw without a valid error payload\")]]); // D30 (self-catch survives rewire)\n\t\t}\n\t};\n\treturn {\n\t\tfactory: \"repeat\",\n\t\tbody,\n\t\topts: { completeWhenDepsComplete: false, terminalAsRealInput: true },\n\t};\n}\n","/**\n * Wall-clock time operators (CSP-2.7 / D52 / B23). Authored as COMPOSITIONS over the already-active\n * higher-order *Map machinery (D47) + the `timer` source — NO raw `setTimeout` in any operator body\n * (R-no-raw-async / check-no-raw-async; `setTimeout` stays confined to `sources.ts`'s `timer`). The\n * timer source's `onDeactivation` clearTimeout IS the reset/cancel: switchMap's unsubscribeDep on a new\n * source value tears the in-flight timer down (the declarative equivalent of the frozen reference's\n * imperative clearTimeout-then-setTimeout). Per-language (D6/D24), never in parity.\n *\n * Shipped this cut (clean *Map+timer):\n * - delay = mergeMap(v → timer(ms)→v) (every value delayed ms, ALL kept, order preserved)\n * - debounce(Time) = switchMap(v → timer(ms)→v) (cancel-and-restart; emit the latest after quiet ms)\n * - throttle(Time) = exhaustMap(v → [v now, alive ms]) (leading edge: emit v, ignore for ms)\n *\n * Behavior on source COMPLETE (per-operator, NOT a uniform DROP): debounce/debounceTime EMIT their\n * pending trailing value — switchMap does not cancel the in-flight inner on source COMPLETE (only a\n * superseding source value cancels it via unsubscribeDep→onDeactivation→clearTimeout), so the timer still\n * fires at `ms`, emits the debounced value, and only THEN does the operator COMPLETE (RxJS\n * debounceTime parity). delay emits every still-pending delayed value then COMPLETEs (mergeMap keeps\n * all inners). throttle/throttleTime have NO trailing value (leading-edge only, RxJS default\n * trailing:false) — an open window inner is dropped when the operator completes.\n *\n * B41 tail (landed 2026-05-31, the two shapes reflect WHEN the clock arms):\n * - audit / auditTime — VALUE-TRIGGERED trailing edge: a source value opens a duration window\n * (`audit(durationSelector)` = the general/notifier form, mirroring the *Map\n * `Project` idiom + D46; `auditTime(ms)` = `audit(() => timer(ms))`), emits the\n * window's LATEST value at the window's close. Self-wires the notifier via\n * ctx.rewireNext — a normal `g.initNode(audit(sel), [source])` operator.\n * - timeout / bufferTime — SUBSCRIBE-ARMED (RxJS-cold): the clock must run from activation, before\n * any source value, so the timer/interval is a CONSTRUCTION-time dep (a depless\n * source arms lazily on subscribe per node `_activate`). A dep-bearing operator\n * body never runs at activation (only depless nodes do, node.ts), so these ship\n * as graph composition HELPERS `timeout(source, ms)` / `bufferTime(source, ms)`\n * returning a Node — NOT `g.initNode(op, [deps])` operators. timeout resets its\n * idle timer per source value via ctx.rewireNext (ERROR on the gap); bufferTime\n * is buffer-over-interval with terminal cleanup via ctx.rewireNext.\n *\n * NOT ported (D58): window/windowCount/windowTime — the Node<Node<T>> higher-order forms are a D45\n * describe island; the array forms (buffer/bufferCount/bufferTime) are the graph-first equivalent.\n *\n * Inspection caveat (timeout/bufferTime): the helper returns a BARE node (free initNode) self-carrying\n * its factory for describe auto-discovery (D51), but it is NOT in a graph's _entries — so g.describe()\n * lists it only when it is a live dep of a registered node (a first-cut limit, like the *Map inners).\n */\n\nimport {\n\ttype Ctx,\n\tdepBatch,\n\tdepTerminal,\n\tisTerminalComplete,\n\tisTerminalError,\n\ttype NodeFn,\n\tterminalErrorValue,\n} from \"../ctx/types.js\";\nimport type { Node } from \"../node/node.js\";\nimport { errorPayload } from \"../protocol/messages.js\";\nimport { exhaustMap, mergeMap, switchMap } from \"./higher-order.js\";\nimport { filter, initNode, map, merge, type Operator } from \"./operators.js\";\nimport { fromAny, interval, type NodeInput, of, timer } from \"./sources.js\";\n\n/** A bare inner that emits `v` once after `ms`, then COMPLETEs (timer(ms)→map(v); auto-completes). */\nfunction delayedValue<S>(v: S, ms: number): Node<S> {\n\treturn initNode(\n\t\tmap(() => v),\n\t\t[initNode(timer(ms), [])],\n\t);\n}\n\n/**\n * An inner that emits `v` IMMEDIATELY (on activation) and stays alive for `ms` (then COMPLETEs),\n * emitting nothing more — the leading-edge throttle window. `merge(of(v), silentTimer)`: `of(v)`\n * emits v + COMPLETE at t=0; `filter(()=>false)` over `timer(ms)` emits no DATA and COMPLETEs at\n * t=ms; merge forwards v at t=0 and COMPLETEs (all deps complete) at t=ms.\n */\nfunction throttleWindow<S>(v: S, ms: number): Node<S> {\n\tconst silentTimer = initNode(\n\t\tfilter<number>(() => false),\n\t\t[initNode(timer(ms), [])],\n\t) as Node<S>;\n\treturn initNode(merge<S>(), [initNode(of(v), []), silentTimer]);\n}\n\n/**\n * delay: shift every value by `ms`, preserving all values + order. `mergeMap` keeps every inner\n * timer live (equal `ms`, so they fire in arrival order).\n */\nexport function delay<S>(ms: number): Operator<S, S> {\n\treturn { ...mergeMap<S, S>((v) => delayedValue(v, ms)), factory: \"delay\" };\n}\n\n/**\n * debounce (alias `debounceTime`): emit the latest value only after `ms` of quiet. `switchMap`\n * cancels the prior timer (its onDeactivation clearTimeout) on each new source value and restarts —\n * the declarative debounce.\n *\n * RxJS-7 divergence (reference rxjs@7.8, B44): RxJS `debounceTime` FLUSHES the pending value\n * IMMEDIATELY when the source COMPLETEs (its `_complete` calls `debouncedNext()` before\n * `complete()`). This composition instead emits the pending value when the in-flight `timer(ms)`\n * fires — i.e. at `(last-value-time + ms)` — so if the source completes mid-window the trailing\n * value arrives up to `ms` later than RxJS. Inherent to the `*Map`+`timer` form (the composition\n * cannot flush early without detecting COMPLETE inside the switchMap inner); accepted, not a bug.\n */\nexport function debounce<S>(ms: number): Operator<S, S> {\n\treturn { ...switchMap<S, S>((v) => delayedValue(v, ms)), factory: \"debounce\" };\n}\n\n/** debounceTime: RxJS-named alias of {@link debounce}. */\nexport function debounceTime<S>(ms: number): Operator<S, S> {\n\treturn { ...switchMap<S, S>((v) => delayedValue(v, ms)), factory: \"debounceTime\" };\n}\n\n/**\n * throttle (alias `throttleTime`): leading-edge — emit a value immediately, then ignore the source\n * for `ms`. `exhaustMap` drops new source values while the current window inner is alive; the\n * window emits v at its leading edge and stays alive `ms`.\n *\n * Matches the RxJS-7 `throttleTime` DEFAULT (leading:true, trailing:false). The leading/trailing\n * OPTIONS RxJS exposes are NOT provided (a capability gap, not a behavior divergence; B44) — add a\n * trailing-window form if a consumer needs it.\n */\nexport function throttle<S>(ms: number): Operator<S, S> {\n\treturn { ...exhaustMap<S, S>((v) => throttleWindow(v, ms)), factory: \"throttle\" };\n}\n\n/** throttleTime: RxJS-named alias of {@link throttle}. */\nexport function throttleTime<S>(ms: number): Operator<S, S> {\n\treturn { ...exhaustMap<S, S>((v) => throttleWindow(v, ms)), factory: \"throttleTime\" };\n}\n\n// ── B41 tail: value-triggered (audit) + subscribe-armed (timeout/bufferTime) ──\n\n/** Per-node bookkeeping for {@link audit}: the open window's notifier + the latest value seen. */\ninterface AuditState<S> {\n\twindowOpen: boolean;\n\tlatest: { v: S } | undefined;\n\tnotifier: Node<unknown> | null;\n}\n\n/**\n * audit: VALUE-TRIGGERED trailing throttle. A source value (when no window is open) opens a duration\n * window via `durationSelector(value)` → a notifier `NodeInput` wired as dep 1 with `ctx.rewireNext`\n * (D47 — the *Map self-rewire idiom, NOT an internal subscribe, D45); during the window new source\n * values only UPDATE the tracked latest (no emit); when the notifier fires (its first DATA / COMPLETE)\n * the window closes and the LATEST value is emitted. This is throttle's trailing-edge twin\n * (throttle emits the window's FIRST value at the leading edge; audit emits the LAST at the close).\n *\n * `durationSelector` is the general/notifier form (mirrors the *Map `Project` idiom + D46); the source\n * is dep 0, the live notifier (if any) is dep 1. On source COMPLETE the pending latest is FLUSHED then\n * COMPLETE (RxJS-7 audit flush-on-complete, B44). A source/notifier ERROR is read as a real terminal\n * input so the live notifier can be removed before ERROR. Self-catching (D30); re-supplies its body on\n * every rewire.\n */\nexport function audit<S>(durationSelector: (v: S) => NodeInput<unknown>): Operator<S, S> {\n\tconst body: NodeFn = (ctx: Ctx) => {\n\t\ttry {\n\t\t\tconst st: AuditState<S> = ctx.state.get<AuditState<S>>() ?? {\n\t\t\t\twindowOpen: false,\n\t\t\t\tlatest: undefined,\n\t\t\t\tnotifier: null,\n\t\t\t};\n\t\t\tconst sourceBatch = depBatch(ctx, 0);\n\t\t\tconst notifierBatch = depBatch(ctx, 1); // live duration notifier while a window is open\n\t\t\tconst sourceTerminal = depTerminal(ctx, 0);\n\t\t\tconst notifierTerminal = depTerminal(ctx, 1);\n\n\t\t\t// every source value updates the window's latest (the value emitted at the window's close).\n\t\t\tconst sb = sourceBatch as readonly S[] | null;\n\t\t\tif (sb) for (const v of sb) st.latest = { v };\n\n\t\t\t// the window closes when its duration notifier fires (DATA or COMPLETE) → emit the latest.\n\t\t\tconst notifierFired =\n\t\t\t\tst.windowOpen &&\n\t\t\t\t((notifierBatch != null && notifierBatch.length > 0) ||\n\t\t\t\t\tisTerminalComplete(notifierTerminal));\n\t\t\tif (notifierFired) {\n\t\t\t\tif (st.latest !== undefined) ctx.down([[\"DATA\", st.latest.v]]);\n\t\t\t\tconst old = st.notifier;\n\t\t\t\tst.windowOpen = false;\n\t\t\t\tst.notifier = null;\n\t\t\t\tst.latest = undefined;\n\t\t\t\tif (old) ctx.rewireNext.unsubscribeDep(old, body);\n\t\t\t}\n\n\t\t\t// source/notifier ERROR → forward ERROR, but first remove the helper-owned notifier.\n\t\t\tconst sourceError = isTerminalError(sourceTerminal);\n\t\t\tconst notifierError = isTerminalError(notifierTerminal);\n\t\t\tif (sourceError || notifierError) {\n\t\t\t\tconst err = terminalErrorValue(sourceError ? sourceTerminal : notifierTerminal);\n\t\t\t\tif (st.notifier) ctx.rewireNext.unsubscribeDep(st.notifier, body);\n\t\t\t\tctx.state.set({ windowOpen: false, latest: undefined, notifier: null });\n\t\t\t\tctx.down([[\"ERROR\", err]]);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// source COMPLETE → flush the pending latest (B44 audit flush-on-complete) then COMPLETE.\n\t\t\tif (isTerminalComplete(sourceTerminal)) {\n\t\t\t\tif (st.windowOpen && st.latest !== undefined) ctx.down([[\"DATA\", st.latest.v]]);\n\t\t\t\tif (st.notifier) ctx.rewireNext.unsubscribeDep(st.notifier, body);\n\t\t\t\tctx.state.set({ windowOpen: false, latest: undefined, notifier: null });\n\t\t\t\tctx.down([[\"COMPLETE\"]]);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// a fresh source value with no open window → open one (value-triggered, trailing edge).\n\t\t\tif (!st.windowOpen && sb != null && sb.length > 0 && st.latest !== undefined) {\n\t\t\t\tconst n = fromAny<unknown>(durationSelector(st.latest.v), { iter: true });\n\t\t\t\tst.windowOpen = true;\n\t\t\t\tst.notifier = n;\n\t\t\t\tctx.rewireNext.subscribeDep(n, body); // (a same-wave close+reopen issues remove-before-add)\n\t\t\t}\n\n\t\t\tctx.state.set(st);\n\t\t} catch (e) {\n\t\t\tctx.down([[\"ERROR\", errorPayload(e, \"audit threw without a valid error payload\")]]);\n\t\t}\n\t};\n\treturn {\n\t\tfactory: \"audit\",\n\t\tbody,\n\t\topts: {\n\t\t\tpartial: true,\n\t\t\tcompleteWhenDepsComplete: false,\n\t\t\terrorWhenDepsError: false,\n\t\t\tterminalAsRealInput: true,\n\t\t},\n\t};\n}\n\n/** auditTime: the `ms`-specialization of {@link audit} — the window is a `timer(ms)`. */\nexport function auditTime<S>(ms: number): Operator<S, S> {\n\treturn { ...audit<S>(() => initNode(timer(ms), [])), factory: \"auditTime\" };\n}\n\n/** Per-node bookkeeping for {@link timeout}: the live idle timer (reset on each source value). */\ninterface TimeoutState {\n\ttimer: Node<unknown> | null;\n}\n\n/**\n * timeout: idle watchdog — forward every source value, but ERROR if more than `ms` elapses with no\n * value (RxJS `timeout(ms)`, `first === each === ms`). SUBSCRIBE-ARMED: the first `timer(ms)` is a\n * CONSTRUCTION-time dep, so it arms when `timeout`'s node is subscribed/activated (a depless source\n * runs lazily on `_activate`) — i.e. a source that never emits its FIRST value within `ms` still\n * errors. A dep-bearing operator body never runs at activation (only depless nodes do, node.ts), which\n * is why this is a HELPER returning a Node, not a `g.initNode(op, [source])` operator.\n *\n * Each source value forwards as-is and RESETS the idle timer (unsubscribeDep the current `timer(ms)`,\n * subscribeDep a fresh one — its `onDeactivation` clearTimeout cancels the prior countdown). The timer\n * firing (its DATA/COMPLETE) is the timeout → `[[ERROR]]`. Source COMPLETE forwards COMPLETE (no\n * error) and removes the idle timer during the terminal wave (D62 terminal-drains-queued-rewire);\n * a source ERROR forwards likewise. The idle timer is also torn down when the consumer unsubscribes\n * (timeout deactivates → dep unsub → timer onDeactivation). Self-catching (D30).\n */\nexport function timeout<S>(source: Node<S>, ms: number): Node<S> {\n\tconst makeTimer = (): Node<unknown> => initNode(timer(ms), []);\n\tconst initial = makeTimer();\n\tconst body: NodeFn = (ctx: Ctx) => {\n\t\ttry {\n\t\t\tconst st: TimeoutState = ctx.state.get<TimeoutState>() ?? { timer: initial };\n\t\t\tconst srcBatch = depBatch(ctx, 0);\n\t\t\tconst srcTerminal = depTerminal(ctx, 0);\n\n\t\t\t// a source value forwards as-is and resets the idle window.\n\t\t\tconst sb = srcBatch as readonly S[] | null;\n\t\t\tif (sb != null && sb.length > 0) {\n\t\t\t\tfor (const v of sb) ctx.down([[\"DATA\", v]]);\n\t\t\t\tconst old = st.timer;\n\t\t\t\tconst next = makeTimer();\n\t\t\t\tst.timer = next;\n\t\t\t\tctx.state.set(st);\n\t\t\t\tif (old) ctx.rewireNext.unsubscribeDep(old, body); // remove-before-add (alignment)\n\t\t\t\tctx.rewireNext.subscribeDep(next, body);\n\t\t\t\treturn; // a value-bearing wave is never also a timeout-fire wave\n\t\t\t}\n\n\t\t\t// source COMPLETE → forward COMPLETE (no timeout fires).\n\t\t\tif (isTerminalComplete(srcTerminal)) {\n\t\t\t\tif (st.timer) ctx.rewireNext.unsubscribeDep(st.timer, body);\n\t\t\t\tctx.down([[\"COMPLETE\"]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// source ERROR (absorbed via errorWhenDepsError:false) → forward it.\n\t\t\tif (isTerminalError(srcTerminal)) {\n\t\t\t\tif (st.timer) ctx.rewireNext.unsubscribeDep(st.timer, body);\n\t\t\t\tctx.down([[\"ERROR\", terminalErrorValue(srcTerminal)]]);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// otherwise this wave is the idle timer firing → timeout ERROR.\n\t\t\tconst timerBatch = depBatch(ctx, 1);\n\t\t\tif (\n\t\t\t\t(timerBatch != null && timerBatch.length > 0) ||\n\t\t\t\tisTerminalComplete(depTerminal(ctx, 1))\n\t\t\t) {\n\t\t\t\tctx.down([[\"ERROR\", new Error(`timeout: no value within ${ms}ms`)]]);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tctx.state.set(st);\n\t\t} catch (e) {\n\t\t\tctx.down([[\"ERROR\", errorPayload(e, \"timeout threw without a valid error payload\")]]);\n\t\t}\n\t};\n\treturn initNode<S, S>(\n\t\t{\n\t\t\tfactory: \"timeout\",\n\t\t\tbody,\n\t\t\topts: {\n\t\t\t\tpartial: true,\n\t\t\t\tcompleteWhenDepsComplete: false,\n\t\t\t\terrorWhenDepsError: false,\n\t\t\t\tterminalAsRealInput: true,\n\t\t\t},\n\t\t},\n\t\t[source as Node<unknown>, initial],\n\t);\n}\n\n/**\n * bufferTime: buffer source values and flush them as an array every `ms` (RxJS `bufferTime(ms)`).\n * SUBSCRIBE-ARMED: the `interval(ms)` notifier is a CONSTRUCTION-time dep (arms on subscribe), so an\n * empty window flushes `[]` even before the first source value — matching the landed {@link buffer}\n * (which flushes on every notifier signal). On source COMPLETE the remainder flushes then COMPLETE\n * (B44), and D62 lets the terminal wave still drain `unsubscribeDep(interval)` so the helper-owned\n * interval source deactivates instead of ticking forever.\n */\nexport function bufferTime<S>(source: Node<S>, ms: number): Node<S[]> {\n\tconst iv: Node<unknown> = initNode(interval(ms), []);\n\tconst body: NodeFn = (ctx: Ctx) => {\n\t\tconst srcBatch = depBatch(ctx, 0);\n\t\tconst tickBatch = depBatch(ctx, 1);\n\t\tconst srcTerminal = depTerminal(ctx, 0);\n\t\tconst buf = ctx.state.get<S[]>() ?? [];\n\t\tif (srcBatch) for (const v of srcBatch) buf.push(v as S);\n\t\tif (isTerminalComplete(srcTerminal)) {\n\t\t\tif (buf.length > 0) ctx.down([[\"DATA\", [...buf]]]);\n\t\t\tctx.state.set([]);\n\t\t\tctx.rewireNext.unsubscribeDep(iv, body);\n\t\t\tctx.down([[\"COMPLETE\"]]);\n\t\t\treturn;\n\t\t}\n\t\tif (isTerminalError(srcTerminal)) {\n\t\t\tctx.state.set([]);\n\t\t\tctx.rewireNext.unsubscribeDep(iv, body);\n\t\t\tctx.down([[\"ERROR\", terminalErrorValue(srcTerminal)]]);\n\t\t\treturn;\n\t\t}\n\t\tif (tickBatch && tickBatch.length > 0) {\n\t\t\tctx.down([[\"DATA\", [...buf]]]);\n\t\t\tctx.state.set([]);\n\t\t\treturn;\n\t\t}\n\t\tctx.state.set(buf);\n\t};\n\treturn initNode<unknown, S[]>(\n\t\t{\n\t\t\tfactory: \"bufferTime\",\n\t\t\tbody,\n\t\t\topts: {\n\t\t\t\tpartial: true,\n\t\t\t\tcompleteWhenDepsComplete: false,\n\t\t\t\terrorWhenDepsError: false,\n\t\t\t\tterminalAsRealInput: true,\n\t\t\t},\n\t\t},\n\t\t[source as Node<unknown>, iv],\n\t);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readAppendLogPage
|
|
3
|
+
} from "./chunk-6PHB5CJS.js";
|
|
4
|
+
import {
|
|
5
|
+
strictJsonCodecFor
|
|
6
|
+
} from "./chunk-4VLAQHZI.js";
|
|
7
|
+
|
|
8
|
+
// src/storage/scalar.ts
|
|
9
|
+
var DECIMAL_INTEGER_RE = /^(0|-?[1-9]\d*)$/;
|
|
10
|
+
var NON_NEGATIVE_DECIMAL_INTEGER_RE = /^(0|[1-9]\d*)$/;
|
|
11
|
+
function isDecimalIntegerString(value) {
|
|
12
|
+
return typeof value === "string" && DECIMAL_INTEGER_RE.test(value);
|
|
13
|
+
}
|
|
14
|
+
function isNonNegativeDecimalIntegerString(value) {
|
|
15
|
+
return typeof value === "string" && NON_NEGATIVE_DECIMAL_INTEGER_RE.test(value);
|
|
16
|
+
}
|
|
17
|
+
function assertDecimalIntegerString(value, label = "decimal integer") {
|
|
18
|
+
if (!isDecimalIntegerString(value)) {
|
|
19
|
+
throw new TypeError(`${label} must be a canonical decimal integer string`);
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
function assertNonNegativeDecimalIntegerString(value, label = "decimal integer") {
|
|
24
|
+
if (!isNonNegativeDecimalIntegerString(value)) {
|
|
25
|
+
throw new TypeError(`${label} must be a canonical non-negative decimal integer string`);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
function bigIntToDecimalString(value) {
|
|
30
|
+
return value.toString();
|
|
31
|
+
}
|
|
32
|
+
function bigIntToNonNegativeDecimalString(value) {
|
|
33
|
+
if (value < 0n) {
|
|
34
|
+
throw new TypeError("decimal integer must be non-negative");
|
|
35
|
+
}
|
|
36
|
+
return value.toString();
|
|
37
|
+
}
|
|
38
|
+
function decimalStringToBigInt(value) {
|
|
39
|
+
return BigInt(assertDecimalIntegerString(value));
|
|
40
|
+
}
|
|
41
|
+
function nonNegativeDecimalStringToBigInt(value) {
|
|
42
|
+
return BigInt(assertNonNegativeDecimalIntegerString(value));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/storage/change.ts
|
|
46
|
+
function nowNs() {
|
|
47
|
+
return bigIntToNonNegativeDecimalString(BigInt(Date.now()) * 1000000n);
|
|
48
|
+
}
|
|
49
|
+
function envelopeChange(change, opts) {
|
|
50
|
+
const envelope = {
|
|
51
|
+
lifecycle: opts.lifecycle ?? "data",
|
|
52
|
+
structure: opts.structure,
|
|
53
|
+
version: opts.version ?? 1,
|
|
54
|
+
t_ns: opts.t_ns ?? nowNs(),
|
|
55
|
+
...opts.seq === void 0 ? {} : { seq: opts.seq },
|
|
56
|
+
change
|
|
57
|
+
};
|
|
58
|
+
return assertChangeEnvelope(envelope);
|
|
59
|
+
}
|
|
60
|
+
function isRecord(value) {
|
|
61
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
62
|
+
}
|
|
63
|
+
function isLifecycle(value) {
|
|
64
|
+
return value === "spec" || value === "data" || value === "ownership";
|
|
65
|
+
}
|
|
66
|
+
function assertChangeEnvelope(value) {
|
|
67
|
+
if (!isRecord(value)) throw new TypeError("changeEnvelopeCodec: frame must be an object");
|
|
68
|
+
if (!isLifecycle(value.lifecycle)) {
|
|
69
|
+
throw new TypeError("changeEnvelopeCodec: lifecycle must be spec, data, or ownership");
|
|
70
|
+
}
|
|
71
|
+
if (typeof value.structure !== "string" || value.structure.length === 0) {
|
|
72
|
+
throw new TypeError("changeEnvelopeCodec: structure must be a non-empty string");
|
|
73
|
+
}
|
|
74
|
+
if ((typeof value.version !== "number" || !Number.isFinite(value.version)) && typeof value.version !== "string") {
|
|
75
|
+
throw new TypeError("changeEnvelopeCodec: version must be a finite number or string");
|
|
76
|
+
}
|
|
77
|
+
assertNonNegativeDecimalIntegerString(value.t_ns, "changeEnvelopeCodec: t_ns");
|
|
78
|
+
if (value.seq !== void 0 && (!Number.isSafeInteger(value.seq) || value.seq < 0)) {
|
|
79
|
+
throw new TypeError(
|
|
80
|
+
"changeEnvelopeCodec: seq must be a non-negative safe integer when present"
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
if (!Object.hasOwn(value, "change")) {
|
|
84
|
+
throw new TypeError("changeEnvelopeCodec: change payload is required");
|
|
85
|
+
}
|
|
86
|
+
return value;
|
|
87
|
+
}
|
|
88
|
+
function changeEnvelopeCodec() {
|
|
89
|
+
const codec = strictJsonCodecFor();
|
|
90
|
+
return {
|
|
91
|
+
encode(value) {
|
|
92
|
+
return codec.encode(assertChangeEnvelope(value));
|
|
93
|
+
},
|
|
94
|
+
decode(bytes) {
|
|
95
|
+
return assertChangeEnvelope(codec.decode(bytes));
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// src/storage/observe-event-log.ts
|
|
101
|
+
function observeEventFrame(event, value, opts = {}) {
|
|
102
|
+
return {
|
|
103
|
+
...envelopeChange(value, {
|
|
104
|
+
lifecycle: "data",
|
|
105
|
+
structure: "observe-event",
|
|
106
|
+
version: 1,
|
|
107
|
+
seq: event.seq
|
|
108
|
+
}),
|
|
109
|
+
structure: "observe-event",
|
|
110
|
+
observeSeq: event.seq,
|
|
111
|
+
path: event.path,
|
|
112
|
+
...opts.stream === void 0 ? {} : { stream: opts.stream }
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function assertObserveEventFrame(value) {
|
|
116
|
+
const frame = assertChangeEnvelope(value);
|
|
117
|
+
const record = frame;
|
|
118
|
+
if (frame.structure !== "observe-event") {
|
|
119
|
+
throw new TypeError("observeEventFrameCodec: structure must be observe-event");
|
|
120
|
+
}
|
|
121
|
+
if (!Number.isSafeInteger(record.observeSeq) || record.observeSeq < 0) {
|
|
122
|
+
throw new TypeError("observeEventFrameCodec: observeSeq must be a non-negative safe integer");
|
|
123
|
+
}
|
|
124
|
+
if (typeof record.path !== "string") {
|
|
125
|
+
throw new TypeError("observeEventFrameCodec: path must be a string");
|
|
126
|
+
}
|
|
127
|
+
if (record.stream !== void 0 && typeof record.stream !== "string") {
|
|
128
|
+
throw new TypeError("observeEventFrameCodec: stream must be a string when present");
|
|
129
|
+
}
|
|
130
|
+
return frame;
|
|
131
|
+
}
|
|
132
|
+
function observeEventFrameCodec() {
|
|
133
|
+
const codec = strictJsonCodecFor();
|
|
134
|
+
return {
|
|
135
|
+
encode(value) {
|
|
136
|
+
return codec.encode(assertObserveEventFrame(value));
|
|
137
|
+
},
|
|
138
|
+
decode(bytes) {
|
|
139
|
+
return assertObserveEventFrame(codec.decode(bytes));
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function readObserveEventLogPage(log, opts = {}) {
|
|
144
|
+
return readAppendLogPage(log, opts);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export {
|
|
148
|
+
isDecimalIntegerString,
|
|
149
|
+
isNonNegativeDecimalIntegerString,
|
|
150
|
+
assertDecimalIntegerString,
|
|
151
|
+
assertNonNegativeDecimalIntegerString,
|
|
152
|
+
bigIntToDecimalString,
|
|
153
|
+
bigIntToNonNegativeDecimalString,
|
|
154
|
+
decimalStringToBigInt,
|
|
155
|
+
nonNegativeDecimalStringToBigInt,
|
|
156
|
+
nowNs,
|
|
157
|
+
envelopeChange,
|
|
158
|
+
assertChangeEnvelope,
|
|
159
|
+
changeEnvelopeCodec,
|
|
160
|
+
observeEventFrame,
|
|
161
|
+
assertObserveEventFrame,
|
|
162
|
+
observeEventFrameCodec,
|
|
163
|
+
readObserveEventLogPage
|
|
164
|
+
};
|
|
165
|
+
//# sourceMappingURL=chunk-K3FXTC3I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/storage/scalar.ts","../src/storage/change.ts","../src/storage/observe-event-log.ts"],"sourcesContent":["/**\n * Storage scalar helpers (D88): host BigInt in memory, canonical decimal strings on JSON/storage.\n */\n\n/** Canonical decimal integer string; no leading zeroes, and no negative zero. */\nexport type DecimalIntegerString = string;\n\n/** Canonical non-negative decimal integer string. */\nexport type NonNegativeDecimalIntegerString = DecimalIntegerString;\n\nconst DECIMAL_INTEGER_RE = /^(0|-?[1-9]\\d*)$/;\nconst NON_NEGATIVE_DECIMAL_INTEGER_RE = /^(0|[1-9]\\d*)$/;\n\n/** Test whether a value is a canonical decimal integer string. */\nexport function isDecimalIntegerString(value: unknown): value is DecimalIntegerString {\n\treturn typeof value === \"string\" && DECIMAL_INTEGER_RE.test(value);\n}\n\n/** Test whether a value is a canonical non-negative decimal integer string. */\nexport function isNonNegativeDecimalIntegerString(\n\tvalue: unknown,\n): value is NonNegativeDecimalIntegerString {\n\treturn typeof value === \"string\" && NON_NEGATIVE_DECIMAL_INTEGER_RE.test(value);\n}\n\n/** Assert a canonical decimal integer string and return it typed. */\nexport function assertDecimalIntegerString(\n\tvalue: unknown,\n\tlabel = \"decimal integer\",\n): DecimalIntegerString {\n\tif (!isDecimalIntegerString(value)) {\n\t\tthrow new TypeError(`${label} must be a canonical decimal integer string`);\n\t}\n\treturn value;\n}\n\n/** Assert a canonical non-negative decimal integer string and return it typed. */\nexport function assertNonNegativeDecimalIntegerString(\n\tvalue: unknown,\n\tlabel = \"decimal integer\",\n): NonNegativeDecimalIntegerString {\n\tif (!isNonNegativeDecimalIntegerString(value)) {\n\t\tthrow new TypeError(`${label} must be a canonical non-negative decimal integer string`);\n\t}\n\treturn value;\n}\n\n/** Convert a host BigInt to the canonical decimal storage scalar. */\nexport function bigIntToDecimalString(value: bigint): DecimalIntegerString {\n\treturn value.toString();\n}\n\n/** Convert a non-negative host BigInt to the canonical non-negative decimal storage scalar. */\nexport function bigIntToNonNegativeDecimalString(value: bigint): NonNegativeDecimalIntegerString {\n\tif (value < 0n) {\n\t\tthrow new TypeError(\"decimal integer must be non-negative\");\n\t}\n\treturn value.toString();\n}\n\n/** Parse a canonical decimal storage scalar into host BigInt. */\nexport function decimalStringToBigInt(value: DecimalIntegerString): bigint {\n\treturn BigInt(assertDecimalIntegerString(value));\n}\n\n/** Parse a canonical non-negative decimal storage scalar into host BigInt. */\nexport function nonNegativeDecimalStringToBigInt(value: NonNegativeDecimalIntegerString): bigint {\n\treturn BigInt(assertNonNegativeDecimalIntegerString(value));\n}\n","/**\n * Storage change envelopes (D82): persistence framing for raw graph/data-structure deltas.\n */\n\nimport type { Codec } from \"./codec.js\";\nimport { strictJsonCodecFor } from \"./codec.js\";\nimport {\n\tassertNonNegativeDecimalIntegerString,\n\tbigIntToNonNegativeDecimalString,\n\ttype NonNegativeDecimalIntegerString,\n} from \"./scalar.js\";\n\n/** Storage-side lifecycle namespace for change envelopes; presentation framing only. */\nexport type ChangeLifecycle = \"spec\" | \"data\" | \"ownership\";\n\n/** D84 cross-runtime wall-clock nanosecond metadata: canonical non-negative decimal string. */\nexport type StorageTimestampNs = NonNegativeDecimalIntegerString;\n\n/** Persistence envelope for raw graph/data-structure deltas (D82), not restore semantics. */\nexport interface ChangeEnvelope<T = unknown> {\n\treadonly lifecycle: ChangeLifecycle;\n\treadonly structure: string;\n\treadonly version: number | string;\n\treadonly t_ns: StorageTimestampNs;\n\treadonly seq?: number;\n\treadonly change: T;\n}\n\n/** Options for wrapping a raw change in a storage envelope. */\nexport interface ChangeEnvelopeOptions {\n\tlifecycle?: ChangeLifecycle;\n\tstructure: string;\n\tversion?: number | string;\n\tt_ns?: StorageTimestampNs;\n\tseq?: number;\n}\n\n/** Wall-clock nanoseconds for storage metadata. */\nexport function nowNs(): StorageTimestampNs {\n\treturn bigIntToNonNegativeDecimalString(BigInt(Date.now()) * 1_000_000n);\n}\n\n/** Wrap a raw change payload in a D82 storage envelope. */\nexport function envelopeChange<T>(change: T, opts: ChangeEnvelopeOptions): ChangeEnvelope<T> {\n\tconst envelope = {\n\t\tlifecycle: opts.lifecycle ?? \"data\",\n\t\tstructure: opts.structure,\n\t\tversion: opts.version ?? 1,\n\t\tt_ns: opts.t_ns ?? nowNs(),\n\t\t...(opts.seq === undefined ? {} : { seq: opts.seq }),\n\t\tchange,\n\t};\n\treturn assertChangeEnvelope<T>(envelope);\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isLifecycle(value: unknown): value is ChangeLifecycle {\n\treturn value === \"spec\" || value === \"data\" || value === \"ownership\";\n}\n\n/** Validate a decoded D82 change envelope and return it with typed payload. */\nexport function assertChangeEnvelope<T = unknown>(value: unknown): ChangeEnvelope<T> {\n\tif (!isRecord(value)) throw new TypeError(\"changeEnvelopeCodec: frame must be an object\");\n\tif (!isLifecycle(value.lifecycle)) {\n\t\tthrow new TypeError(\"changeEnvelopeCodec: lifecycle must be spec, data, or ownership\");\n\t}\n\tif (typeof value.structure !== \"string\" || value.structure.length === 0) {\n\t\tthrow new TypeError(\"changeEnvelopeCodec: structure must be a non-empty string\");\n\t}\n\tif (\n\t\t(typeof value.version !== \"number\" || !Number.isFinite(value.version)) &&\n\t\ttypeof value.version !== \"string\"\n\t) {\n\t\tthrow new TypeError(\"changeEnvelopeCodec: version must be a finite number or string\");\n\t}\n\tassertNonNegativeDecimalIntegerString(value.t_ns, \"changeEnvelopeCodec: t_ns\");\n\tif (value.seq !== undefined && (!Number.isSafeInteger(value.seq) || (value.seq as number) < 0)) {\n\t\tthrow new TypeError(\n\t\t\t\"changeEnvelopeCodec: seq must be a non-negative safe integer when present\",\n\t\t);\n\t}\n\tif (!Object.hasOwn(value, \"change\")) {\n\t\tthrow new TypeError(\"changeEnvelopeCodec: change payload is required\");\n\t}\n\treturn value as unknown as ChangeEnvelope<T>;\n}\n\n/** Stable JSON codec for D82 change envelopes, with strict framing checks. */\nexport function changeEnvelopeCodec<T = unknown>(): Codec<ChangeEnvelope<T>> {\n\tconst codec = strictJsonCodecFor<unknown>();\n\treturn {\n\t\tencode(value) {\n\t\t\treturn codec.encode(assertChangeEnvelope(value));\n\t\t},\n\t\tdecode(bytes) {\n\t\t\treturn assertChangeEnvelope<T>(codec.decode(bytes));\n\t\t},\n\t};\n}\n","import type { AppendLogPage, AppendLogReadOptions, AppendLogStorageTier } from \"./append-log.js\";\nimport { readAppendLogPage } from \"./append-log.js\";\nimport { assertChangeEnvelope, type ChangeEnvelope, envelopeChange } from \"./change.js\";\nimport type { Codec } from \"./codec.js\";\nimport { strictJsonCodecFor } from \"./codec.js\";\n\nexport interface ObserveEventLike {\n\treadonly seq: number;\n\treadonly path: string;\n}\n\n/** Storage frame for one Graph.observe() event, preserving graph observe sequence. */\nexport interface ObserveEventFrame<T = unknown> extends ChangeEnvelope<T> {\n\treadonly structure: \"observe-event\";\n\treadonly observeSeq: number;\n\treadonly path: string;\n\treadonly stream?: string;\n}\n\n/** One ordered observe-event log page. It is not graph projection or restore replay. */\nexport type ObserveEventLogPage<T = unknown> = AppendLogPage<ObserveEventFrame<T>>;\n\n/** Create a storage frame from one observe event and mapped payload. */\nexport function observeEventFrame<T>(\n\tevent: ObserveEventLike,\n\tvalue: T,\n\topts: { stream?: string } = {},\n): ObserveEventFrame<T> {\n\treturn {\n\t\t...envelopeChange(value, {\n\t\t\tlifecycle: \"data\",\n\t\t\tstructure: \"observe-event\",\n\t\t\tversion: 1,\n\t\t\tseq: event.seq,\n\t\t}),\n\t\tstructure: \"observe-event\",\n\t\tobserveSeq: event.seq,\n\t\tpath: event.path,\n\t\t...(opts.stream === undefined ? {} : { stream: opts.stream }),\n\t};\n}\n\n/** Validate a decoded D82 observe-event storage frame. */\nexport function assertObserveEventFrame<T = unknown>(value: unknown): ObserveEventFrame<T> {\n\tconst frame = assertChangeEnvelope<T>(value);\n\tconst record = frame as unknown as Record<string, unknown>;\n\tif (frame.structure !== \"observe-event\") {\n\t\tthrow new TypeError(\"observeEventFrameCodec: structure must be observe-event\");\n\t}\n\tif (!Number.isSafeInteger(record.observeSeq) || (record.observeSeq as number) < 0) {\n\t\tthrow new TypeError(\"observeEventFrameCodec: observeSeq must be a non-negative safe integer\");\n\t}\n\tif (typeof record.path !== \"string\") {\n\t\tthrow new TypeError(\"observeEventFrameCodec: path must be a string\");\n\t}\n\tif (record.stream !== undefined && typeof record.stream !== \"string\") {\n\t\tthrow new TypeError(\"observeEventFrameCodec: stream must be a string when present\");\n\t}\n\treturn frame as ObserveEventFrame<T>;\n}\n\n/** Stable JSON codec for D82 observe-event frames, not restore records. */\nexport function observeEventFrameCodec<T = unknown>(): Codec<ObserveEventFrame<T>> {\n\tconst codec = strictJsonCodecFor<unknown>();\n\treturn {\n\t\tencode(value) {\n\t\t\treturn codec.encode(assertObserveEventFrame(value));\n\t\t},\n\t\tdecode(bytes) {\n\t\t\treturn assertObserveEventFrame<T>(codec.decode(bytes));\n\t\t},\n\t};\n}\n\n/**\n * Read one ordered observe-event log page without projecting it into graph state.\n */\nexport function readObserveEventLogPage<T = unknown>(\n\tlog: AppendLogStorageTier<ObserveEventFrame<T>>,\n\topts: AppendLogReadOptions = {},\n): Promise<ObserveEventLogPage<T>> {\n\treturn readAppendLogPage(log, opts);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// src/graph/resilience.ts
|
|
2
|
+
var noBackoff = Object.freeze({ kind: "none" });
|
|
3
|
+
function retryPolicy(maxAttempts = 1, backoff = noBackoff) {
|
|
4
|
+
if (!Number.isInteger(maxAttempts) || maxAttempts <= 0) {
|
|
5
|
+
throw new RangeError("retryPolicy: maxAttempts must be a positive integer");
|
|
6
|
+
}
|
|
7
|
+
return Object.freeze({ maxAttempts, backoff });
|
|
8
|
+
}
|
|
9
|
+
function shouldRetry(policy, failedAttempt) {
|
|
10
|
+
return failedAttempt < policy.maxAttempts;
|
|
11
|
+
}
|
|
12
|
+
function nextRetryDelayMs(policy, nextAttempt) {
|
|
13
|
+
if (!Number.isInteger(nextAttempt) || nextAttempt <= 0 || nextAttempt > policy.maxAttempts) {
|
|
14
|
+
return void 0;
|
|
15
|
+
}
|
|
16
|
+
return backoffDelayMs(policy.backoff, nextAttempt);
|
|
17
|
+
}
|
|
18
|
+
function backoffDelayMs(policy, attempt) {
|
|
19
|
+
const safeAttempt = Math.max(1, Math.trunc(attempt));
|
|
20
|
+
switch (policy.kind) {
|
|
21
|
+
case "none":
|
|
22
|
+
return 0;
|
|
23
|
+
case "constant":
|
|
24
|
+
return nonNegative(policy.delayMs);
|
|
25
|
+
case "linear":
|
|
26
|
+
return cap(
|
|
27
|
+
nonNegative(policy.initialMs) + nonNegative(policy.stepMs) * (safeAttempt - 1),
|
|
28
|
+
policy.maxMs
|
|
29
|
+
);
|
|
30
|
+
case "exponential": {
|
|
31
|
+
const factor = Math.max(1, Math.trunc(policy.factor));
|
|
32
|
+
return cap(nonNegative(policy.initialMs) * factor ** (safeAttempt - 1), policy.maxMs);
|
|
33
|
+
}
|
|
34
|
+
case "fibonacci":
|
|
35
|
+
return cap(nonNegative(policy.unitMs) * fibonacci(safeAttempt), policy.maxMs);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function cap(value, max) {
|
|
39
|
+
if (max === void 0) return value;
|
|
40
|
+
return Math.min(value, nonNegative(max));
|
|
41
|
+
}
|
|
42
|
+
function nonNegative(value) {
|
|
43
|
+
if (!Number.isFinite(value)) return 0;
|
|
44
|
+
return Math.max(0, value);
|
|
45
|
+
}
|
|
46
|
+
function fibonacci(n) {
|
|
47
|
+
if (n <= 1) return 1;
|
|
48
|
+
let prev = 1;
|
|
49
|
+
let curr = 1;
|
|
50
|
+
for (let i = 2; i <= n; i += 1) {
|
|
51
|
+
const next = prev + curr;
|
|
52
|
+
prev = curr;
|
|
53
|
+
curr = next;
|
|
54
|
+
}
|
|
55
|
+
return curr;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export {
|
|
59
|
+
noBackoff,
|
|
60
|
+
retryPolicy,
|
|
61
|
+
shouldRetry,
|
|
62
|
+
nextRetryDelayMs,
|
|
63
|
+
backoffDelayMs
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=chunk-OOEN33FB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/graph/resilience.ts"],"sourcesContent":["/**\n * Passive resilience policy helpers for graph-visible adapters (D130/D132).\n *\n * These helpers never schedule work and never own graph state. Drivers/adapters\n * consume them, while graph-visible bundles expose attempts/status/errors.\n */\n\nexport type BackoffPolicy =\n\t| { readonly kind: \"none\" }\n\t| { readonly kind: \"constant\"; readonly delayMs: number }\n\t| {\n\t\t\treadonly kind: \"linear\";\n\t\t\treadonly initialMs: number;\n\t\t\treadonly stepMs: number;\n\t\t\treadonly maxMs?: number;\n\t }\n\t| {\n\t\t\treadonly kind: \"exponential\";\n\t\t\treadonly initialMs: number;\n\t\t\treadonly factor: number;\n\t\t\treadonly maxMs?: number;\n\t }\n\t| { readonly kind: \"fibonacci\"; readonly unitMs: number; readonly maxMs?: number };\n\nexport interface RetryPolicy {\n\t/** Total attempts including the first try. */\n\treadonly maxAttempts: number;\n\treadonly backoff: BackoffPolicy;\n}\n\nexport type RetryState = \"idle\" | \"running\" | \"waiting\" | \"succeeded\" | \"failed\" | \"exhausted\";\n\nexport interface RetryStatus {\n\treadonly attempt: number;\n\treadonly maxAttempts: number;\n\treadonly delayMs?: number;\n\treadonly state: RetryState;\n}\n\nexport const noBackoff: BackoffPolicy = Object.freeze({ kind: \"none\" });\n\nexport function retryPolicy(maxAttempts = 1, backoff: BackoffPolicy = noBackoff): RetryPolicy {\n\tif (!Number.isInteger(maxAttempts) || maxAttempts <= 0) {\n\t\tthrow new RangeError(\"retryPolicy: maxAttempts must be a positive integer\");\n\t}\n\treturn Object.freeze({ maxAttempts, backoff });\n}\n\nexport function shouldRetry(policy: RetryPolicy, failedAttempt: number): boolean {\n\treturn failedAttempt < policy.maxAttempts;\n}\n\nexport function nextRetryDelayMs(policy: RetryPolicy, nextAttempt: number): number | undefined {\n\tif (!Number.isInteger(nextAttempt) || nextAttempt <= 0 || nextAttempt > policy.maxAttempts) {\n\t\treturn undefined;\n\t}\n\treturn backoffDelayMs(policy.backoff, nextAttempt);\n}\n\nexport function backoffDelayMs(policy: BackoffPolicy, attempt: number): number {\n\tconst safeAttempt = Math.max(1, Math.trunc(attempt));\n\tswitch (policy.kind) {\n\t\tcase \"none\":\n\t\t\treturn 0;\n\t\tcase \"constant\":\n\t\t\treturn nonNegative(policy.delayMs);\n\t\tcase \"linear\":\n\t\t\treturn cap(\n\t\t\t\tnonNegative(policy.initialMs) + nonNegative(policy.stepMs) * (safeAttempt - 1),\n\t\t\t\tpolicy.maxMs,\n\t\t\t);\n\t\tcase \"exponential\": {\n\t\t\tconst factor = Math.max(1, Math.trunc(policy.factor));\n\t\t\treturn cap(nonNegative(policy.initialMs) * factor ** (safeAttempt - 1), policy.maxMs);\n\t\t}\n\t\tcase \"fibonacci\":\n\t\t\treturn cap(nonNegative(policy.unitMs) * fibonacci(safeAttempt), policy.maxMs);\n\t}\n}\n\nfunction cap(value: number, max: number | undefined): number {\n\tif (max === undefined) return value;\n\treturn Math.min(value, nonNegative(max));\n}\n\nfunction nonNegative(value: number): number {\n\tif (!Number.isFinite(value)) return 0;\n\treturn Math.max(0, value);\n}\n\nfunction fibonacci(n: number): number {\n\tif (n <= 1) return 1;\n\tlet prev = 1;\n\tlet curr = 1;\n\tfor (let i = 2; i <= n; i += 1) {\n\t\tconst next = prev + curr;\n\t\tprev = curr;\n\t\tcurr = next;\n\t}\n\treturn curr;\n}\n"],"mappings":";AAuCO,IAAM,YAA2B,OAAO,OAAO,EAAE,MAAM,OAAO,CAAC;AAE/D,SAAS,YAAY,cAAc,GAAG,UAAyB,WAAwB;AAC7F,MAAI,CAAC,OAAO,UAAU,WAAW,KAAK,eAAe,GAAG;AACvD,UAAM,IAAI,WAAW,qDAAqD;AAAA,EAC3E;AACA,SAAO,OAAO,OAAO,EAAE,aAAa,QAAQ,CAAC;AAC9C;AAEO,SAAS,YAAY,QAAqB,eAAgC;AAChF,SAAO,gBAAgB,OAAO;AAC/B;AAEO,SAAS,iBAAiB,QAAqB,aAAyC;AAC9F,MAAI,CAAC,OAAO,UAAU,WAAW,KAAK,eAAe,KAAK,cAAc,OAAO,aAAa;AAC3F,WAAO;AAAA,EACR;AACA,SAAO,eAAe,OAAO,SAAS,WAAW;AAClD;AAEO,SAAS,eAAe,QAAuB,SAAyB;AAC9E,QAAM,cAAc,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,CAAC;AACnD,UAAQ,OAAO,MAAM;AAAA,IACpB,KAAK;AACJ,aAAO;AAAA,IACR,KAAK;AACJ,aAAO,YAAY,OAAO,OAAO;AAAA,IAClC,KAAK;AACJ,aAAO;AAAA,QACN,YAAY,OAAO,SAAS,IAAI,YAAY,OAAO,MAAM,KAAK,cAAc;AAAA,QAC5E,OAAO;AAAA,MACR;AAAA,IACD,KAAK,eAAe;AACnB,YAAM,SAAS,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,MAAM,CAAC;AACpD,aAAO,IAAI,YAAY,OAAO,SAAS,IAAI,WAAW,cAAc,IAAI,OAAO,KAAK;AAAA,IACrF;AAAA,IACA,KAAK;AACJ,aAAO,IAAI,YAAY,OAAO,MAAM,IAAI,UAAU,WAAW,GAAG,OAAO,KAAK;AAAA,EAC9E;AACD;AAEA,SAAS,IAAI,OAAe,KAAiC;AAC5D,MAAI,QAAQ,OAAW,QAAO;AAC9B,SAAO,KAAK,IAAI,OAAO,YAAY,GAAG,CAAC;AACxC;AAEA,SAAS,YAAY,OAAuB;AAC3C,MAAI,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACpC,SAAO,KAAK,IAAI,GAAG,KAAK;AACzB;AAEA,SAAS,UAAU,GAAmB;AACrC,MAAI,KAAK,EAAG,QAAO;AACnB,MAAI,OAAO;AACX,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK,GAAG;AAC/B,UAAM,OAAO,OAAO;AACpB,WAAO;AACP,WAAO;AAAA,EACR;AACA,SAAO;AACR;","names":[]}
|