@graphrefly/ts 0.0.0 → 0.0.1
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/README.md +135 -0
- package/dist/adapters/index.cjs +105 -66
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +11 -136
- package/dist/adapters/index.d.ts +11 -136
- package/dist/adapters/index.js +27 -225
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/observe-storage.d.cts +4 -4
- package/dist/adapters/observe-storage.d.ts +4 -4
- package/dist/adapters/observe-storage.js +1 -0
- package/dist/adapters/observe-storage.js.map +1 -1
- package/dist/adapters/react.cjs +166 -0
- package/dist/adapters/react.cjs.map +1 -0
- package/dist/adapters/react.d.cts +31 -0
- package/dist/adapters/react.d.ts +31 -0
- package/dist/adapters/react.js +51 -0
- package/dist/adapters/react.js.map +1 -0
- package/dist/adapters/solid.cjs +157 -0
- package/dist/adapters/solid.cjs.map +1 -0
- package/dist/adapters/solid.d.cts +26 -0
- package/dist/adapters/solid.d.ts +26 -0
- package/dist/adapters/solid.js +48 -0
- package/dist/adapters/solid.js.map +1 -0
- package/dist/adapters/svelte.cjs +148 -0
- package/dist/adapters/svelte.cjs.map +1 -0
- package/dist/adapters/svelte.d.cts +31 -0
- package/dist/adapters/svelte.d.ts +31 -0
- package/dist/adapters/svelte.js +46 -0
- package/dist/adapters/svelte.js.map +1 -0
- package/dist/adapters/vue.cjs +155 -0
- package/dist/adapters/vue.cjs.map +1 -0
- package/dist/adapters/vue.d.cts +26 -0
- package/dist/adapters/vue.d.ts +26 -0
- package/dist/adapters/vue.js +46 -0
- package/dist/adapters/vue.js.map +1 -0
- package/dist/agent-runtime-BesGDZcB.d.ts +555 -0
- package/dist/agent-runtime-DZTJ3C-p.d.cts +555 -0
- package/dist/agentic-memory-BmRCvh0d.d.ts +517 -0
- package/dist/agentic-memory-DfuVZ-lY.d.cts +517 -0
- package/dist/capability-admission-B0BzqAm5.d.cts +102 -0
- package/dist/capability-admission-g0mn9hpq.d.ts +102 -0
- package/dist/{chunk-JR4IKCR2.js → chunk-2747WN4Y.js} +5 -5
- package/dist/{chunk-2ILL7HQI.js → chunk-3JR3EDB2.js} +17 -17
- package/dist/{chunk-2ILL7HQI.js.map → chunk-3JR3EDB2.js.map} +1 -1
- package/dist/{chunk-GDL26N2T.js → chunk-3KN7NJDR.js} +2 -2
- package/dist/{chunk-DJC4CHLQ.js → chunk-43BKLFZU.js} +9 -9
- package/dist/chunk-6XAIOL3X.js +2407 -0
- package/dist/chunk-6XAIOL3X.js.map +1 -0
- package/dist/{chunk-SCRFRCGR.js → chunk-BSQGE5PS.js} +1 -1
- package/dist/{chunk-Y3ZLRGHC.js → chunk-CZNV3VXM.js} +16 -16
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/{chunk-JIMUDQN3.js → chunk-FBUU43PM.js} +2 -2
- package/dist/chunk-H75VXTGT.js +219 -0
- package/dist/chunk-H75VXTGT.js.map +1 -0
- package/dist/{chunk-RIIOUTGM.js → chunk-HKK2JD7Z.js} +12 -9
- package/dist/chunk-HKK2JD7Z.js.map +1 -0
- package/dist/{chunk-D6BG7U6A.js → chunk-IXZBUWSP.js} +3 -3
- package/dist/chunk-PC3BTTBE.js +3217 -0
- package/dist/chunk-PC3BTTBE.js.map +1 -0
- package/dist/chunk-QFY4AFY4.js +879 -0
- package/dist/chunk-QFY4AFY4.js.map +1 -0
- package/dist/{chunk-DK554R7P.js → chunk-S6HXABGL.js} +2 -1
- package/dist/chunk-S6HXABGL.js.map +1 -0
- package/dist/{chunk-PKVBHGBM.js → chunk-SS2A464I.js} +7 -7
- package/dist/chunk-UT3MHJCW.js +49 -0
- package/dist/chunk-UT3MHJCW.js.map +1 -0
- package/dist/{chunk-G4M3NHRJ.js → chunk-V7CIJE4B.js} +3 -3
- package/dist/{chunk-TEW47IVR.js → chunk-VPEFSDME.js} +2 -2
- package/dist/chunk-VTHLCFN4.js +368 -0
- package/dist/chunk-VTHLCFN4.js.map +1 -0
- package/dist/{chunk-SWTLEQL6.js → chunk-WQIA3GFB.js} +2 -2
- package/dist/chunk-WQIA3GFB.js.map +1 -0
- package/dist/{chunk-I3IHOHCJ.js → chunk-XKXWK2KP.js} +108 -64
- package/dist/chunk-XKXWK2KP.js.map +1 -0
- package/dist/{chunk-COHO25CZ.js → chunk-YDSIVHRR.js} +553 -7
- package/dist/chunk-YDSIVHRR.js.map +1 -0
- package/dist/chunk-YXMZ2N6J.js +1884 -0
- package/dist/chunk-YXMZ2N6J.js.map +1 -0
- package/dist/composition/index.cjs +102 -57
- package/dist/composition/index.cjs.map +1 -1
- package/dist/composition/index.d.cts +4 -4
- package/dist/composition/index.d.ts +4 -4
- package/dist/composition/index.js +6 -5
- package/dist/core/index.cjs +102 -57
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +5 -4
- package/dist/cqrs/index.cjs.map +1 -1
- package/dist/cqrs/index.d.cts +4 -4
- package/dist/cqrs/index.d.ts +4 -4
- package/dist/cqrs/index.js +3 -2
- package/dist/cqrs/index.js.map +1 -1
- package/dist/cqrs/messaging.cjs +312 -0
- package/dist/cqrs/messaging.cjs.map +1 -0
- package/dist/cqrs/messaging.d.cts +57 -0
- package/dist/cqrs/messaging.d.ts +57 -0
- package/dist/cqrs/messaging.js +274 -0
- package/dist/cqrs/messaging.js.map +1 -0
- package/dist/cqrs/work-queue.cjs +329 -0
- package/dist/cqrs/work-queue.cjs.map +1 -0
- package/dist/cqrs/work-queue.d.cts +90 -0
- package/dist/cqrs/work-queue.d.ts +90 -0
- package/dist/cqrs/work-queue.js +292 -0
- package/dist/cqrs/work-queue.js.map +1 -0
- package/dist/data/index.cjs +19 -0
- package/dist/data/index.cjs.map +1 -0
- package/dist/data/index.d.cts +36 -0
- package/dist/data/index.d.ts +36 -0
- package/dist/data/index.js +1 -0
- package/dist/data/index.js.map +1 -0
- package/dist/data-structures/index.cjs +105 -57
- package/dist/data-structures/index.cjs.map +1 -1
- package/dist/data-structures/index.d.cts +8 -8
- package/dist/data-structures/index.d.ts +8 -8
- package/dist/data-structures/index.js +7 -6
- package/dist/{describe-BZb7AS2y.d.ts → describe-BpyJuWkw.d.ts} +1 -1
- package/dist/{describe-Ciu8SUnN.d.cts → describe-DYMw_l1C.d.cts} +1 -1
- package/dist/executors/work-queue.cjs +342 -0
- package/dist/executors/work-queue.cjs.map +1 -0
- package/dist/executors/work-queue.d.cts +90 -0
- package/dist/executors/work-queue.d.ts +90 -0
- package/dist/executors/work-queue.js +306 -0
- package/dist/executors/work-queue.js.map +1 -0
- package/dist/graph/index.cjs +112 -58
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +9 -9
- package/dist/graph/index.d.ts +9 -9
- package/dist/graph/index.js +18 -17
- package/dist/{graph-DfdF9zy4.d.ts → graph-D-1-SQeC.d.ts} +3 -3
- package/dist/{graph-s23RbbFO.d.cts → graph-DCEWh4T2.d.cts} +3 -3
- package/dist/{index-CAEmLCYF.d.cts → index-72VZC0-E.d.cts} +2 -2
- package/dist/{index-SnzZu3x7.d.ts → index-Bmxeu0nK.d.ts} +2 -2
- package/dist/index.cjs +112 -58
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -10
- package/dist/index.d.ts +11 -10
- package/dist/index.js +118 -113
- package/dist/inspection/boundary.cjs +98 -0
- package/dist/inspection/boundary.cjs.map +1 -0
- package/dist/inspection/boundary.d.cts +61 -0
- package/dist/inspection/boundary.d.ts +61 -0
- package/dist/inspection/boundary.js +75 -0
- package/dist/inspection/boundary.js.map +1 -0
- package/dist/{messages-BZqrGGm1.d.ts → messages-CAzUPPJM.d.cts} +10 -5
- package/dist/{messages-BZqrGGm1.d.cts → messages-CAzUPPJM.d.ts} +10 -5
- package/dist/messaging/index.cjs +744 -613
- package/dist/messaging/index.cjs.map +1 -1
- package/dist/messaging/index.d.cts +216 -160
- package/dist/messaging/index.d.ts +216 -160
- package/dist/messaging/index.js +19 -749
- package/dist/messaging/index.js.map +1 -1
- package/dist/operators/index.cjs +102 -57
- package/dist/operators/index.cjs.map +1 -1
- package/dist/operators/index.d.cts +6 -6
- package/dist/operators/index.d.ts +6 -6
- package/dist/operators/index.js +8 -7
- package/dist/orchestration/index.cjs +3333 -59
- package/dist/orchestration/index.cjs.map +1 -1
- package/dist/orchestration/index.d.cts +7 -4
- package/dist/orchestration/index.d.ts +7 -4
- package/dist/orchestration/index.js +49 -8
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/messaging.cjs +314 -0
- package/dist/orchestration/messaging.cjs.map +1 -0
- package/dist/orchestration/messaging.d.cts +59 -0
- package/dist/orchestration/messaging.d.ts +59 -0
- package/dist/orchestration/messaging.js +276 -0
- package/dist/orchestration/messaging.js.map +1 -0
- package/dist/orchestration/work-queue.cjs +262 -0
- package/dist/orchestration/work-queue.cjs.map +1 -0
- package/dist/orchestration/work-queue.d.cts +85 -0
- package/dist/orchestration/work-queue.d.ts +85 -0
- package/dist/orchestration/work-queue.js +226 -0
- package/dist/orchestration/work-queue.js.map +1 -0
- package/dist/patterns/event-flow.cjs +447 -0
- package/dist/patterns/event-flow.cjs.map +1 -0
- package/dist/patterns/event-flow.d.cts +115 -0
- package/dist/patterns/event-flow.d.ts +115 -0
- package/dist/patterns/event-flow.js +14 -0
- package/dist/patterns/event-flow.js.map +1 -0
- package/dist/patterns/index.cjs +423 -18
- package/dist/patterns/index.cjs.map +1 -1
- package/dist/patterns/index.d.cts +8 -5
- package/dist/patterns/index.d.ts +8 -5
- package/dist/patterns/index.js +13 -4
- package/dist/{reactive-collection-Cb1II1Fi.d.ts → reactive-collection-BAmfrGjd.d.ts} +9 -9
- package/dist/{reactive-collection-BxBqtIOE.d.cts → reactive-collection-DNV0-gFi.d.cts} +9 -9
- package/dist/{reactive-collection-storage-D-KmjE0J.d.cts → reactive-collection-storage-BNEldDyi.d.cts} +5 -5
- package/dist/{reactive-collection-storage-BNiEc-Gd.d.ts → reactive-collection-storage-YZsAQsWK.d.ts} +5 -5
- package/dist/{reactive-map-D-g3dv8I.d.cts → reactive-map-DRD1LJ2H.d.cts} +6 -6
- package/dist/{reactive-map-BcB4KsQR.d.ts → reactive-map-EsDiCmJk.d.ts} +6 -6
- package/dist/render/index.d.cts +3 -3
- package/dist/render/index.d.ts +3 -3
- package/dist/render/index.js +1 -0
- package/dist/{semantic-memory-graph-BYoIlP35.d.cts → semantic-memory-graph-DKuNzuWw.d.cts} +2 -2
- package/dist/{semantic-memory-graph-CxyXLms3.d.ts → semantic-memory-graph-uwbwJdhe.d.ts} +2 -2
- package/dist/solutions/index.cjs +4478 -2
- package/dist/solutions/index.cjs.map +1 -1
- package/dist/solutions/index.d.cts +13 -519
- package/dist/solutions/index.d.ts +13 -519
- package/dist/solutions/index.js +90 -6
- package/dist/solutions/reactive-layout/browser/index.cjs +449 -0
- package/dist/solutions/reactive-layout/browser/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/browser/index.d.cts +44 -0
- package/dist/solutions/reactive-layout/browser/index.d.ts +44 -0
- package/dist/solutions/reactive-layout/browser/index.js +69 -0
- package/dist/solutions/reactive-layout/browser/index.js.map +1 -0
- package/dist/solutions/reactive-layout/index.cjs +4266 -0
- package/dist/solutions/reactive-layout/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/index.d.cts +581 -0
- package/dist/solutions/reactive-layout/index.d.ts +581 -0
- package/dist/solutions/reactive-layout/index.js +86 -0
- package/dist/solutions/reactive-layout/index.js.map +1 -0
- package/dist/solutions/reactive-layout/node-canvas/index.cjs +545 -0
- package/dist/solutions/reactive-layout/node-canvas/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/node-canvas/index.d.cts +54 -0
- package/dist/solutions/reactive-layout/node-canvas/index.d.ts +54 -0
- package/dist/solutions/reactive-layout/node-canvas/index.js +131 -0
- package/dist/solutions/reactive-layout/node-canvas/index.js.map +1 -0
- package/dist/solutions/reactive-layout/react-native/index.cjs +494 -0
- package/dist/solutions/reactive-layout/react-native/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/react-native/index.d.cts +51 -0
- package/dist/solutions/reactive-layout/react-native/index.d.ts +51 -0
- package/dist/solutions/reactive-layout/react-native/index.js +77 -0
- package/dist/solutions/reactive-layout/react-native/index.js.map +1 -0
- package/dist/solutions/reactive-layout/skia/index.cjs +547 -0
- package/dist/solutions/reactive-layout/skia/index.cjs.map +1 -0
- package/dist/solutions/reactive-layout/skia/index.d.cts +64 -0
- package/dist/solutions/reactive-layout/skia/index.d.ts +64 -0
- package/dist/solutions/reactive-layout/skia/index.js +70 -0
- package/dist/solutions/reactive-layout/skia/index.js.map +1 -0
- package/dist/solutions/work-item/actions.cjs +2164 -0
- package/dist/solutions/work-item/actions.cjs.map +1 -0
- package/dist/solutions/work-item/actions.d.cts +201 -0
- package/dist/solutions/work-item/actions.d.ts +201 -0
- package/dist/solutions/work-item/actions.js +1454 -0
- package/dist/solutions/work-item/actions.js.map +1 -0
- package/dist/solutions/work-item/scheduling.cjs +2454 -0
- package/dist/solutions/work-item/scheduling.cjs.map +1 -0
- package/dist/solutions/work-item/scheduling.d.cts +433 -0
- package/dist/solutions/work-item/scheduling.d.ts +433 -0
- package/dist/solutions/work-item/scheduling.js +32 -0
- package/dist/solutions/work-item/scheduling.js.map +1 -0
- package/dist/solutions/work-item/work-queue.cjs +306 -0
- package/dist/solutions/work-item/work-queue.cjs.map +1 -0
- package/dist/solutions/work-item/work-queue.d.cts +71 -0
- package/dist/solutions/work-item/work-queue.d.ts +71 -0
- package/dist/solutions/work-item/work-queue.js +270 -0
- package/dist/solutions/work-item/work-queue.js.map +1 -0
- package/dist/sources/browser.cjs +169 -57
- package/dist/sources/browser.cjs.map +1 -1
- package/dist/sources/browser.d.cts +33 -6
- package/dist/sources/browser.d.ts +33 -6
- package/dist/sources/browser.js +73 -6
- package/dist/sources/browser.js.map +1 -1
- package/dist/sources/index.cjs +102 -57
- package/dist/sources/index.cjs.map +1 -1
- package/dist/sources/index.d.cts +5 -5
- package/dist/sources/index.d.ts +5 -5
- package/dist/sources/index.js +6 -5
- package/dist/sources/node.cjs.map +1 -1
- package/dist/sources/node.d.cts +4 -4
- package/dist/sources/node.d.ts +4 -4
- package/dist/sources/node.js +2 -1
- package/dist/sources/node.js.map +1 -1
- package/dist/storage/browser.js +1 -0
- package/dist/storage/browser.js.map +1 -1
- package/dist/storage/index.d.cts +5 -5
- package/dist/storage/index.d.ts +5 -5
- package/dist/storage/index.js +5 -4
- package/dist/storage/node.js +1 -0
- package/dist/storage/node.js.map +1 -1
- package/dist/store-C-joM4gh.d.ts +123 -0
- package/dist/store-CNJwmT-h.d.cts +123 -0
- package/dist/testing/index.cjs +1 -0
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/index.js +3 -2
- package/dist/{types-h12mNYbq.d.ts → types-BsJvElYZ.d.ts} +31 -31
- package/dist/{types-bNMSWKqF.d.cts → types-CcPIn7sy.d.cts} +31 -31
- package/dist/work-item-runtime-C3M79vE9.d.ts +228 -0
- package/dist/work-item-runtime-qaVgsL0T.d.cts +228 -0
- package/dist/work-queue/index.cjs +1132 -0
- package/dist/work-queue/index.cjs.map +1 -0
- package/dist/work-queue/index.d.cts +369 -0
- package/dist/work-queue/index.d.ts +369 -0
- package/dist/work-queue/index.js +1078 -0
- package/dist/work-queue/index.js.map +1 -0
- package/package.json +266 -2
- package/dist/chunk-COHO25CZ.js.map +0 -1
- package/dist/chunk-DK554R7P.js.map +0 -1
- package/dist/chunk-I3IHOHCJ.js.map +0 -1
- package/dist/chunk-RIIOUTGM.js.map +0 -1
- package/dist/chunk-SWTLEQL6.js.map +0 -1
- /package/dist/{chunk-JR4IKCR2.js.map → chunk-2747WN4Y.js.map} +0 -0
- /package/dist/{chunk-GDL26N2T.js.map → chunk-3KN7NJDR.js.map} +0 -0
- /package/dist/{chunk-DJC4CHLQ.js.map → chunk-43BKLFZU.js.map} +0 -0
- /package/dist/{chunk-SCRFRCGR.js.map → chunk-BSQGE5PS.js.map} +0 -0
- /package/dist/{chunk-Y3ZLRGHC.js.map → chunk-CZNV3VXM.js.map} +0 -0
- /package/dist/{chunk-JIMUDQN3.js.map → chunk-FBUU43PM.js.map} +0 -0
- /package/dist/{chunk-D6BG7U6A.js.map → chunk-IXZBUWSP.js.map} +0 -0
- /package/dist/{chunk-PKVBHGBM.js.map → chunk-SS2A464I.js.map} +0 -0
- /package/dist/{chunk-G4M3NHRJ.js.map → chunk-V7CIJE4B.js.map} +0 -0
- /package/dist/{chunk-TEW47IVR.js.map → chunk-VPEFSDME.js.map} +0 -0
|
@@ -0,0 +1,879 @@
|
|
|
1
|
+
import {
|
|
2
|
+
attachMessageBusCommandSource,
|
|
3
|
+
getMessageBusState,
|
|
4
|
+
registerMessageBusState
|
|
5
|
+
} from "./chunk-UT3MHJCW.js";
|
|
6
|
+
import {
|
|
7
|
+
depBatch
|
|
8
|
+
} from "./chunk-WQIA3GFB.js";
|
|
9
|
+
|
|
10
|
+
// src/messaging/index.ts
|
|
11
|
+
function eventMessage(type, payload, opts) {
|
|
12
|
+
assertNonEmpty(type, "eventMessage.type");
|
|
13
|
+
assertNonEmpty(opts.id, "eventMessage.id");
|
|
14
|
+
return {
|
|
15
|
+
id: opts.id,
|
|
16
|
+
type,
|
|
17
|
+
payload,
|
|
18
|
+
...opts.key === void 0 ? {} : { key: opts.key },
|
|
19
|
+
...opts.subjectId === void 0 ? {} : { subjectId: opts.subjectId },
|
|
20
|
+
...opts.correlationId === void 0 ? {} : { correlationId: opts.correlationId },
|
|
21
|
+
...opts.causationId === void 0 ? {} : { causationId: opts.causationId },
|
|
22
|
+
...opts.occurredAtMs === void 0 ? {} : { occurredAtMs: opts.occurredAtMs },
|
|
23
|
+
...opts.actor === void 0 ? {} : { actor: opts.actor },
|
|
24
|
+
...opts.evidenceRefs === void 0 ? {} : { evidenceRefs: opts.evidenceRefs },
|
|
25
|
+
...opts.schema === void 0 ? {} : { schema: opts.schema },
|
|
26
|
+
...opts.metadata === void 0 ? {} : { metadata: opts.metadata }
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function isEventMessage(value) {
|
|
30
|
+
return eventMessageIssue(value) === void 0;
|
|
31
|
+
}
|
|
32
|
+
function eventMessageIssue(value) {
|
|
33
|
+
if (!isObjectRecord(value)) {
|
|
34
|
+
return eventIssue("event message must be an object");
|
|
35
|
+
}
|
|
36
|
+
if (typeof value.id !== "string" || value.id.length === 0) {
|
|
37
|
+
return eventIssue("event message id must be a non-empty string");
|
|
38
|
+
}
|
|
39
|
+
if (typeof value.type !== "string" || value.type.length === 0) {
|
|
40
|
+
return eventIssue("event message type must be a non-empty string");
|
|
41
|
+
}
|
|
42
|
+
if (!("payload" in value)) {
|
|
43
|
+
return eventIssue("event message payload field is required");
|
|
44
|
+
}
|
|
45
|
+
return void 0;
|
|
46
|
+
}
|
|
47
|
+
function eventIssue(message) {
|
|
48
|
+
return {
|
|
49
|
+
kind: "issue",
|
|
50
|
+
code: "malformed-event-message",
|
|
51
|
+
message,
|
|
52
|
+
severity: "error",
|
|
53
|
+
source: "messageBus.eventMessage"
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
var PROMPTS_TOPIC = "prompts";
|
|
57
|
+
var RESPONSES_TOPIC = "responses";
|
|
58
|
+
var INJECTIONS_TOPIC = "injections";
|
|
59
|
+
var DEFERRED_TOPIC = "deferred";
|
|
60
|
+
var SPAWNS_TOPIC = "spawns";
|
|
61
|
+
var CONTEXT_TOPIC = "context";
|
|
62
|
+
var TODOS_TOPIC = "todos";
|
|
63
|
+
var STANDARD_TOPICS = Object.freeze([
|
|
64
|
+
PROMPTS_TOPIC,
|
|
65
|
+
RESPONSES_TOPIC,
|
|
66
|
+
INJECTIONS_TOPIC,
|
|
67
|
+
DEFERRED_TOPIC,
|
|
68
|
+
SPAWNS_TOPIC,
|
|
69
|
+
CONTEXT_TOPIC,
|
|
70
|
+
TODOS_TOPIC
|
|
71
|
+
]);
|
|
72
|
+
function messageBus(graph, opts = {}) {
|
|
73
|
+
const name = opts.name ?? "messageBus";
|
|
74
|
+
const initialTopics = uniqueTopics(opts.topics ?? []);
|
|
75
|
+
const commandSources = [];
|
|
76
|
+
const commandBody = (ctx) => {
|
|
77
|
+
for (let i = 0; i < commandSources.length; i++) {
|
|
78
|
+
for (const command of depBatch(ctx, i) ?? []) ctx.down([["DATA", command]]);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const commands = graph.node([], commandBody, {
|
|
82
|
+
name: `${name}/commands`,
|
|
83
|
+
factory: "messageBusCommands",
|
|
84
|
+
completeWhenDepsComplete: false,
|
|
85
|
+
errorWhenDepsError: false
|
|
86
|
+
});
|
|
87
|
+
const state = {
|
|
88
|
+
graph,
|
|
89
|
+
name,
|
|
90
|
+
now: opts.now ?? Date.now,
|
|
91
|
+
topicPolicy: opts.topicPolicy ?? "strict",
|
|
92
|
+
retention: opts.retention ?? {},
|
|
93
|
+
dedupe: opts.dedupe ?? { commandId: "status" },
|
|
94
|
+
topics: new Map(initialTopics.map((topic) => [topic, makeTopicState()])),
|
|
95
|
+
subscriptions: /* @__PURE__ */ new Map(),
|
|
96
|
+
seenCommandIds: /* @__PURE__ */ new Set(),
|
|
97
|
+
seenIdempotencyKeys: /* @__PURE__ */ new Set(),
|
|
98
|
+
deadLetters: [],
|
|
99
|
+
deadLetterSeq: 0,
|
|
100
|
+
commandSources,
|
|
101
|
+
commandBody
|
|
102
|
+
};
|
|
103
|
+
const runtime = graph.node(
|
|
104
|
+
[commands],
|
|
105
|
+
(ctx) => {
|
|
106
|
+
for (const command of depBatch(ctx, 0) ?? []) {
|
|
107
|
+
for (const event of reduceMessageBusCommand(state, command)) {
|
|
108
|
+
ctx.down([["DATA", event]]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: `${name}/runtime`,
|
|
114
|
+
factory: "messageBusRuntime",
|
|
115
|
+
completeWhenDepsComplete: false,
|
|
116
|
+
errorWhenDepsError: false
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
graph.retain(runtime, { reason: `${name}.messageBus.runtime` });
|
|
120
|
+
const messages = graph.node(
|
|
121
|
+
[runtime],
|
|
122
|
+
(ctx) => {
|
|
123
|
+
for (const event of depBatch(ctx, 0) ?? []) {
|
|
124
|
+
const typed = event;
|
|
125
|
+
if (typed.kind === "message") ctx.down([["DATA", typed.message]]);
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: `${name}/messages`,
|
|
130
|
+
factory: "messageBusMessages",
|
|
131
|
+
completeWhenDepsComplete: false,
|
|
132
|
+
errorWhenDepsError: false
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
const status = graph.node(
|
|
136
|
+
[runtime],
|
|
137
|
+
(ctx) => {
|
|
138
|
+
for (const event of depBatch(ctx, 0) ?? []) {
|
|
139
|
+
const typed = event;
|
|
140
|
+
if (typed.kind === "status") ctx.down([["DATA", typed.status]]);
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: `${name}/status`,
|
|
145
|
+
factory: "messageBusStatus",
|
|
146
|
+
completeWhenDepsComplete: false,
|
|
147
|
+
errorWhenDepsError: false
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
const issues = graph.node(
|
|
151
|
+
[runtime],
|
|
152
|
+
(ctx) => {
|
|
153
|
+
for (const event of depBatch(ctx, 0) ?? []) {
|
|
154
|
+
const typed = event;
|
|
155
|
+
if (typed.kind === "issue") ctx.down([["DATA", typed.issue]]);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: `${name}/issues`,
|
|
160
|
+
factory: "messageBusIssues",
|
|
161
|
+
completeWhenDepsComplete: false,
|
|
162
|
+
errorWhenDepsError: false
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
const bus = {
|
|
166
|
+
commands,
|
|
167
|
+
messages,
|
|
168
|
+
status,
|
|
169
|
+
issues,
|
|
170
|
+
ensureTopic(topic, commandOpts = {}) {
|
|
171
|
+
return publishCommand(commands, {
|
|
172
|
+
kind: "ensure-topic",
|
|
173
|
+
topic,
|
|
174
|
+
...commandOpts.commandId === void 0 ? {} : { commandId: commandOpts.commandId }
|
|
175
|
+
});
|
|
176
|
+
},
|
|
177
|
+
closeTopic(topic, commandOpts = {}) {
|
|
178
|
+
return publishCommand(commands, {
|
|
179
|
+
kind: "close-topic",
|
|
180
|
+
topic,
|
|
181
|
+
...commandOpts.commandId === void 0 ? {} : { commandId: commandOpts.commandId }
|
|
182
|
+
});
|
|
183
|
+
},
|
|
184
|
+
publish(topic, payload, publishOpts = {}) {
|
|
185
|
+
return publishCommand(commands, {
|
|
186
|
+
kind: "publish",
|
|
187
|
+
topic,
|
|
188
|
+
payload,
|
|
189
|
+
...publishOpts.key === void 0 ? {} : { key: publishOpts.key },
|
|
190
|
+
...publishOpts.commandId === void 0 ? {} : { commandId: publishOpts.commandId },
|
|
191
|
+
...publishOpts.idempotencyKey === void 0 ? {} : { idempotencyKey: publishOpts.idempotencyKey }
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
topic(topic, projectionOpts = {}) {
|
|
195
|
+
assertTopicKey(topic, "messageBus.topic");
|
|
196
|
+
const snapshotPullId = /* @__PURE__ */ Symbol(`${name}/${topic}/topicSnapshot`);
|
|
197
|
+
const snapshot = graph.node(
|
|
198
|
+
[messages],
|
|
199
|
+
(ctx) => {
|
|
200
|
+
const params = pullParams(ctx.pull);
|
|
201
|
+
ctx.down([["DATA", topicPage(state, topic, params)]]);
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
name: projectionOpts.name ?? `${name}/${topic}/topic`,
|
|
205
|
+
factory: "messageBusTopicProjection",
|
|
206
|
+
meta: { topic },
|
|
207
|
+
pullId: snapshotPullId,
|
|
208
|
+
partial: true,
|
|
209
|
+
completeWhenDepsComplete: false,
|
|
210
|
+
errorWhenDepsError: false
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
return { snapshot, snapshotPullId, status, issues };
|
|
214
|
+
},
|
|
215
|
+
catalog(projectionOpts = {}) {
|
|
216
|
+
const snapshotPullId = /* @__PURE__ */ Symbol(`${name}/catalogSnapshot`);
|
|
217
|
+
const snapshot = graph.node(
|
|
218
|
+
[runtime],
|
|
219
|
+
(ctx) => {
|
|
220
|
+
const params = pullParams(ctx.pull);
|
|
221
|
+
ctx.down([["DATA", catalogPage(state, params)]]);
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
name: projectionOpts.name ?? `${name}/catalog`,
|
|
225
|
+
factory: "messageBusCatalog",
|
|
226
|
+
pullId: snapshotPullId,
|
|
227
|
+
partial: true,
|
|
228
|
+
completeWhenDepsComplete: false,
|
|
229
|
+
errorWhenDepsError: false
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
return { snapshot, snapshotPullId, status, issues };
|
|
233
|
+
},
|
|
234
|
+
deadLetter(projectionOpts = {}) {
|
|
235
|
+
const snapshotPullId = /* @__PURE__ */ Symbol(`${name}/deadLetterSnapshot`);
|
|
236
|
+
const snapshot = graph.node(
|
|
237
|
+
[runtime],
|
|
238
|
+
(ctx) => {
|
|
239
|
+
const params = pullParams(ctx.pull);
|
|
240
|
+
ctx.down([["DATA", deadLetterPage(state, params)]]);
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
name: projectionOpts.name ?? `${name}/deadLetter`,
|
|
244
|
+
factory: "messageBusDeadLetter",
|
|
245
|
+
pullId: snapshotPullId,
|
|
246
|
+
partial: true,
|
|
247
|
+
completeWhenDepsComplete: false,
|
|
248
|
+
errorWhenDepsError: false
|
|
249
|
+
}
|
|
250
|
+
);
|
|
251
|
+
return { snapshot, snapshotPullId, status, issues };
|
|
252
|
+
},
|
|
253
|
+
subscription(subscriptionOpts) {
|
|
254
|
+
assertTopicKey(subscriptionOpts.topic, "messageBus.subscription");
|
|
255
|
+
assertNonEmpty(subscriptionOpts.subscriptionId, "messageBus.subscriptionId");
|
|
256
|
+
const sub = ensureSubscription(state, {
|
|
257
|
+
topic: subscriptionOpts.topic,
|
|
258
|
+
subscriptionId: subscriptionOpts.subscriptionId,
|
|
259
|
+
from: subscriptionOpts.from ?? "earliest"
|
|
260
|
+
});
|
|
261
|
+
const availablePullId = /* @__PURE__ */ Symbol(
|
|
262
|
+
`${name}/${subscriptionOpts.topic}/${subscriptionOpts.subscriptionId}/available`
|
|
263
|
+
);
|
|
264
|
+
const projectionName = subscriptionOpts.name ?? `${name}/${subscriptionOpts.topic}/${subscriptionOpts.subscriptionId}`;
|
|
265
|
+
const available = graph.node(
|
|
266
|
+
[messages, status],
|
|
267
|
+
(ctx) => {
|
|
268
|
+
const params = pullParams(ctx.pull);
|
|
269
|
+
ctx.down([["DATA", availablePage(state, sub, params)]]);
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: `${projectionName}/available`,
|
|
273
|
+
factory: "messageBusSubscriptionAvailable",
|
|
274
|
+
meta: { topic: subscriptionOpts.topic, subscriptionId: subscriptionOpts.subscriptionId },
|
|
275
|
+
pullId: availablePullId,
|
|
276
|
+
partial: true,
|
|
277
|
+
completeWhenDepsComplete: false,
|
|
278
|
+
errorWhenDepsError: false
|
|
279
|
+
}
|
|
280
|
+
);
|
|
281
|
+
const cursor = graph.node(
|
|
282
|
+
[status],
|
|
283
|
+
(ctx) => {
|
|
284
|
+
for (const fact of depBatch(ctx, 0) ?? []) {
|
|
285
|
+
const typed = fact;
|
|
286
|
+
const subscriptionMoved = typed.topic === sub.topic && typed.subscriptionId === sub.subscriptionId && (typed.kind === "subscription-acked" || typed.kind === "subscription-sought" || typed.kind === "subscription-closed");
|
|
287
|
+
const retentionMoved = typed.topic === sub.topic && typed.kind === "retention-trimmed";
|
|
288
|
+
if (subscriptionMoved || retentionMoved) {
|
|
289
|
+
ctx.down([["DATA", cursorSnapshot(state, sub)]]);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
name: `${projectionName}/cursor`,
|
|
295
|
+
factory: "messageBusSubscriptionCursor",
|
|
296
|
+
completeWhenDepsComplete: false,
|
|
297
|
+
errorWhenDepsError: false
|
|
298
|
+
}
|
|
299
|
+
);
|
|
300
|
+
return {
|
|
301
|
+
available,
|
|
302
|
+
availablePullId,
|
|
303
|
+
cursor,
|
|
304
|
+
status,
|
|
305
|
+
issues,
|
|
306
|
+
ack(seq, commandOpts = {}) {
|
|
307
|
+
return publishCommand(commands, {
|
|
308
|
+
kind: "ack",
|
|
309
|
+
topic: sub.topic,
|
|
310
|
+
subscriptionId: sub.subscriptionId,
|
|
311
|
+
seq,
|
|
312
|
+
...commandOpts.commandId === void 0 ? {} : { commandId: commandOpts.commandId }
|
|
313
|
+
});
|
|
314
|
+
},
|
|
315
|
+
seek(nextSeq, commandOpts = {}) {
|
|
316
|
+
return publishCommand(commands, {
|
|
317
|
+
kind: "seek",
|
|
318
|
+
topic: sub.topic,
|
|
319
|
+
subscriptionId: sub.subscriptionId,
|
|
320
|
+
nextSeq,
|
|
321
|
+
...commandOpts.commandId === void 0 ? {} : { commandId: commandOpts.commandId }
|
|
322
|
+
});
|
|
323
|
+
},
|
|
324
|
+
close(commandOpts = {}) {
|
|
325
|
+
return publishCommand(commands, {
|
|
326
|
+
kind: "close-subscription",
|
|
327
|
+
topic: sub.topic,
|
|
328
|
+
subscriptionId: sub.subscriptionId,
|
|
329
|
+
...commandOpts.commandId === void 0 ? {} : { commandId: commandOpts.commandId }
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
registerMessageBusState(bus, state);
|
|
336
|
+
return bus;
|
|
337
|
+
}
|
|
338
|
+
function fromTopic(bus, topic) {
|
|
339
|
+
return bus.topic(topic).snapshot;
|
|
340
|
+
}
|
|
341
|
+
function toTopic(graph, source, bus, topic, opts = {}) {
|
|
342
|
+
const state = getMessageBusState(bus);
|
|
343
|
+
if (state === void 0) throw new Error("toTopic: unknown message bus implementation");
|
|
344
|
+
if (state.graph !== graph) throw new Error("toTopic: bus and source graph must match");
|
|
345
|
+
assertTopicKey(topic, "toTopic");
|
|
346
|
+
const commands = graph.node(
|
|
347
|
+
[source],
|
|
348
|
+
(ctx) => {
|
|
349
|
+
for (const value of depBatch(ctx, 0) ?? []) {
|
|
350
|
+
const key = opts.keyOf?.(value);
|
|
351
|
+
const commandId = opts.commandIdOf?.(value);
|
|
352
|
+
ctx.down([
|
|
353
|
+
[
|
|
354
|
+
"DATA",
|
|
355
|
+
{
|
|
356
|
+
kind: "publish",
|
|
357
|
+
topic,
|
|
358
|
+
payload: value,
|
|
359
|
+
...key === void 0 ? {} : { key },
|
|
360
|
+
...commandId === void 0 ? {} : { commandId }
|
|
361
|
+
}
|
|
362
|
+
]
|
|
363
|
+
]);
|
|
364
|
+
}
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
name: opts.name ?? `${state.name}/${topic}/toTopic`,
|
|
368
|
+
factory: "toTopic",
|
|
369
|
+
meta: { topic },
|
|
370
|
+
completeWhenDepsComplete: false,
|
|
371
|
+
errorWhenDepsError: false
|
|
372
|
+
}
|
|
373
|
+
);
|
|
374
|
+
const releaseSource = attachMessageBusCommandSource(
|
|
375
|
+
graph,
|
|
376
|
+
bus,
|
|
377
|
+
commands
|
|
378
|
+
);
|
|
379
|
+
let released = false;
|
|
380
|
+
return {
|
|
381
|
+
commands,
|
|
382
|
+
release() {
|
|
383
|
+
if (released) return;
|
|
384
|
+
released = true;
|
|
385
|
+
releaseSource();
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function reduceMessageBusCommand(state, command) {
|
|
390
|
+
const malformed = validateCommand(command);
|
|
391
|
+
if (malformed !== void 0) return rejectCommand(state, command, malformed);
|
|
392
|
+
if (command.commandId !== void 0) {
|
|
393
|
+
if (state.seenCommandIds.has(command.commandId)) {
|
|
394
|
+
return duplicateCommandEvents(state, command, "duplicate commandId");
|
|
395
|
+
}
|
|
396
|
+
state.seenCommandIds.add(command.commandId);
|
|
397
|
+
}
|
|
398
|
+
if (command.kind === "publish" && command.idempotencyKey !== void 0 && state.seenIdempotencyKeys.has(idempotencyKey(command.topic, command.idempotencyKey))) {
|
|
399
|
+
return duplicateCommandEvents(state, command, "duplicate idempotencyKey");
|
|
400
|
+
}
|
|
401
|
+
switch (command.kind) {
|
|
402
|
+
case "ensure-topic":
|
|
403
|
+
return ensureTopic(state, command.topic, command.commandId);
|
|
404
|
+
case "close-topic": {
|
|
405
|
+
const topic = state.topics.get(command.topic);
|
|
406
|
+
if (topic === void 0) {
|
|
407
|
+
return issueEvents(state, command, "unknown-topic", `unknown topic '${command.topic}'`);
|
|
408
|
+
}
|
|
409
|
+
topic.closed = true;
|
|
410
|
+
return [
|
|
411
|
+
{
|
|
412
|
+
kind: "status",
|
|
413
|
+
status: statusFact(state, "topic-closed", {
|
|
414
|
+
topic: command.topic,
|
|
415
|
+
commandId: command.commandId
|
|
416
|
+
})
|
|
417
|
+
}
|
|
418
|
+
];
|
|
419
|
+
}
|
|
420
|
+
case "topic-policy":
|
|
421
|
+
state.topicPolicy = command.topicPolicy;
|
|
422
|
+
return [
|
|
423
|
+
{
|
|
424
|
+
kind: "status",
|
|
425
|
+
status: statusFact(state, "projection-ready", {
|
|
426
|
+
commandId: command.commandId,
|
|
427
|
+
details: { topicPolicy: command.topicPolicy }
|
|
428
|
+
})
|
|
429
|
+
}
|
|
430
|
+
];
|
|
431
|
+
case "publish":
|
|
432
|
+
return publishMessage(state, command);
|
|
433
|
+
case "ack":
|
|
434
|
+
return ackSubscription(state, command);
|
|
435
|
+
case "seek":
|
|
436
|
+
return seekSubscription(state, command);
|
|
437
|
+
case "close-subscription":
|
|
438
|
+
return closeSubscription(state, command);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function publishMessage(state, command) {
|
|
442
|
+
let topic = state.topics.get(command.topic);
|
|
443
|
+
const events = [];
|
|
444
|
+
if (topic === void 0) {
|
|
445
|
+
if (state.topicPolicy !== "create-as-fact") {
|
|
446
|
+
return issueEvents(state, command, "unknown-topic", `unknown topic '${command.topic}'`);
|
|
447
|
+
}
|
|
448
|
+
events.push(...ensureTopic(state, command.topic, command.commandId));
|
|
449
|
+
topic = state.topics.get(command.topic);
|
|
450
|
+
}
|
|
451
|
+
if (topic === void 0)
|
|
452
|
+
return issueEvents(state, command, "unknown-topic", `unknown topic '${command.topic}'`);
|
|
453
|
+
if (topic.closed)
|
|
454
|
+
return issueEvents(state, command, "closed-topic", `closed topic '${command.topic}'`);
|
|
455
|
+
const message = {
|
|
456
|
+
topic: command.topic,
|
|
457
|
+
seq: topic.nextSeq++,
|
|
458
|
+
payload: command.payload,
|
|
459
|
+
timestampMs: state.now(),
|
|
460
|
+
...command.key === void 0 ? {} : { key: command.key },
|
|
461
|
+
...command.idempotencyKey === void 0 ? {} : { idempotencyKey: command.idempotencyKey },
|
|
462
|
+
...command.commandId === void 0 ? {} : { commandId: command.commandId }
|
|
463
|
+
};
|
|
464
|
+
if (command.idempotencyKey !== void 0) {
|
|
465
|
+
state.seenIdempotencyKeys.add(idempotencyKey(command.topic, command.idempotencyKey));
|
|
466
|
+
}
|
|
467
|
+
topic.messages.push(message);
|
|
468
|
+
events.push({ kind: "message", message });
|
|
469
|
+
events.push({
|
|
470
|
+
kind: "status",
|
|
471
|
+
status: statusFact(state, "message-published", {
|
|
472
|
+
topic: command.topic,
|
|
473
|
+
seq: message.seq,
|
|
474
|
+
commandId: command.commandId
|
|
475
|
+
})
|
|
476
|
+
});
|
|
477
|
+
events.push(...trimRetention(state, command.topic, topic));
|
|
478
|
+
return events;
|
|
479
|
+
}
|
|
480
|
+
function ensureTopic(state, topic, commandId) {
|
|
481
|
+
assertTopicKey(topic, "messageBus");
|
|
482
|
+
if (!state.topics.has(topic)) state.topics.set(topic, makeTopicState());
|
|
483
|
+
return [
|
|
484
|
+
{
|
|
485
|
+
kind: "status",
|
|
486
|
+
status: statusFact(state, "topic-created", { topic, commandId })
|
|
487
|
+
}
|
|
488
|
+
];
|
|
489
|
+
}
|
|
490
|
+
function trimRetention(state, topicName, topic) {
|
|
491
|
+
const max = state.retention.maxMessages;
|
|
492
|
+
if (max === void 0 || topic.messages.length <= max) return [];
|
|
493
|
+
if (!Number.isInteger(max) || max < 1) {
|
|
494
|
+
return issueEvents(
|
|
495
|
+
state,
|
|
496
|
+
{ kind: "publish", topic: topicName, payload: void 0 },
|
|
497
|
+
"policy-rejected",
|
|
498
|
+
"retention.maxMessages must be a positive integer"
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
const trimCount = topic.messages.length - max;
|
|
502
|
+
topic.messages.splice(0, trimCount);
|
|
503
|
+
topic.headSeq = topic.messages[0]?.seq ?? topic.nextSeq;
|
|
504
|
+
const events = [
|
|
505
|
+
{
|
|
506
|
+
kind: "status",
|
|
507
|
+
status: statusFact(state, "retention-trimmed", {
|
|
508
|
+
topic: topicName,
|
|
509
|
+
headSeq: topic.headSeq,
|
|
510
|
+
details: { trimCount }
|
|
511
|
+
})
|
|
512
|
+
}
|
|
513
|
+
];
|
|
514
|
+
for (const sub of state.subscriptions.values()) {
|
|
515
|
+
if (sub.closed || sub.topic !== topicName || sub.nextSeq >= topic.headSeq) continue;
|
|
516
|
+
sub.retentionGap = true;
|
|
517
|
+
events.push(
|
|
518
|
+
...issueEvents(
|
|
519
|
+
state,
|
|
520
|
+
{
|
|
521
|
+
kind: "seek",
|
|
522
|
+
topic: topicName,
|
|
523
|
+
subscriptionId: sub.subscriptionId,
|
|
524
|
+
nextSeq: sub.nextSeq
|
|
525
|
+
},
|
|
526
|
+
"retention-gap",
|
|
527
|
+
`subscription '${sub.subscriptionId}' is before retained headSeq`
|
|
528
|
+
)
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
return events;
|
|
532
|
+
}
|
|
533
|
+
function ackSubscription(state, command) {
|
|
534
|
+
const topic = state.topics.get(command.topic);
|
|
535
|
+
if (topic === void 0)
|
|
536
|
+
return issueEvents(state, command, "unknown-topic", `unknown topic '${command.topic}'`);
|
|
537
|
+
const sub = getSubscription(state, command.topic, command.subscriptionId);
|
|
538
|
+
if (sub === void 0)
|
|
539
|
+
return issueEvents(
|
|
540
|
+
state,
|
|
541
|
+
command,
|
|
542
|
+
"unknown-subscription",
|
|
543
|
+
`unknown subscription '${command.subscriptionId}'`
|
|
544
|
+
);
|
|
545
|
+
if (sub.closed)
|
|
546
|
+
return issueEvents(state, command, "subscription-closed", "subscription is closed");
|
|
547
|
+
if (sub.retentionGap)
|
|
548
|
+
return issueEvents(state, command, "retention-gap", "subscription must seek before ack");
|
|
549
|
+
if (command.seq < sub.nextSeq)
|
|
550
|
+
return issueEvents(state, command, "source-cursor-stale", "ack is behind subscription cursor");
|
|
551
|
+
if (command.seq >= topic.nextSeq)
|
|
552
|
+
return issueEvents(state, command, "cursor-out-of-range", "ack is beyond topic tail");
|
|
553
|
+
sub.nextSeq = Math.max(sub.nextSeq, command.seq + 1);
|
|
554
|
+
return [
|
|
555
|
+
{
|
|
556
|
+
kind: "status",
|
|
557
|
+
status: statusFact(state, "subscription-acked", {
|
|
558
|
+
topic: command.topic,
|
|
559
|
+
subscriptionId: command.subscriptionId,
|
|
560
|
+
nextSeq: sub.nextSeq,
|
|
561
|
+
commandId: command.commandId
|
|
562
|
+
})
|
|
563
|
+
}
|
|
564
|
+
];
|
|
565
|
+
}
|
|
566
|
+
function seekSubscription(state, command) {
|
|
567
|
+
const topic = state.topics.get(command.topic);
|
|
568
|
+
if (topic === void 0)
|
|
569
|
+
return issueEvents(state, command, "unknown-topic", `unknown topic '${command.topic}'`);
|
|
570
|
+
const sub = getSubscription(state, command.topic, command.subscriptionId);
|
|
571
|
+
if (sub === void 0)
|
|
572
|
+
return issueEvents(
|
|
573
|
+
state,
|
|
574
|
+
command,
|
|
575
|
+
"unknown-subscription",
|
|
576
|
+
`unknown subscription '${command.subscriptionId}'`
|
|
577
|
+
);
|
|
578
|
+
if (sub.closed)
|
|
579
|
+
return issueEvents(state, command, "subscription-closed", "subscription is closed");
|
|
580
|
+
if (command.nextSeq < topic.headSeq)
|
|
581
|
+
return issueEvents(state, command, "retention-gap", "seek is before retained headSeq");
|
|
582
|
+
if (command.nextSeq > topic.nextSeq)
|
|
583
|
+
return issueEvents(state, command, "cursor-out-of-range", "seek is beyond topic tail");
|
|
584
|
+
sub.nextSeq = command.nextSeq;
|
|
585
|
+
sub.retentionGap = false;
|
|
586
|
+
return [
|
|
587
|
+
{
|
|
588
|
+
kind: "status",
|
|
589
|
+
status: statusFact(state, "subscription-sought", {
|
|
590
|
+
topic: command.topic,
|
|
591
|
+
subscriptionId: command.subscriptionId,
|
|
592
|
+
nextSeq: sub.nextSeq,
|
|
593
|
+
commandId: command.commandId
|
|
594
|
+
})
|
|
595
|
+
}
|
|
596
|
+
];
|
|
597
|
+
}
|
|
598
|
+
function closeSubscription(state, command) {
|
|
599
|
+
if (!state.topics.has(command.topic))
|
|
600
|
+
return issueEvents(state, command, "unknown-topic", `unknown topic '${command.topic}'`);
|
|
601
|
+
const sub = getSubscription(state, command.topic, command.subscriptionId);
|
|
602
|
+
if (sub === void 0)
|
|
603
|
+
return issueEvents(
|
|
604
|
+
state,
|
|
605
|
+
command,
|
|
606
|
+
"unknown-subscription",
|
|
607
|
+
`unknown subscription '${command.subscriptionId}'`
|
|
608
|
+
);
|
|
609
|
+
sub.closed = true;
|
|
610
|
+
return [
|
|
611
|
+
{
|
|
612
|
+
kind: "status",
|
|
613
|
+
status: statusFact(state, "subscription-closed", {
|
|
614
|
+
topic: command.topic,
|
|
615
|
+
subscriptionId: command.subscriptionId,
|
|
616
|
+
nextSeq: sub.nextSeq,
|
|
617
|
+
commandId: command.commandId
|
|
618
|
+
})
|
|
619
|
+
}
|
|
620
|
+
];
|
|
621
|
+
}
|
|
622
|
+
function issueEvents(state, command, code, message) {
|
|
623
|
+
const topic = commandTopic(command);
|
|
624
|
+
const commandId = commandIdOf(command);
|
|
625
|
+
const issue = {
|
|
626
|
+
kind: "issue",
|
|
627
|
+
code,
|
|
628
|
+
message,
|
|
629
|
+
severity: "error",
|
|
630
|
+
source: "messageBus",
|
|
631
|
+
details: command,
|
|
632
|
+
metadata: topic === void 0 ? void 0 : { topic }
|
|
633
|
+
};
|
|
634
|
+
const entry = {
|
|
635
|
+
entrySeq: ++state.deadLetterSeq,
|
|
636
|
+
...topic === void 0 ? {} : { topic },
|
|
637
|
+
...isObjectRecord(command) ? { command } : {},
|
|
638
|
+
issue,
|
|
639
|
+
timestampMs: state.now()
|
|
640
|
+
};
|
|
641
|
+
state.deadLetters.push(entry);
|
|
642
|
+
return [
|
|
643
|
+
{ kind: "issue", issue },
|
|
644
|
+
{ kind: "dead-letter", entry },
|
|
645
|
+
{
|
|
646
|
+
kind: "status",
|
|
647
|
+
status: statusFact(state, "command-rejected", {
|
|
648
|
+
topic,
|
|
649
|
+
commandId,
|
|
650
|
+
issueCode: code
|
|
651
|
+
})
|
|
652
|
+
}
|
|
653
|
+
];
|
|
654
|
+
}
|
|
655
|
+
function rejectCommand(state, command, reason) {
|
|
656
|
+
return issueEvents(state, command, "malformed-command", reason);
|
|
657
|
+
}
|
|
658
|
+
function duplicateCommandEvents(state, command, message) {
|
|
659
|
+
const status = statusFact(state, "duplicate-command", {
|
|
660
|
+
topic: "topic" in command ? command.topic : void 0,
|
|
661
|
+
commandId: command.commandId
|
|
662
|
+
});
|
|
663
|
+
if (state.dedupe.commandId === "issue") {
|
|
664
|
+
return [
|
|
665
|
+
{ kind: "status", status },
|
|
666
|
+
...issueEvents(state, command, "duplicate-command", message)
|
|
667
|
+
];
|
|
668
|
+
}
|
|
669
|
+
return [{ kind: "status", status }];
|
|
670
|
+
}
|
|
671
|
+
function statusFact(state, kind, fields) {
|
|
672
|
+
return {
|
|
673
|
+
kind,
|
|
674
|
+
timestampMs: state.now(),
|
|
675
|
+
...fields.topic === void 0 ? {} : { topic: fields.topic },
|
|
676
|
+
...fields.seq === void 0 ? {} : { seq: fields.seq },
|
|
677
|
+
...fields.headSeq === void 0 ? {} : { headSeq: fields.headSeq },
|
|
678
|
+
...fields.subscriptionId === void 0 ? {} : { subscriptionId: fields.subscriptionId },
|
|
679
|
+
...fields.nextSeq === void 0 ? {} : { nextSeq: fields.nextSeq },
|
|
680
|
+
...fields.commandId === void 0 ? {} : { commandId: fields.commandId },
|
|
681
|
+
...fields.issueCode === void 0 ? {} : { issueCode: fields.issueCode },
|
|
682
|
+
...fields.details === void 0 ? {} : { details: fields.details }
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
function validateCommand(command) {
|
|
686
|
+
if (!isObjectRecord(command)) return "command must be an object";
|
|
687
|
+
if (typeof command.kind !== "string") return "command kind is required";
|
|
688
|
+
if (!isMessageBusCommandKind(command.kind)) return `unknown command kind '${command.kind}'`;
|
|
689
|
+
if ("topic" in command) {
|
|
690
|
+
if (typeof command.topic !== "string") return "messageBus: topic must be a non-empty string";
|
|
691
|
+
const topicError = validateTopicKey(command.topic, "messageBus");
|
|
692
|
+
if (topicError !== void 0) return topicError;
|
|
693
|
+
}
|
|
694
|
+
if ("subscriptionId" in command && typeof command.subscriptionId !== "string") {
|
|
695
|
+
return "subscriptionId must be a string";
|
|
696
|
+
}
|
|
697
|
+
if (command.kind === "publish" && command.payload === void 0)
|
|
698
|
+
return "publish payload is required";
|
|
699
|
+
if (command.kind === "ack" && !isPositiveSeq(command.seq))
|
|
700
|
+
return "ack seq must be a positive integer";
|
|
701
|
+
if (command.kind === "seek" && !isPositiveSeq(command.nextSeq)) {
|
|
702
|
+
return "seek nextSeq must be a positive integer";
|
|
703
|
+
}
|
|
704
|
+
if (command.kind === "topic-policy" && command.topicPolicy !== "strict" && command.topicPolicy !== "create-as-fact") {
|
|
705
|
+
return "topicPolicy is not recognized";
|
|
706
|
+
}
|
|
707
|
+
return void 0;
|
|
708
|
+
}
|
|
709
|
+
function isMessageBusCommandKind(kind) {
|
|
710
|
+
return kind === "ensure-topic" || kind === "close-topic" || kind === "publish" || kind === "topic-policy" || kind === "ack" || kind === "seek" || kind === "close-subscription";
|
|
711
|
+
}
|
|
712
|
+
function catalogPage(state, params) {
|
|
713
|
+
const limit = positiveLimit(params.limit);
|
|
714
|
+
const topics = [...state.topics.entries()].filter(
|
|
715
|
+
([topic, value]) => (params.includeClosed ? true : !value.closed) && (params.afterTopic === void 0 || topic > params.afterTopic)
|
|
716
|
+
).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
717
|
+
const page = topics.slice(0, limit);
|
|
718
|
+
const hasMore = topics.length > limit;
|
|
719
|
+
return {
|
|
720
|
+
topics: page.map(([topic, value]) => ({
|
|
721
|
+
topic,
|
|
722
|
+
closed: value.closed,
|
|
723
|
+
headSeq: value.headSeq,
|
|
724
|
+
nextSeq: value.nextSeq,
|
|
725
|
+
messageCount: value.messages.length
|
|
726
|
+
})),
|
|
727
|
+
...hasMore && page.length > 0 ? { nextAfterTopic: page[page.length - 1]?.[0] } : {},
|
|
728
|
+
hasMore
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
function topicPage(state, topicName, params) {
|
|
732
|
+
const topic = state.topics.get(topicName);
|
|
733
|
+
const start = params.afterSeq === void 0 ? topic?.headSeq ?? 1 : params.afterSeq + 1;
|
|
734
|
+
const all = (topic?.messages ?? []).filter((message) => message.seq >= start);
|
|
735
|
+
const limit = positiveLimit(params.limit);
|
|
736
|
+
const messages = all.slice(0, limit);
|
|
737
|
+
const hasMore = all.length > limit;
|
|
738
|
+
return {
|
|
739
|
+
topic: topicName,
|
|
740
|
+
messages,
|
|
741
|
+
fromSeq: start,
|
|
742
|
+
...messages.length > 0 ? { throughSeq: messages[messages.length - 1]?.seq } : {},
|
|
743
|
+
...hasMore && messages.length > 0 ? { nextAfterSeq: messages[messages.length - 1]?.seq } : {},
|
|
744
|
+
hasMore
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
function availablePage(state, sub, params) {
|
|
748
|
+
const cursor = cursorSnapshot(state, sub);
|
|
749
|
+
const start = params.afterSeq === void 0 ? sub.nextSeq : params.afterSeq + 1;
|
|
750
|
+
const topic = state.topics.get(sub.topic);
|
|
751
|
+
const all = sub.retentionGap ? [] : (topic?.messages ?? []).filter((message) => message.seq >= start);
|
|
752
|
+
const limit = positiveLimit(params.limit);
|
|
753
|
+
const messages = all.slice(0, limit);
|
|
754
|
+
const hasMore = all.length > limit;
|
|
755
|
+
return {
|
|
756
|
+
topic: sub.topic,
|
|
757
|
+
subscriptionId: sub.subscriptionId,
|
|
758
|
+
cursor,
|
|
759
|
+
messages,
|
|
760
|
+
fromSeq: start,
|
|
761
|
+
...messages.length > 0 ? { throughSeq: messages[messages.length - 1]?.seq } : {},
|
|
762
|
+
...hasMore && messages.length > 0 ? { nextAfterSeq: messages[messages.length - 1]?.seq } : {},
|
|
763
|
+
hasMore
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
function deadLetterPage(state, params) {
|
|
767
|
+
const limit = positiveLimit(params.limit);
|
|
768
|
+
const entries = state.deadLetters.filter((entry) => {
|
|
769
|
+
if (params.afterEntrySeq !== void 0 && entry.entrySeq <= params.afterEntrySeq) return false;
|
|
770
|
+
if (params.topic !== void 0 && entry.topic !== params.topic) return false;
|
|
771
|
+
if (params.code !== void 0 && entry.issue.code !== params.code) return false;
|
|
772
|
+
return true;
|
|
773
|
+
});
|
|
774
|
+
const page = entries.slice(0, limit);
|
|
775
|
+
const hasMore = entries.length > limit;
|
|
776
|
+
return {
|
|
777
|
+
entries: page,
|
|
778
|
+
...hasMore && page.length > 0 ? { nextAfterEntrySeq: page[page.length - 1]?.entrySeq } : {},
|
|
779
|
+
hasMore
|
|
780
|
+
};
|
|
781
|
+
}
|
|
782
|
+
function cursorSnapshot(state, sub) {
|
|
783
|
+
const topic = state.topics.get(sub.topic);
|
|
784
|
+
return {
|
|
785
|
+
topic: sub.topic,
|
|
786
|
+
subscriptionId: sub.subscriptionId,
|
|
787
|
+
nextSeq: sub.nextSeq,
|
|
788
|
+
closed: sub.closed,
|
|
789
|
+
retentionGap: sub.retentionGap,
|
|
790
|
+
headSeq: topic?.headSeq ?? 1
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
function ensureSubscription(state, opts) {
|
|
794
|
+
const key = `${opts.topic}\0${opts.subscriptionId}`;
|
|
795
|
+
const existing = state.subscriptions.get(key);
|
|
796
|
+
if (existing !== void 0) return existing;
|
|
797
|
+
const topic = state.topics.get(opts.topic);
|
|
798
|
+
const nextSeq = opts.from === "earliest" ? topic?.headSeq ?? 1 : opts.from === "latest" ? topic?.nextSeq ?? 1 : opts.from;
|
|
799
|
+
const sub = {
|
|
800
|
+
topic: opts.topic,
|
|
801
|
+
subscriptionId: opts.subscriptionId,
|
|
802
|
+
nextSeq,
|
|
803
|
+
closed: false,
|
|
804
|
+
retentionGap: topic !== void 0 && nextSeq < topic.headSeq
|
|
805
|
+
};
|
|
806
|
+
state.subscriptions.set(key, sub);
|
|
807
|
+
return sub;
|
|
808
|
+
}
|
|
809
|
+
function getSubscription(state, topic, subscriptionId) {
|
|
810
|
+
return state.subscriptions.get(`${topic}\0${subscriptionId}`);
|
|
811
|
+
}
|
|
812
|
+
function pullParams(pull) {
|
|
813
|
+
return isObjectRecord(pull?.params) ? pull.params : {};
|
|
814
|
+
}
|
|
815
|
+
function publishCommand(commandNode, command) {
|
|
816
|
+
commandNode.down([["DATA", command]]);
|
|
817
|
+
return command;
|
|
818
|
+
}
|
|
819
|
+
function makeTopicState() {
|
|
820
|
+
return { closed: false, headSeq: 1, nextSeq: 1, messages: [] };
|
|
821
|
+
}
|
|
822
|
+
function uniqueTopics(topics) {
|
|
823
|
+
const unique = [...new Set(topics)];
|
|
824
|
+
if (unique.length !== topics.length) throw new Error("messageBus: duplicate topic");
|
|
825
|
+
for (const topic of unique) assertTopicKey(topic, "messageBus");
|
|
826
|
+
return Object.freeze(unique.sort());
|
|
827
|
+
}
|
|
828
|
+
function assertTopicKey(topic, owner) {
|
|
829
|
+
const error = validateTopicKey(topic, owner);
|
|
830
|
+
if (error !== void 0) throw new Error(error);
|
|
831
|
+
}
|
|
832
|
+
function validateTopicKey(topic, owner) {
|
|
833
|
+
if (typeof topic !== "string" || topic.length === 0)
|
|
834
|
+
return `${owner}: topic must be a non-empty string`;
|
|
835
|
+
return void 0;
|
|
836
|
+
}
|
|
837
|
+
function assertNonEmpty(value, owner) {
|
|
838
|
+
if (typeof value !== "string" || value.length === 0)
|
|
839
|
+
throw new Error(`${owner}: must be a non-empty string`);
|
|
840
|
+
}
|
|
841
|
+
function positiveLimit(limit) {
|
|
842
|
+
if (limit === void 0) return 100;
|
|
843
|
+
if (!Number.isInteger(limit) || limit < 1)
|
|
844
|
+
throw new Error("messageBus: limit must be a positive integer");
|
|
845
|
+
return limit;
|
|
846
|
+
}
|
|
847
|
+
function isPositiveSeq(value) {
|
|
848
|
+
return Number.isInteger(value) && value >= 1;
|
|
849
|
+
}
|
|
850
|
+
function isObjectRecord(value) {
|
|
851
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
852
|
+
}
|
|
853
|
+
function commandTopic(command) {
|
|
854
|
+
return isObjectRecord(command) && typeof command.topic === "string" ? command.topic : void 0;
|
|
855
|
+
}
|
|
856
|
+
function commandIdOf(command) {
|
|
857
|
+
return isObjectRecord(command) && typeof command.commandId === "string" ? command.commandId : void 0;
|
|
858
|
+
}
|
|
859
|
+
function idempotencyKey(topic, key) {
|
|
860
|
+
return `${topic}\0${key}`;
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
export {
|
|
864
|
+
eventMessage,
|
|
865
|
+
isEventMessage,
|
|
866
|
+
eventMessageIssue,
|
|
867
|
+
PROMPTS_TOPIC,
|
|
868
|
+
RESPONSES_TOPIC,
|
|
869
|
+
INJECTIONS_TOPIC,
|
|
870
|
+
DEFERRED_TOPIC,
|
|
871
|
+
SPAWNS_TOPIC,
|
|
872
|
+
CONTEXT_TOPIC,
|
|
873
|
+
TODOS_TOPIC,
|
|
874
|
+
STANDARD_TOPICS,
|
|
875
|
+
messageBus,
|
|
876
|
+
fromTopic,
|
|
877
|
+
toTopic
|
|
878
|
+
};
|
|
879
|
+
//# sourceMappingURL=chunk-QFY4AFY4.js.map
|