iterate 0.2.6 → 0.3.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/README.md +86 -76
- package/THIRD_PARTY_NOTICES.md +55 -0
- package/bin/iterate.js +18 -3
- package/dist/api-url-B6404M82.mjs +17 -0
- package/dist/api-url-B6404M82.mjs.map +1 -0
- package/dist/app-ref-BipL0feU.mjs +35 -0
- package/dist/app-ref-BipL0feU.mjs.map +1 -0
- package/dist/app-ref-C1CrgXqX.mjs +7 -0
- package/dist/app-ref-C1CrgXqX.mjs.map +1 -0
- package/dist/app-ref-DYai_om1.mjs +7 -0
- package/dist/app-ref-DYai_om1.mjs.map +1 -0
- package/dist/cli-D0c-pDL_.mjs +1010 -0
- package/dist/cli-D0c-pDL_.mjs.map +1 -0
- package/dist/client.d.ts +3 -0
- package/dist/client.mjs +4 -0
- package/dist/cloudflare-BTm90gQ4.mjs +951 -0
- package/dist/cloudflare-BTm90gQ4.mjs.map +1 -0
- package/dist/contract-s4FW4eES.mjs +309 -0
- package/dist/contract-s4FW4eES.mjs.map +1 -0
- package/dist/document-review/index.d.ts +5 -0
- package/dist/document-review/types.d.ts +107 -0
- package/dist/document-review.mjs +7015 -0
- package/dist/document-review.mjs.map +1 -0
- package/dist/durable-object-processor-durability-CNsTjAJS.mjs +205 -0
- package/dist/durable-object-processor-durability-CNsTjAJS.mjs.map +1 -0
- package/dist/idempotency-DleloJNt.mjs +28 -0
- package/dist/idempotency-DleloJNt.mjs.map +1 -0
- package/dist/index.mjs +1 -1
- package/dist/itx/api-url.d.ts +6 -0
- package/dist/itx/itx-node-client.d.ts +65 -0
- package/dist/itx/itx-session.d.ts +215 -0
- package/dist/itx/owned-rpc-session.d.ts +14 -0
- package/dist/itx/query-client.d.ts +10 -0
- package/dist/itx-api.generated.d.ts +6195 -0
- package/dist/itx-session-sjud8GiT.mjs +534 -0
- package/dist/itx-session-sjud8GiT.mjs.map +1 -0
- package/dist/live-state-BJNqOwFw.mjs +299 -0
- package/dist/live-state-BJNqOwFw.mjs.map +1 -0
- package/dist/next/api.d.ts +479 -0
- package/dist/next/api.mjs +0 -0
- package/dist/next/app-server.d.ts +44 -0
- package/dist/next/app-server.mjs +479 -0
- package/dist/next/app-server.mjs.map +1 -0
- package/dist/next/app-session.d.ts +49 -0
- package/dist/next/app-session.mjs +238 -0
- package/dist/next/app-session.mjs.map +1 -0
- package/dist/next/app.d.ts +29 -0
- package/dist/next/app.mjs +141 -0
- package/dist/next/app.mjs.map +1 -0
- package/dist/next/client/live-state.d.ts +63 -0
- package/dist/next/client/oauth.d.ts +12 -0
- package/dist/next/client/react.d.ts +109 -0
- package/dist/next/client/socket.d.ts +6 -0
- package/dist/next/client.mjs +156 -0
- package/dist/next/client.mjs.map +1 -0
- package/dist/next/expression.d.ts +146 -0
- package/dist/next/expression.mjs +399 -0
- package/dist/next/expression.mjs.map +1 -0
- package/dist/next/lib.d.ts +56 -0
- package/dist/next/lib.mjs +199 -0
- package/dist/next/lib.mjs.map +1 -0
- package/dist/next/oauth-scopes.d.ts +32 -0
- package/dist/next/oauth-scopes.mjs +40 -0
- package/dist/next/oauth-scopes.mjs.map +1 -0
- package/dist/next/oauth.mjs +29 -0
- package/dist/next/oauth.mjs.map +1 -0
- package/dist/next/principal.d.ts +64 -0
- package/dist/next/principal.mjs +98 -0
- package/dist/next/principal.mjs.map +1 -0
- package/dist/next/project-ingress.d.ts +37 -0
- package/dist/next/project-ingress.mjs +75 -0
- package/dist/next/project-ingress.mjs.map +1 -0
- package/dist/next/react.mjs +285 -0
- package/dist/next/react.mjs.map +1 -0
- package/dist/next/sdk/auth.d.ts +5 -0
- package/dist/next/sdk/index.d.ts +112 -0
- package/dist/next/sdk.mjs +139 -0
- package/dist/next/sdk.mjs.map +1 -0
- package/dist/next/stream/processor.d.ts +378 -0
- package/dist/next/stream/processor.mjs +582 -0
- package/dist/next/stream/processor.mjs.map +1 -0
- package/dist/next/stream/run.d.ts +58 -0
- package/dist/next/stream/run.mjs +40 -0
- package/dist/next/stream/run.mjs.map +1 -0
- package/dist/next-node.d.ts +15 -0
- package/dist/next-node.mjs +51 -0
- package/dist/next-node.mjs.map +1 -0
- package/dist/node.d.ts +3 -0
- package/dist/node.mjs +185 -0
- package/dist/node.mjs.map +1 -0
- package/dist/processor-host-capabilities-BMFH3KTM.mjs +56 -0
- package/dist/processor-host-capabilities-BMFH3KTM.mjs.map +1 -0
- package/dist/processors/cloudflare.d.ts +3 -0
- package/dist/processors/durable-object-processor-durability.d.ts +79 -0
- package/dist/processors/event-consumption-metrics.d.ts +82 -0
- package/dist/processors/idempotency.d.ts +13 -0
- package/dist/processors/index.d.ts +12 -0
- package/dist/processors/processor-contracts.d.ts +342 -0
- package/dist/processors/processor-facet.d.ts +186 -0
- package/dist/processors/processor-host-capabilities.d.ts +60 -0
- package/dist/processors/prompt-sections.d.ts +17 -0
- package/dist/processors/rpc-types.d.ts +515 -0
- package/dist/processors/schemas.d.ts +102 -0
- package/dist/processors/stream-handle.d.ts +45 -0
- package/dist/processors/stream-processor-keepalive.d.ts +95 -0
- package/dist/processors/stream-processor-registry.d.ts +233 -0
- package/dist/processors/stream-processor-runner.d.ts +289 -0
- package/dist/processors/stream-processor.d.ts +339 -0
- package/dist/processors/stream-runtime-metrics.d.ts +107 -0
- package/dist/processors/testing.d.ts +302 -0
- package/dist/processors-BoNyeBfQ.mjs +10 -0
- package/dist/processors-BoNyeBfQ.mjs.map +1 -0
- package/dist/processors-cloudflare.mjs +3 -0
- package/dist/processors-testing.mjs +435 -0
- package/dist/processors-testing.mjs.map +1 -0
- package/dist/processors.mjs +52 -0
- package/dist/processors.mjs.map +1 -0
- package/dist/protocol-DnK_f2m6.mjs +251 -0
- package/dist/protocol-DnK_f2m6.mjs.map +1 -0
- package/dist/sdk/capnweb/index.d.ts +2 -0
- package/dist/sdk/capnweb/live-state/compact.d.ts +5 -0
- package/dist/sdk/capnweb/live-state/diff.d.ts +41 -0
- package/dist/sdk/capnweb/live-state/engine.d.ts +44 -0
- package/dist/sdk/capnweb/live-state/index.d.ts +41 -0
- package/dist/sdk/capnweb/live-state/protocol.d.ts +87 -0
- package/dist/sdk/capnweb/live-state/retain.d.ts +23 -0
- package/dist/sdk/capnweb/live-state/store.d.ts +20 -0
- package/dist/sdk/capnweb/live-state/types.d.ts +11 -0
- package/dist/sdk/capnweb/react.d.ts +45 -0
- package/dist/sdk/capnweb/react.mjs +316 -0
- package/dist/sdk/capnweb/react.mjs.map +1 -0
- package/dist/sdk/capnweb.mjs +4 -0
- package/dist/sdk/itx/react.d.ts +191 -0
- package/dist/sdk/itx/react.mjs +383 -0
- package/dist/sdk/itx/react.mjs.map +1 -0
- package/dist/sdk-DMB-IM11.mjs +933 -0
- package/dist/sdk-DMB-IM11.mjs.map +1 -0
- package/dist/sdk.d.ts +339 -0
- package/dist/sdk.mjs +2 -0
- package/dist/serve-itx.d.ts +46 -0
- package/dist/starter-apps/flake-dashboard/app-ref.d.ts +31 -0
- package/dist/starter-apps/flake-dashboard/configured-worker.mjs +1055 -0
- package/dist/starter-apps/flake-dashboard/configured-worker.mjs.map +1 -0
- package/dist/starter-apps/flake-dashboard/contract.d.ts +4839 -0
- package/dist/starter-apps/flake-dashboard/contract.mjs +2 -0
- package/dist/starter-apps/flake-dashboard/index.d.ts +17 -0
- package/dist/starter-apps/flake-dashboard/index.mjs +56 -0
- package/dist/starter-apps/flake-dashboard/index.mjs.map +1 -0
- package/dist/starter-apps/flake-dashboard/worker.d.ts +4607 -0
- package/dist/starter-apps/github-ai-linter/ai-linter.d.ts +8914 -0
- package/dist/starter-apps/github-ai-linter/configured-worker.mjs +17987 -0
- package/dist/starter-apps/github-ai-linter/configured-worker.mjs.map +1 -0
- package/dist/starter-apps/github-ai-linter/contract.d.ts +9193 -0
- package/dist/starter-apps/github-ai-linter/index.d.ts +10 -0
- package/dist/starter-apps/github-ai-linter/index.mjs +36 -0
- package/dist/starter-apps/github-ai-linter/index.mjs.map +1 -0
- package/dist/starter-apps/github-ai-linter/prompt.d.ts +13 -0
- package/dist/starter-apps/github-ai-linter/review-bot.d.ts +808 -0
- package/dist/starter-apps/github-ai-linter/rules.d.ts +34 -0
- package/dist/starter-apps/github-ai-linter/worker-ref.d.ts +19 -0
- package/dist/starter-apps/github-ai-linter/worker.d.ts +19 -0
- package/dist/starter-apps/github-ai-linter/worker.mjs +947 -0
- package/dist/starter-apps/github-ai-linter/worker.mjs.map +1 -0
- package/dist/starter-apps/guestbook/app-ref.d.ts +27 -0
- package/dist/starter-apps/guestbook/client.d.ts +7 -0
- package/dist/starter-apps/guestbook/client.mjs +59 -0
- package/dist/starter-apps/guestbook/configured-worker.mjs +205 -0
- package/dist/starter-apps/guestbook/configured-worker.mjs.map +1 -0
- package/dist/starter-apps/guestbook/index.d.ts +9 -0
- package/dist/starter-apps/guestbook/index.mjs +31 -0
- package/dist/starter-apps/guestbook/index.mjs.map +1 -0
- package/dist/starter-apps/guestbook/processor.d.ts +2267 -0
- package/dist/starter-apps/guestbook/worker.d.ts +26 -0
- package/dist/starter-apps/guestbook/worker.mjs +191 -0
- package/dist/starter-apps/guestbook/worker.mjs.map +1 -0
- package/dist/starter-apps/media/configured-worker.mjs +577 -0
- package/dist/starter-apps/media/configured-worker.mjs.map +1 -0
- package/dist/starter-apps/media/index.mjs +36 -0
- package/dist/starter-apps/media/index.mjs.map +1 -0
- package/dist/starter-apps/media/ref.mjs +20 -0
- package/dist/starter-apps/media/ref.mjs.map +1 -0
- package/dist/starter-apps/media/worker.mjs +579 -0
- package/dist/starter-apps/media/worker.mjs.map +1 -0
- package/dist/starter-apps/notes/configured-worker.mjs +6134 -0
- package/dist/starter-apps/notes/configured-worker.mjs.map +1 -0
- package/dist/starter-apps/notes/index.mjs +23 -0
- package/dist/starter-apps/notes/index.mjs.map +1 -0
- package/dist/starter-apps/notes/ref.mjs +21 -0
- package/dist/starter-apps/notes/ref.mjs.map +1 -0
- package/dist/starter-apps/notes/worker.mjs +427 -0
- package/dist/starter-apps/notes/worker.mjs.map +1 -0
- package/dist/starter-apps/todo/client.mjs +59 -0
- package/dist/starter-apps/todo/configured-worker.mjs +2864 -0
- package/dist/starter-apps/todo/configured-worker.mjs.map +1 -0
- package/dist/starter-apps/todo/index.d.ts +8 -0
- package/dist/starter-apps/todo/index.mjs +29 -0
- package/dist/starter-apps/todo/index.mjs.map +1 -0
- package/dist/stream-processor-keepalive-DAQTP6m3.mjs +2082 -0
- package/dist/stream-processor-keepalive-DAQTP6m3.mjs.map +1 -0
- package/dist/usingCtx-inzbY1Qz.mjs +57 -0
- package/dist/usingCtx-mZx5nsAW.mjs +11800 -0
- package/dist/usingCtx-mZx5nsAW.mjs.map +1 -0
- package/dist/worker-ref-DZxPDmb_.mjs +390 -0
- package/dist/worker-ref-DZxPDmb_.mjs.map +1 -0
- package/menubar/Iterate.entitlements +12 -0
- package/menubar/Iterate.swift +914 -0
- package/menubar/IterateIcon.swift +145 -0
- package/menubar/README.md +28 -0
- package/menubar/build-menubar-app.sh +59 -0
- package/package.json +235 -18
- package/dist/cli-DMS4kJph.mjs +0 -868
- package/dist/cli-DMS4kJph.mjs.map +0 -1
- package/dist/config-DtnR7Lv7.mjs +0 -170
- package/dist/config-DtnR7Lv7.mjs.map +0 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/stream-tui/agent-chat-terminal.d.mts +0 -1
- package/dist/stream-tui/agent-chat-terminal.mjs +0 -933
- package/dist/stream-tui/agent-chat-terminal.mjs.map +0 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//#region src/processors/processor-host-capabilities.ts
|
|
2
|
+
/**
|
|
3
|
+
* The two live capabilities every processor host hands the stream alongside
|
|
4
|
+
* its event-batch callback, shared by the DO registry and browser runtime so they cannot
|
|
5
|
+
* drift. `getRuntimeState` assembles the published shape from its two honest
|
|
6
|
+
* sources: the SNAPSHOT from the runner (`opts.snapshot` — the cursor owner),
|
|
7
|
+
* the `runtime` bag from the processor, with the self-measured metrics merged
|
|
8
|
+
* in host-side so a subclass override cannot accidentally drop them.
|
|
9
|
+
*/
|
|
10
|
+
function hostRuntimeCapabilities(processor, opts) {
|
|
11
|
+
return {
|
|
12
|
+
getRuntimeState: async () => {
|
|
13
|
+
const contributed = await processor.getRuntimeState();
|
|
14
|
+
const metrics = processor.eventConsumptionMetrics.report();
|
|
15
|
+
return {
|
|
16
|
+
snapshot: await opts.snapshot(),
|
|
17
|
+
runtime: {
|
|
18
|
+
...contributed.runtime,
|
|
19
|
+
metrics
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
ping: (input) => {
|
|
24
|
+
const t1 = opts.now();
|
|
25
|
+
const oneWayEstimateMs = opts.oneWayEstimateMs?.();
|
|
26
|
+
if (oneWayEstimateMs !== void 0) processor.eventConsumptionMetrics.notePingObserved({
|
|
27
|
+
t0: input.t0,
|
|
28
|
+
t1,
|
|
29
|
+
oneWayEstimateMs
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
t0: input.t0,
|
|
33
|
+
t1,
|
|
34
|
+
t2: opts.now()
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Serializable processor contract carried by server and browser hosts. */
|
|
40
|
+
function announceContract(contract) {
|
|
41
|
+
return {
|
|
42
|
+
slug: contract.slug,
|
|
43
|
+
version: contract.version,
|
|
44
|
+
description: contract.description,
|
|
45
|
+
consumes: [...contract.consumes],
|
|
46
|
+
emits: [...contract.emits],
|
|
47
|
+
ownedEvents: Object.entries(contract.events).map(([type, definition]) => ({
|
|
48
|
+
type,
|
|
49
|
+
...definition.description === void 0 ? {} : { description: definition.description }
|
|
50
|
+
}))
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { hostRuntimeCapabilities as n, announceContract as t };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=processor-host-capabilities-BMFH3KTM.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processor-host-capabilities-BMFH3KTM.mjs","names":[],"sources":["../src/processors/processor-host-capabilities.ts"],"sourcesContent":["import type { z } from \"zod\";\nimport type {\n GetProcessorRuntimeState,\n ProcessorSnapshot,\n StreamPingInput,\n StreamConnectionPing,\n} from \"./rpc-types.ts\";\nimport type { ProcessorContractAnnouncement } from \"./processor-contracts.ts\";\nimport type { EventConsumptionMetrics } from \"./event-consumption-metrics.ts\";\nimport type { ProcessorRuntimeContribution } from \"./stream-processor.ts\";\n\n/**\n * The processor surface shared by the Durable Object registry\n * (stream-processor-registry.ts) and the browser host (stream-browser-store.ts):\n * the contract description returned by `wakeStreamProcessor`, the\n * processor-contributed runtime bag, and self-measured event-consumption metrics.\n * Deliberately NOT the drive surface — cursors, snapshots, and delivery live\n * in the StreamProcessorRunner, which reaches the protected hooks through\n * `StreamProcessor.runnerHooks`.\n */\nexport type AnyHostedProcessor = {\n contract: {\n slug: string;\n version: string;\n description: string;\n stateSchema: z.ZodType;\n consumes: readonly string[];\n emits: readonly string[];\n events: Record<string, { description?: string; payloadSchema?: unknown }>;\n };\n /** The processor-contributed runtime bag; the snapshot half comes from the runner. */\n getRuntimeState(): Promise<ProcessorRuntimeContribution>;\n readonly eventConsumptionMetrics: Pick<\n EventConsumptionMetrics,\n \"report\" | \"notePingObserved\" | \"noteAppendCommitted\" | \"clearPendingAppends\"\n >;\n};\n\n/**\n * The two live capabilities every processor host hands the stream alongside\n * its event-batch callback, shared by the DO registry and browser runtime so they cannot\n * drift. `getRuntimeState` assembles the published shape from its two honest\n * sources: the SNAPSHOT from the runner (`opts.snapshot` — the cursor owner),\n * the `runtime` bag from the processor, with the self-measured metrics merged\n * in host-side so a subclass override cannot accidentally drop them.\n */\nexport function hostRuntimeCapabilities(\n processor: AnyHostedProcessor,\n opts: {\n now: () => number;\n /** The driving runner's committed snapshot (`() => runner.snapshot()`). */\n snapshot: () => Promise<ProcessorSnapshot<unknown>>;\n oneWayEstimateMs?: () => number | undefined;\n },\n): { getRuntimeState: GetProcessorRuntimeState; ping: StreamConnectionPing } {\n return {\n getRuntimeState: async () => {\n const contributed = await processor.getRuntimeState();\n const metrics = processor.eventConsumptionMetrics.report();\n return {\n snapshot: await opts.snapshot(),\n runtime: { ...contributed.runtime, metrics },\n };\n },\n ping: (input: StreamPingInput) => {\n const t1 = opts.now();\n const oneWayEstimateMs = opts.oneWayEstimateMs?.();\n if (oneWayEstimateMs !== undefined) {\n processor.eventConsumptionMetrics.notePingObserved({ t0: input.t0, t1, oneWayEstimateMs });\n }\n return { t0: input.t0, t1, t2: opts.now() };\n },\n };\n}\n\n/** Serializable processor contract carried by server and browser hosts. */\nexport function announceContract(contract: {\n slug: string;\n version: string;\n description: string;\n consumes: readonly string[];\n emits: readonly string[];\n events: Record<string, { description?: string; payloadSchema?: unknown }>;\n}): ProcessorContractAnnouncement {\n return {\n slug: contract.slug,\n version: contract.version,\n description: contract.description,\n consumes: [...contract.consumes],\n emits: [...contract.emits],\n ownedEvents: Object.entries(contract.events).map(([type, definition]) => ({\n type,\n ...(definition.description === undefined ? {} : { description: definition.description }),\n })),\n };\n}\n"],"mappings":";;;;;;;;;AA8CA,SAAgB,wBACd,WACA,MAM2E;CAC3E,OAAO;EACL,iBAAiB,YAAY;GAC3B,MAAM,cAAc,MAAM,UAAU,gBAAgB;GACpD,MAAM,UAAU,UAAU,wBAAwB,OAAO;GACzD,OAAO;IACL,UAAU,MAAM,KAAK,SAAS;IAC9B,SAAS;KAAE,GAAG,YAAY;KAAS;IAAQ;GAC7C;EACF;EACA,OAAO,UAA2B;GAChC,MAAM,KAAK,KAAK,IAAI;GACpB,MAAM,mBAAmB,KAAK,mBAAmB;GACjD,IAAI,qBAAqB,KAAA,GACvB,UAAU,wBAAwB,iBAAiB;IAAE,IAAI,MAAM;IAAI;IAAI;GAAiB,CAAC;GAE3F,OAAO;IAAE,IAAI,MAAM;IAAI;IAAI,IAAI,KAAK,IAAI;GAAE;EAC5C;CACF;AACF;;AAGA,SAAgB,iBAAiB,UAOC;CAChC,OAAO;EACL,MAAM,SAAS;EACf,SAAS,SAAS;EAClB,aAAa,SAAS;EACtB,UAAU,CAAC,GAAG,SAAS,QAAQ;EAC/B,OAAO,CAAC,GAAG,SAAS,KAAK;EACzB,aAAa,OAAO,QAAQ,SAAS,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,iBAAiB;GACxE;GACA,GAAI,WAAW,gBAAgB,KAAA,IAAY,CAAC,IAAI,EAAE,aAAa,WAAW,YAAY;EACxF,EAAE;CACJ;AACF"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { ProcessorStream } from "./stream-handle.ts";
|
|
2
|
+
import type { ProcessorProgressStore, ProcessorRecovery } from "./stream-processor-runner.ts";
|
|
3
|
+
/** The two-cursor progress record ({@link ProcessorProgress}). */
|
|
4
|
+
export declare const processorProgressKey: (name: string) => string;
|
|
5
|
+
/** The per-runner keepalive record ({@link KeepaliveRecord}). */
|
|
6
|
+
export declare const processorKeepaliveKey: (name: string) => string;
|
|
7
|
+
/**
|
|
8
|
+
* The runner's durable progress store over DO KV (`storage.kv` — synchronous,
|
|
9
|
+
* single-threaded isolate, so read-check-write is atomic without awaits).
|
|
10
|
+
*/
|
|
11
|
+
export declare function durableObjectProgressStore<State>(args: {
|
|
12
|
+
storage: DurableObjectStorage;
|
|
13
|
+
/** The registered processor name (subscription name = contract slug) —
|
|
14
|
+
* keys the progress record. */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Synchronously clear related projections when the source stream is replaced. */
|
|
17
|
+
resetForStream?: () => void;
|
|
18
|
+
/**
|
|
19
|
+
* An optional bounded reduction cache. Processing cursors always remain
|
|
20
|
+
* durable; a cold runner refolds reduce-only from initialState when the
|
|
21
|
+
* predicate declines a large cache.
|
|
22
|
+
*/
|
|
23
|
+
reductionCache?: {
|
|
24
|
+
shouldCacheReduction(state: State): boolean;
|
|
25
|
+
initialState(): State;
|
|
26
|
+
};
|
|
27
|
+
}): ProcessorProgressStore<State>;
|
|
28
|
+
/**
|
|
29
|
+
* The runner's recovery adapter for a Durable Object: wraps ONE
|
|
30
|
+
* {@link ProcessorKeepalive} for THIS runner (per-runner recovery identity, so
|
|
31
|
+
* a revival names exactly which processor owed work). The keepalive machinery
|
|
32
|
+
* — mark-before-work, bounded backoff, quiet-clean reset,
|
|
33
|
+
* deploy-version reset, wedged-work detection — is reused wholesale, never
|
|
34
|
+
* reimplemented.
|
|
35
|
+
*
|
|
36
|
+
* DO-shaped seams are INJECTED, not reached for:
|
|
37
|
+
* - `armAlarm` — the hosting registry's alarm slice for this runner. A DO
|
|
38
|
+
* has ONE alarm; the registry merges every runner's desire (plus its own)
|
|
39
|
+
* and arms the earliest, exactly like the host's `setAlarmSlice`. This
|
|
40
|
+
* adapter never touches `storage.setAlarm`.
|
|
41
|
+
* - `waitUntil` — calls the hosting DO's `ctx.waitUntil`, keeping the
|
|
42
|
+
* incarnation alive while tracked work runs.
|
|
43
|
+
*
|
|
44
|
+
* Revival appends the core `stream/processor-revived` fact (ONE type for
|
|
45
|
+
* every processor — {@link STREAM_PROCESSOR_REVIVED_EVENT_TYPE}; the payload's
|
|
46
|
+
* `processorSlug` and the idempotency key carry the per-processor identity)
|
|
47
|
+
* to the stream and STOPS: the append wakes the source stream's event sender (its
|
|
48
|
+
* `woken` handlers cold-boot the stream DO if the deploy evicted it too), and
|
|
49
|
+
* wake-mode delivery reaches head and guarantees a turn: either the contract
|
|
50
|
+
* consumes the fact and receives it, or the runner supplies its eventless
|
|
51
|
+
* `processEvent(event: null, caughtUp: true)` pass. No self-driven catch-up
|
|
52
|
+
* here, unlike the host's `catchUpInternal` loop: delivery has ONE entrypoint.
|
|
53
|
+
*
|
|
54
|
+
* Construction re-issues a persisted armed desire through `armAlarm` (the
|
|
55
|
+
* host's boot-time reconcile): a platform `setAlarm` that failed after the KV
|
|
56
|
+
* record committed — or an eviction in the fire→re-arm window — would
|
|
57
|
+
* otherwise leave the only thing that revives this DO permanently lost.
|
|
58
|
+
*/
|
|
59
|
+
export declare function durableObjectRecovery(args: {
|
|
60
|
+
storage: DurableObjectStorage;
|
|
61
|
+
/** The registered processor name (subscription name = contract slug) —
|
|
62
|
+
* keys the per-runner keepalive record and the revival fact's idempotency
|
|
63
|
+
* key, and fills the revival payload's `processorSlug`. */
|
|
64
|
+
name: string;
|
|
65
|
+
/** The processor's home stream: revived facts and crash-loop evidence land here. */
|
|
66
|
+
stream: ProcessorStream;
|
|
67
|
+
/** Worker deploy version; a change resets the keepalive's crash-loop budget
|
|
68
|
+
* (the antidote deploy). Pass `workerVersion(env)`. REQUIRED for the same
|
|
69
|
+
* reason the host requires it: a silent default could never take the
|
|
70
|
+
* version-reset code path. */
|
|
71
|
+
version: string;
|
|
72
|
+
/** The registry's alarm-slice seam for this runner (null = disarm). */
|
|
73
|
+
armAlarm: (atMs: number | null) => void;
|
|
74
|
+
/** The hosting DO's `ctx.waitUntil` — keeps the incarnation alive while
|
|
75
|
+
* tracked work runs. */
|
|
76
|
+
waitUntil: (work: Promise<unknown>) => void;
|
|
77
|
+
/** Injected clock for the test harness; production uses Date.now. */
|
|
78
|
+
now?: () => number;
|
|
79
|
+
}): ProcessorRecovery;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { type LatencyStats } from "./stream-runtime-metrics.ts";
|
|
2
|
+
/** The `runtime.metrics` slice a host reports through `getRuntimeState()`. */
|
|
3
|
+
export type EventConsumptionMetricsReport = {
|
|
4
|
+
/** ISO timestamp when this host runtime started measuring (in-memory; resets on reload). */
|
|
5
|
+
measuredSince: string;
|
|
6
|
+
/**
|
|
7
|
+
* The full consume-your-own-appends loop, one clock: this host called
|
|
8
|
+
* `append()` at t0, and its OWN event connection later delivered (and the
|
|
9
|
+
* host fully ingested) THAT COMMITTED OFFSET.
|
|
10
|
+
*
|
|
11
|
+
* Samples only exist for appends that came back. An append of a type this
|
|
12
|
+
* host does not consume, or one the stream never hands back, contributes
|
|
13
|
+
* NOTHING here — it is not a slow loop, it is no loop, and the two must not
|
|
14
|
+
* be spelled the same. `null` is "no such append observed", never a
|
|
15
|
+
* fabricated number.
|
|
16
|
+
*/
|
|
17
|
+
consumeOwnAppendMs: LatencyStats | null;
|
|
18
|
+
/** `append()` call → commit acknowledged (the RPC round trip incl. commit). */
|
|
19
|
+
appendRoundTripMs: LatencyStats | null;
|
|
20
|
+
/**
|
|
21
|
+
* Age of the newest event in each batch when the host finished ingesting
|
|
22
|
+
* it, i.e. commit-to-consumed for OTHER producers' events too. Crosses
|
|
23
|
+
* clocks (event `createdAt` is stream time), corrected by the ping-derived
|
|
24
|
+
* offset estimate when one exists — an estimate, and labeled as such in UIs.
|
|
25
|
+
*/
|
|
26
|
+
deliveryAgeMs: LatencyStats | null;
|
|
27
|
+
/** Time the host spent ingesting each delivered batch (fold/SQLite write). */
|
|
28
|
+
ingestMs: LatencyStats | null;
|
|
29
|
+
batchesIngested: number;
|
|
30
|
+
eventsIngested: number;
|
|
31
|
+
/** Estimated host−stream clock skew (ms) from observed pings; `null` until pinged. */
|
|
32
|
+
clockOffsetMs: number | null;
|
|
33
|
+
};
|
|
34
|
+
export declare class EventConsumptionMetrics {
|
|
35
|
+
#private;
|
|
36
|
+
constructor(nowMs: number);
|
|
37
|
+
/**
|
|
38
|
+
* An `append()` this host issued resolved: `t0` is when the host called it,
|
|
39
|
+
* `atMs` is when the commit came back, and `maxCommittedOffset` is the
|
|
40
|
+
* highest committed offset that CAN come back to this host — the caller's
|
|
41
|
+
* judgement, because only the caller knows what it consumes. `null` means
|
|
42
|
+
* the append carried nothing this host will ever be delivered, and is timed
|
|
43
|
+
* for its round trip alone.
|
|
44
|
+
*/
|
|
45
|
+
noteAppendCommitted(args: {
|
|
46
|
+
maxCommittedOffset: number | null;
|
|
47
|
+
t0: number;
|
|
48
|
+
atMs: number;
|
|
49
|
+
}): void;
|
|
50
|
+
/** One delivered batch fully ingested (fold applied / SQLite write done). */
|
|
51
|
+
noteBatchIngested(args: {
|
|
52
|
+
/** Highest offset the host has now ingested through (its cursor, not just this batch). */
|
|
53
|
+
ingestedThroughOffset: number;
|
|
54
|
+
/**
|
|
55
|
+
* The offsets this batch actually CARRIED.
|
|
56
|
+
*
|
|
57
|
+
* The cursor above sweeps past rows this host was never handed — a
|
|
58
|
+
* filtered subscription skips them durably — so it cannot tell an own
|
|
59
|
+
* append that came back from one that never will. These can.
|
|
60
|
+
*/
|
|
61
|
+
ingestedOffsets: readonly number[];
|
|
62
|
+
/** `Date.parse(newestEvent.createdAt)` for the newest event in the batch, if any. */
|
|
63
|
+
newestEventCreatedAtMs?: number;
|
|
64
|
+
/** When the host started ingesting this batch. */
|
|
65
|
+
ingestStartedAtMs: number;
|
|
66
|
+
atMs: number;
|
|
67
|
+
}): void;
|
|
68
|
+
/**
|
|
69
|
+
* The stream pinged this host: `t0` is the stream's send time (stream
|
|
70
|
+
* clock), `t1` the host's receive time (host clock). With a one-way-delay
|
|
71
|
+
* estimate (half the host's measured transport RTT, when it has one) this
|
|
72
|
+
* yields the host−stream clock offset used to correct delivery ages.
|
|
73
|
+
*/
|
|
74
|
+
notePingObserved(args: {
|
|
75
|
+
t0: number;
|
|
76
|
+
t1: number;
|
|
77
|
+
oneWayEstimateMs?: number;
|
|
78
|
+
}): void;
|
|
79
|
+
/** The host's event connection reopened: in-flight own-append correlations are void. */
|
|
80
|
+
clearPendingAppends(): void;
|
|
81
|
+
report(): EventConsumptionMetricsReport;
|
|
82
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
type EventBody = {
|
|
2
|
+
type: string;
|
|
3
|
+
payload?: unknown;
|
|
4
|
+
metadata?: unknown;
|
|
5
|
+
ephemeral?: boolean | undefined;
|
|
6
|
+
};
|
|
7
|
+
export declare function idempotencyConflictMessage(idempotencyKey: string, existingOffset: number): string;
|
|
8
|
+
export declare function isIdempotencyConflict(error: unknown): boolean;
|
|
9
|
+
/** Whether a requested append names the SAME event an idempotency key already committed. */
|
|
10
|
+
export declare function sameIdempotentEvent(existing: EventBody, requested: EventBody): boolean;
|
|
11
|
+
/** Structural JSON equality (key-order-insensitive). */
|
|
12
|
+
export declare function jsonValuesEqual(left: unknown, right: unknown): boolean;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from "./schemas.ts";
|
|
2
|
+
export * from "./rpc-types.ts";
|
|
3
|
+
export * from "./stream-handle.ts";
|
|
4
|
+
export * from "./idempotency.ts";
|
|
5
|
+
export * from "./processor-contracts.ts";
|
|
6
|
+
export * from "./stream-processor.ts";
|
|
7
|
+
export * from "./stream-processor-runner.ts";
|
|
8
|
+
export * from "./stream-processor-keepalive.ts";
|
|
9
|
+
export * from "./processor-host-capabilities.ts";
|
|
10
|
+
export * from "./event-consumption-metrics.ts";
|
|
11
|
+
export * from "./stream-runtime-metrics.ts";
|
|
12
|
+
export * from "./prompt-sections.ts";
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { StreamEvent, StreamEventInput } from "./schemas.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Merge one processor configuration patch into its current configuration.
|
|
5
|
+
*
|
|
6
|
+
* Configuration patches recurse only through plain JSON objects. Arrays,
|
|
7
|
+
* scalars, and `null` replace the previous value wholesale; omitted keys are
|
|
8
|
+
* retained. Processors validate the merged result with their own complete
|
|
9
|
+
* configuration schema before storing it in reduced state.
|
|
10
|
+
*/
|
|
11
|
+
export declare function mergeProcessorConfig(base: unknown, patch: unknown): unknown;
|
|
12
|
+
/**
|
|
13
|
+
* One documented example payload for an owned event, rendered on the public
|
|
14
|
+
* event docs site (events.iterate.com). The payload must parse against the
|
|
15
|
+
* event's `payloadSchema` — enforced by the event-docs unit tests rather than
|
|
16
|
+
* at module load, so a bad example fails CI instead of bricking a worker boot.
|
|
17
|
+
*/
|
|
18
|
+
export type EventExample = {
|
|
19
|
+
/** What this example shows, e.g. "Durable delivery to another stream". */
|
|
20
|
+
description: string;
|
|
21
|
+
/** The example payload, in the payload schema's input shape. */
|
|
22
|
+
payload: unknown;
|
|
23
|
+
};
|
|
24
|
+
/** One owned event: its payload schema plus optional human description and examples. */
|
|
25
|
+
export type EventDefinition<PayloadOutput = unknown, PayloadInput = PayloadOutput> = {
|
|
26
|
+
description?: string;
|
|
27
|
+
payloadSchema: z.ZodType<PayloadOutput, PayloadInput>;
|
|
28
|
+
/**
|
|
29
|
+
* FORCIBLY ephemeral: every append and parse built from this definition
|
|
30
|
+
* defaults the envelope's `ephemeral` flag to `true` and REJECTS an explicit
|
|
31
|
+
* `ephemeral: false`. For events that must never become durable stream
|
|
32
|
+
* facts (streaming chunks) — declaring it here makes forgetting the flag at
|
|
33
|
+
* an append site impossible instead of a silent storage leak.
|
|
34
|
+
*/
|
|
35
|
+
ephemeral?: true;
|
|
36
|
+
examples?: readonly EventExample[];
|
|
37
|
+
};
|
|
38
|
+
/** A contract's owned events, keyed by the durable event type string. */
|
|
39
|
+
export type EventCatalog = Record<string, EventDefinition<unknown, unknown>>;
|
|
40
|
+
/** The string-keyed event definitions of a catalog object (index signatures excluded). */
|
|
41
|
+
type EventCatalogFromObject<Value> = {
|
|
42
|
+
[Key in keyof Value as string extends Key ? never : number extends Key ? never : Value[Key] extends EventDefinition ? Key : never]: Value[Key];
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A `processorDeps` entry may be a full contract (`{ events: ... }`) or a
|
|
46
|
+
* standalone event catalog, so a processor can depend on another processor's
|
|
47
|
+
* contract or on a small shared catalog.
|
|
48
|
+
*/
|
|
49
|
+
type ContractEventCatalog<ContractOrCatalog> = ContractOrCatalog extends {
|
|
50
|
+
events: infer Events;
|
|
51
|
+
} ? EventCatalogFromObject<Events> : EventCatalogFromObject<ContractOrCatalog>;
|
|
52
|
+
/** All event type strings resolvable from local `events` plus `processorDeps`. */
|
|
53
|
+
type ResolvedEventType<Events extends EventCatalog, ProcessorDeps extends readonly unknown[]> = Extract<keyof EventCatalogFromObject<Events> | EventTypeFromProcessorDeps<ProcessorDeps>, string>;
|
|
54
|
+
/** Union of every event type string owned by any `processorDeps` entry. */
|
|
55
|
+
type EventTypeFromProcessorDeps<ProcessorDeps extends readonly unknown[]> = ProcessorDeps[number] extends infer ProcessorDep ? ProcessorDep extends unknown ? keyof ContractEventCatalog<ProcessorDep> : never : never;
|
|
56
|
+
/**
|
|
57
|
+
* Resolve a string event type to the definition that owns it. Local events win
|
|
58
|
+
* in the type-level lookup; runtime validation rejects duplicate ownership.
|
|
59
|
+
*/
|
|
60
|
+
type EventDefinitionForType<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Type extends string> = Type extends keyof Events ? Events[Type] : ProcessorDeps[number] extends infer ProcessorDep ? ProcessorDep extends unknown ? Type extends keyof ContractEventCatalog<ProcessorDep> ? ContractEventCatalog<ProcessorDep>[Type] : never : never : never;
|
|
61
|
+
/** `StreamEventInput` with `type`/`payload` narrowed to one event definition. */
|
|
62
|
+
type TypedStreamEventInput<Type extends string = string, Payload = Record<string, unknown>> = Omit<StreamEventInput, "payload" | "type"> & {
|
|
63
|
+
type: Type;
|
|
64
|
+
payload: Payload;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* A durable processor input. Wake processors never receive ephemeral events, so
|
|
68
|
+
* a domain object's processor-typed append door must not claim that they do.
|
|
69
|
+
*/
|
|
70
|
+
type TypedConsumedEventInput<Type extends string = string, Payload = Record<string, unknown>> = Omit<TypedStreamEventInput<Type, Payload>, "ephemeral"> & {
|
|
71
|
+
ephemeral?: never;
|
|
72
|
+
};
|
|
73
|
+
/** `StreamEvent` with `type`/`payload` narrowed to one event definition. */
|
|
74
|
+
type TypedStreamEvent<Type extends string = string, Payload = Record<string, unknown>> = Omit<StreamEvent, "payload" | "type"> & TypedStreamEventInput<Type, Payload>;
|
|
75
|
+
/** Committed event for one resolved type (payload parsed, so required). */
|
|
76
|
+
type EventFromType<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Type extends string> = Type extends unknown ? EventDefinitionForType<Events, ProcessorDeps, Type> extends EventDefinition<infer PayloadOutput, unknown> ? TypedStreamEvent<Type, PayloadOutput> & {
|
|
77
|
+
payload: PayloadOutput;
|
|
78
|
+
} & ParsedEphemeralEnvelope<EventDefinitionForType<Events, ProcessorDeps, Type>> : never : never;
|
|
79
|
+
/** A committed event resolved from a contract's owned events or processor dependencies.
|
|
80
|
+
* Unknown event-type strings retain the untyped {@link StreamEvent} shape. */
|
|
81
|
+
export type ResolvedEvent<Contract, Type extends string> = Contract extends {
|
|
82
|
+
events: EventCatalog;
|
|
83
|
+
} ? Type extends ResolvedEventType<ContractEventCatalog<Contract>, ProcessorDepsOf<Contract>> ? EventFromType<ContractEventCatalog<Contract>, ProcessorDepsOf<Contract>, Type> : StreamEvent : StreamEvent;
|
|
84
|
+
/** Union of committed-event shapes for a `consumes` tuple; `"*"` alone means any `StreamEvent`. */
|
|
85
|
+
type EventFromTypes<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Types extends readonly string[]> = "*" extends Types[number] ? [Exclude<Types[number], "*">] extends [never] ? StreamEvent : EventFromType<Events, ProcessorDeps, Exclude<Types[number], "*">> : EventFromType<Events, ProcessorDeps, Types[number]>;
|
|
86
|
+
/** Append input for one resolved type (payload accepts the schema's input shape). */
|
|
87
|
+
type InputFromType<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Type extends string> = Type extends unknown ? EventDefinitionForType<Events, ProcessorDeps, Type> extends EventDefinition<unknown, infer PayloadInput> ? TypedStreamEventInput<Type, PayloadInput> : never : never;
|
|
88
|
+
/** Durable append input for one event delivered to a wake processor. */
|
|
89
|
+
type ConsumedInputFromType<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Type extends string> = Type extends unknown ? EventDefinitionForType<Events, ProcessorDeps, Type> extends EventDefinition<unknown, infer PayloadInput> ? TypedConsumedEventInput<Type, PayloadInput> : never : never;
|
|
90
|
+
/** Durable append-input shapes for a processor's `consumes` tuple. */
|
|
91
|
+
type ConsumedInputFromTypes<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Types extends readonly string[]> = "*" extends Types[number] ? Omit<StreamEventInput, "ephemeral"> & {
|
|
92
|
+
ephemeral?: never;
|
|
93
|
+
} : ConsumedInputFromType<Events, ProcessorDeps, Types[number]>;
|
|
94
|
+
/** Parsed append input for one resolved type (payload validated, so required). */
|
|
95
|
+
type ParsedInputFromType<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Type extends string> = Type extends unknown ? EventDefinitionForType<Events, ProcessorDeps, Type> extends EventDefinition<infer PayloadOutput, unknown> ? TypedStreamEventInput<Type, PayloadOutput> & {
|
|
96
|
+
payload: PayloadOutput;
|
|
97
|
+
} & ParsedEphemeralEnvelope<EventDefinitionForType<Events, ProcessorDeps, Type>> : never : never;
|
|
98
|
+
/** Contract-forced ephemeral inputs default to `true` during parsing. */
|
|
99
|
+
type ParsedEphemeralEnvelope<Definition> = Definition extends {
|
|
100
|
+
ephemeral: true;
|
|
101
|
+
} ? {
|
|
102
|
+
ephemeral: true;
|
|
103
|
+
} : unknown;
|
|
104
|
+
/** A typed builder preserves the supplied envelope while returning parsed payload/default output. */
|
|
105
|
+
type BuiltInputFromEvent<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Event extends {
|
|
106
|
+
type: string;
|
|
107
|
+
}> = Event extends unknown ? Omit<Event, "payload"> & Pick<ParsedInputFromType<Events, ProcessorDeps, Event["type"]>, "payload"> & ParsedEphemeralEnvelope<EventDefinitionForType<Events, ProcessorDeps, Event["type"]>> : never;
|
|
108
|
+
/** Parsed durable inputs for a processor's `consumes` tuple. */
|
|
109
|
+
type ParsedConsumedInputFromTypes<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Types extends readonly string[]> = "*" extends Types[number] ? Omit<StreamEventInput, "ephemeral"> & {
|
|
110
|
+
ephemeral?: never;
|
|
111
|
+
} : Types[number] extends infer Type extends string ? EventDefinitionForType<Events, ProcessorDeps, Type> extends EventDefinition<infer PayloadOutput, unknown> ? TypedConsumedEventInput<Type, PayloadOutput> : never : never;
|
|
112
|
+
/** Union of committed-event shapes a contract's `consumes` list can deliver to `reduce`. */
|
|
113
|
+
export type ConsumedEvent<Contract> = Contract extends {
|
|
114
|
+
events: EventCatalog;
|
|
115
|
+
consumes: infer Consumes extends readonly string[];
|
|
116
|
+
} ? EventFromTypes<ContractEventCatalog<Contract>, ProcessorDepsOf<Contract>, Consumes> : never;
|
|
117
|
+
/**
|
|
118
|
+
* Union of durable append-input shapes accepted by a contract's `consumes`
|
|
119
|
+
* list. Ephemeral events are excluded because hosted processors cannot consume
|
|
120
|
+
* them; append those intentionally through the raw Stream door. This is a
|
|
121
|
+
* schema/vocabulary union, not proof that an event is valid in the processor's
|
|
122
|
+
* current state or came from a particular provenance.
|
|
123
|
+
*/
|
|
124
|
+
export type ConsumedInput<Contract> = Contract extends {
|
|
125
|
+
events: EventCatalog;
|
|
126
|
+
consumes: infer Consumes extends readonly string[];
|
|
127
|
+
} ? ConsumedInputFromTypes<ContractEventCatalog<Contract>, ProcessorDepsOf<Contract>, Consumes> : never;
|
|
128
|
+
/** Union of append-input shapes a contract's `emits` list allows a processor to append. */
|
|
129
|
+
export type EmittedInput<Contract> = Contract extends {
|
|
130
|
+
events: EventCatalog;
|
|
131
|
+
emits: infer Emits extends readonly string[];
|
|
132
|
+
} ? InputFromType<ContractEventCatalog<Contract>, ProcessorDepsOf<Contract>, Emits[number]> : never;
|
|
133
|
+
/** A contract's `processorDeps` tuple, defaulting to empty when absent. */
|
|
134
|
+
type ProcessorDepsOf<Contract> = Contract extends {
|
|
135
|
+
processorDeps?: infer ProcessorDeps;
|
|
136
|
+
} ? ProcessorDeps extends readonly unknown[] ? ProcessorDeps : readonly [] : readonly [];
|
|
137
|
+
/** A contract's reduced-state type, inferred from its `stateSchema`. */
|
|
138
|
+
export type ProcessorState<Contract> = Contract extends {
|
|
139
|
+
stateSchema: infer State extends z.ZodType;
|
|
140
|
+
} ? z.output<State> : never;
|
|
141
|
+
/** Reduced state must be object-shaped and must accept `{}` (the empty initial state). */
|
|
142
|
+
type DefaultableObjectStateSchema<StateSchema extends z.ZodType> = z.output<StateSchema> extends Record<string, unknown> ? {} extends z.input<StateSchema> ? StateSchema : never : never;
|
|
143
|
+
/**
|
|
144
|
+
* Compile-time typo guard for `consumes` / `emits`: resolves to `unknown` when
|
|
145
|
+
* every string in `Types` is resolvable (leaving the contract argument
|
|
146
|
+
* unchanged), `never` when one is not — failing the call where the bad string
|
|
147
|
+
* is written. `AllowStar` admits the `"*"` wildcard (consumes only).
|
|
148
|
+
*/
|
|
149
|
+
type ResolvedEventTypesOnly<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Types extends readonly string[], AllowStar extends string = never> = [Exclude<Exclude<Types[number], AllowStar>, ResolvedEventType<Events, ProcessorDeps>>] extends [
|
|
150
|
+
never
|
|
151
|
+
] ? unknown : never;
|
|
152
|
+
/** `contract.buildEvent(...)`: validate an append input against the resolved payload schema. */
|
|
153
|
+
type ProcessorContractBuildEvent<Events extends EventCatalog, ProcessorDeps extends readonly unknown[]> = <const Event extends InputFromType<Events, ProcessorDeps, ResolvedEventType<Events, ProcessorDeps>> & {
|
|
154
|
+
type: string;
|
|
155
|
+
}>(event: Event) => BuiltInputFromEvent<Events, ProcessorDeps, Event>;
|
|
156
|
+
/** Resolved contract types compatible with an event's current discriminator type. */
|
|
157
|
+
type ResolvedTypeFromEvent<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Event extends {
|
|
158
|
+
type: string;
|
|
159
|
+
}> = Extract<ResolvedEventType<Events, ProcessorDeps>, Event["type"]>;
|
|
160
|
+
/** `contract.parseEvent(...)`: validate a committed event and infer its output from `event.type`. */
|
|
161
|
+
type ProcessorContractParseEvent<Events extends EventCatalog, ProcessorDeps extends readonly unknown[]> = <const Event extends StreamEvent>(event: Event) => EventFromType<Events, ProcessorDeps, ResolvedTypeFromEvent<Events, ProcessorDeps, Event>>;
|
|
162
|
+
/**
|
|
163
|
+
* Same as `parseEvent`, but for append inputs that do not yet have an offset or
|
|
164
|
+
* createdAt. This exists for stream-owned pre-commit policy: the Stream Durable
|
|
165
|
+
* Object must reject some contract-owned events BEFORE they become durable
|
|
166
|
+
* facts (see the core processor's `validate`) — validating them
|
|
167
|
+
* later, in the wake side effect, would leave the invalid event committed and
|
|
168
|
+
* reduced into durable state. The lifecycle e2e tests assert both the rejection
|
|
169
|
+
* and that nothing was committed.
|
|
170
|
+
*/
|
|
171
|
+
type ProcessorContractParseEventInput<Events extends EventCatalog, ProcessorDeps extends readonly unknown[]> = <const Event extends StreamEventInput>(event: Event) => ParsedInputFromType<Events, ProcessorDeps, ResolvedTypeFromEvent<Events, ProcessorDeps, Event>>;
|
|
172
|
+
/**
|
|
173
|
+
* `contract.parseConsumedInput(...)`: validate one domain-object append
|
|
174
|
+
* against the exact event vocabulary delivered to the processor.
|
|
175
|
+
*/
|
|
176
|
+
type ProcessorContractParseConsumedInput<Events extends EventCatalog, ProcessorDeps extends readonly unknown[], Consumes extends readonly string[]> = <const Event extends ConsumedInputFromTypes<Events, ProcessorDeps, Consumes>>(event: Event) => "*" extends Consumes[number] ? ParsedConsumedInputFromTypes<Events, ProcessorDeps, Consumes> : ParsedConsumedInputFromTypes<Events, ProcessorDeps, readonly Extract<Consumes[number], Event["type"]>[]>;
|
|
177
|
+
/**
|
|
178
|
+
* `getEventSchema` without offset/createdAt (and strict, so an accidental
|
|
179
|
+
* `offset` key on an append input fails loudly). Gives pre-append policy code
|
|
180
|
+
* the same payload validation as reducers, without fabricating a committed
|
|
181
|
+
* event just to get at the typed payload.
|
|
182
|
+
*/
|
|
183
|
+
export declare function getEventInputSchema<const Type extends string, const PayloadSchema extends z.ZodType>(args: {
|
|
184
|
+
type: Type;
|
|
185
|
+
payloadSchema: PayloadSchema;
|
|
186
|
+
ephemeral?: boolean;
|
|
187
|
+
}): z.ZodType<TypedStreamEventInput<Type, z.output<PayloadSchema>>, TypedStreamEventInput<Type, z.input<PayloadSchema>>>;
|
|
188
|
+
/** Memoized {@link getEventSchema} (see {@link eventSchemaCache}). */
|
|
189
|
+
export declare function cachedEventSchema(args: {
|
|
190
|
+
type: string;
|
|
191
|
+
payloadSchema: z.ZodType;
|
|
192
|
+
ephemeral?: boolean;
|
|
193
|
+
}): z.ZodType;
|
|
194
|
+
/** Union of append-input shapes for every event a contract can resolve (own + deps). */
|
|
195
|
+
type ResolvedEventInput<Contract> = Contract extends {
|
|
196
|
+
events: EventCatalog;
|
|
197
|
+
} ? InputFromType<ContractEventCatalog<Contract>, ProcessorDepsOf<Contract>, ResolvedEventType<ContractEventCatalog<Contract>, ProcessorDepsOf<Contract>>> : never;
|
|
198
|
+
/**
|
|
199
|
+
* Validate an append input with the payload schema resolved from a processor
|
|
200
|
+
* contract. Prefer the contract-bound `contract.buildEvent(event)` API, which
|
|
201
|
+
* carries the same types without repeating the contract in the argument.
|
|
202
|
+
*
|
|
203
|
+
* @deprecated Use `contract.buildEvent(event)`.
|
|
204
|
+
*/
|
|
205
|
+
export declare function buildEvent<const Contract extends {
|
|
206
|
+
slug?: string;
|
|
207
|
+
events: EventCatalog;
|
|
208
|
+
processorDeps?: readonly unknown[];
|
|
209
|
+
}, const Event extends ResolvedEventInput<NoInfer<Contract>> & {
|
|
210
|
+
type: string;
|
|
211
|
+
}>(args: {
|
|
212
|
+
contract: Contract;
|
|
213
|
+
event: Event;
|
|
214
|
+
}): BuiltInputFromEvent<ContractEventCatalog<Contract>, ProcessorDepsOf<Contract>, Event>;
|
|
215
|
+
/**
|
|
216
|
+
* Typed identity for processor contracts: validation plus the pre-bound
|
|
217
|
+
* `buildEvent` / `parseEvent` / `parseEventInput` / `parseConsumedInput`
|
|
218
|
+
* helpers.
|
|
219
|
+
*
|
|
220
|
+
* The signature enforces the important invariants at authoring time:
|
|
221
|
+
*
|
|
222
|
+
* - `stateSchema` must parse `{}` to an object-shaped reduced state;
|
|
223
|
+
* - every string in `consumes` and `emits` must resolve against local `events`
|
|
224
|
+
* plus `processorDeps` (and both are contextually typed for autocomplete);
|
|
225
|
+
* - local `events` must not redefine an event already owned by a
|
|
226
|
+
* `processorDeps` contract. Event ownership is intentionally one processor
|
|
227
|
+
* deep: a processor can depend on another owner, but it cannot shadow that
|
|
228
|
+
* owner's public event type with a second payload schema.
|
|
229
|
+
*/
|
|
230
|
+
export declare function defineProcessorContract<const StateSchema extends z.ZodType, const Events extends EventCatalog, const Consumes extends readonly (ResolvedEventType<Events, ProcessorDeps> | "*")[], const Emits extends readonly ResolvedEventType<Events, ProcessorDeps>[], const ProcessorDeps extends readonly unknown[] = readonly []>(contract: {
|
|
231
|
+
slug: string;
|
|
232
|
+
version: string;
|
|
233
|
+
description: string;
|
|
234
|
+
stateSchema: DefaultableObjectStateSchema<StateSchema>;
|
|
235
|
+
processorDeps?: ProcessorDeps;
|
|
236
|
+
events: Events;
|
|
237
|
+
consumes: Consumes & ResolvedEventTypesOnly<Events, ProcessorDeps, Consumes, "*">;
|
|
238
|
+
emits: Emits & ResolvedEventTypesOnly<Events, ProcessorDeps, Emits>;
|
|
239
|
+
}): {
|
|
240
|
+
slug: string;
|
|
241
|
+
version: string;
|
|
242
|
+
description: string;
|
|
243
|
+
stateSchema: StateSchema;
|
|
244
|
+
processorDeps?: ProcessorDeps;
|
|
245
|
+
events: Events;
|
|
246
|
+
consumes: Consumes;
|
|
247
|
+
emits: Emits;
|
|
248
|
+
buildEvent: ProcessorContractBuildEvent<Events, ProcessorDeps>;
|
|
249
|
+
parseEvent: ProcessorContractParseEvent<Events, ProcessorDeps>;
|
|
250
|
+
parseEventInput: ProcessorContractParseEventInput<Events, ProcessorDeps>;
|
|
251
|
+
parseConsumedInput: ProcessorContractParseConsumedInput<Events, ProcessorDeps, Consumes>;
|
|
252
|
+
};
|
|
253
|
+
/**
|
|
254
|
+
* Enforces the invariant that reduced processor state is object-shaped (so
|
|
255
|
+
* state slices can evolve safely and hooks never branch on primitive state).
|
|
256
|
+
*/
|
|
257
|
+
export declare function assertObjectProcessorState(args: {
|
|
258
|
+
processorSlug: string;
|
|
259
|
+
value: unknown;
|
|
260
|
+
}): void;
|
|
261
|
+
/**
|
|
262
|
+
* Resolve the payload schema a processor should use for an incoming event:
|
|
263
|
+
* the named definition when the type is listed in `consumes`, a permissive
|
|
264
|
+
* `z.unknown()` definition when the contract consumes `"*"`, and `undefined`
|
|
265
|
+
* when the event is not consumed at all. Runtime counterpart of
|
|
266
|
+
* `ConsumedEvent<Contract>`.
|
|
267
|
+
*
|
|
268
|
+
* `"*"` NEVER MATCHES AN EPHEMERAL EVENT, and that one rule is what lets
|
|
269
|
+
* ephemeral types live in `consumes` beside durable ones instead of in a
|
|
270
|
+
* parallel list. Naming a type explicitly is the opt-in: you cannot be handed
|
|
271
|
+
* a microphone firehose by a wildcard you wrote for durable facts, and a
|
|
272
|
+
* processor that wants live events says so by type. Ephemeral bodies live
|
|
273
|
+
* only in the Stream DO's bounded buffer, so a processor receiving one must
|
|
274
|
+
* have decided it can cope with never seeing it again — a decision nobody
|
|
275
|
+
* makes by writing `"*"`.
|
|
276
|
+
*/
|
|
277
|
+
export declare function getConsumedEventDefinition(args: {
|
|
278
|
+
contract: {
|
|
279
|
+
events: EventCatalog;
|
|
280
|
+
processorDeps?: readonly unknown[];
|
|
281
|
+
consumes: readonly string[];
|
|
282
|
+
};
|
|
283
|
+
eventType: string;
|
|
284
|
+
/** Whether the event being resolved is ephemeral; gates the `"*"` fallback. */
|
|
285
|
+
ephemeral?: boolean;
|
|
286
|
+
}): EventDefinition | undefined;
|
|
287
|
+
export declare function getResolvedEventDefinition(args: {
|
|
288
|
+
contract: {
|
|
289
|
+
events: EventCatalog;
|
|
290
|
+
processorDeps?: readonly unknown[];
|
|
291
|
+
};
|
|
292
|
+
eventType: string;
|
|
293
|
+
}): EventDefinition | undefined;
|
|
294
|
+
/**
|
|
295
|
+
* The ONE platform revival fact for every recovery-wired stream processor.
|
|
296
|
+
* Appended by the platform keepalive (`durableObjectRecovery` in
|
|
297
|
+
* durable-object-processor-durability.ts) when a processor is revived after
|
|
298
|
+
* its incarnation died owing background work — never emitted by a processor.
|
|
299
|
+
* Per-processor identity rides the payload's `processorSlug` and the
|
|
300
|
+
* `processor-revived:<slug>@...` idempotency key, not the type string.
|
|
301
|
+
* Consuming it is OPTIONAL: a processor should do so only when it reacts to
|
|
302
|
+
* the fact itself. Its append still wakes delivery when it is unconsumed, and
|
|
303
|
+
* a head-reaching frame receives the runner's eventless
|
|
304
|
+
* `processEvent(event: null, caughtUp: true)` pass so open obligations are not
|
|
305
|
+
* stranded. The event DEFINITION (payload schema) lives with the platform's
|
|
306
|
+
* core stream contract; this constant is here so contracts and the recovery
|
|
307
|
+
* adapter agree on the type string without importing that contract.
|
|
308
|
+
*/
|
|
309
|
+
export declare const STREAM_PROCESSOR_REVIVED_EVENT_TYPE = "events.iterate.com/stream/processor-revived";
|
|
310
|
+
/**
|
|
311
|
+
* A processor contract announcement carried on `connection-opened` when the
|
|
312
|
+
* callback owner is a hosted stream processor. UIs and tooling read it from
|
|
313
|
+
* that event and from `runtime.connections[..].openedBy`.
|
|
314
|
+
*/
|
|
315
|
+
export declare const ProcessorContractAnnouncement: z.ZodObject<{
|
|
316
|
+
slug: z.ZodString;
|
|
317
|
+
version: z.ZodString;
|
|
318
|
+
description: z.ZodString;
|
|
319
|
+
consumes: z.ZodArray<z.ZodString>;
|
|
320
|
+
emits: z.ZodArray<z.ZodString>;
|
|
321
|
+
ownedEvents: z.ZodArray<z.ZodObject<{
|
|
322
|
+
type: z.ZodString;
|
|
323
|
+
description: z.ZodOptional<z.ZodString>;
|
|
324
|
+
}, z.core.$strip>>;
|
|
325
|
+
}, z.core.$strip>;
|
|
326
|
+
export type ProcessorContractAnnouncement = z.infer<typeof ProcessorContractAnnouncement>;
|
|
327
|
+
/**
|
|
328
|
+
* Platform stream events a processor contract may CONSUME without owning —
|
|
329
|
+
* pass as a `processorDeps` entry. Currently just the keepalive revival fact.
|
|
330
|
+
* Consumption is optional and belongs only in processors that react to the
|
|
331
|
+
* fact itself; an unconsumed revival tail receives the runner's eventless
|
|
332
|
+
* at-head turn. The event's authoritative definition lives with the
|
|
333
|
+
* platform's core stream contract, and this catalog is deliberately
|
|
334
|
+
* payload-loose.
|
|
335
|
+
*/
|
|
336
|
+
export declare const PLATFORM_STREAM_EVENTS: {
|
|
337
|
+
"events.iterate.com/stream/processor-revived": {
|
|
338
|
+
description: string;
|
|
339
|
+
payloadSchema: z.ZodObject<{}, z.core.$loose>;
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
export {};
|