iterate 0.2.7 → 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 +11 -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,302 @@
|
|
|
1
|
+
import type { StreamEvent, StreamEventInput } from "./schemas.ts";
|
|
2
|
+
import type { StreamEventReadInput } from "./rpc-types.ts";
|
|
3
|
+
import type { ConsumedInput, ProcessorState, ResolvedEvent } from "./processor-contracts.ts";
|
|
4
|
+
import type { RegisteredProcessorReads } from "./stream-processor-registry.ts";
|
|
5
|
+
import type { ProcessorStream } from "./stream-handle.ts";
|
|
6
|
+
import type { StreamProcessor, StreamProcessorContract } from "./stream-processor.ts";
|
|
7
|
+
import type { ProcessorProgressStore } from "./stream-processor-runner.ts";
|
|
8
|
+
import { StreamProcessorRunner } from "./stream-processor-runner.ts";
|
|
9
|
+
export declare class MemoryStream implements ProcessorStream {
|
|
10
|
+
events: StreamEvent[];
|
|
11
|
+
streamId: `${string}-${string}-${string}-${string}-${string}`;
|
|
12
|
+
/** Injectable clock for createdAt stamps; harnesses point it at virtual time. */
|
|
13
|
+
now: () => number;
|
|
14
|
+
/** Simulate a transient Stream DO outage: appends of this type throw. */
|
|
15
|
+
failAppendsOfType: string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* OPT-IN ASYNCHRONOUS COMMIT. Undefined — the default — is today's behaviour
|
|
18
|
+
* and every existing suite's behaviour.
|
|
19
|
+
*
|
|
20
|
+
* `append` below validates and publishes in its own SYNCHRONOUS body: it is
|
|
21
|
+
* declared `async`, but nothing inside it awaits, so the events are in
|
|
22
|
+
* `this.events` and their offsets are taken before the returned promise is
|
|
23
|
+
* even handed back. Two call sites therefore commit in the order they
|
|
24
|
+
* CALLED, whoever awaited and whoever did not. That determinism is what
|
|
25
|
+
* makes scenario steps reproducible and it is why ~250 suites rest on it.
|
|
26
|
+
*
|
|
27
|
+
* It is also a lie about production. A real append is an RPC to the Stream
|
|
28
|
+
* Durable Object; two of them can be in flight at once, and the one issued
|
|
29
|
+
* first is not guaranteed to commit first. Every ordering bug of that shape
|
|
30
|
+
* — an un-awaited append racing an awaited one, and the un-awaited one
|
|
31
|
+
* losing — is structurally invisible here.
|
|
32
|
+
*
|
|
33
|
+
* Set this and an append waits for the returned promise before it validates
|
|
34
|
+
* anything or takes an offset, so offsets are assigned at COMMIT the way the
|
|
35
|
+
* Durable Object assigns them. Return `undefined` to let a batch commit at
|
|
36
|
+
* once, which is what keeps the cost of the mode to the batches a test
|
|
37
|
+
* actually cares about.
|
|
38
|
+
*
|
|
39
|
+
* A test is expected to DECIDE which of two in-flight appends wins rather
|
|
40
|
+
* than to wait and see: a race whose loser cannot be pinned is a flake, not
|
|
41
|
+
* a test. Whatever the hook waits on must be bounded, because the fix for
|
|
42
|
+
* such a bug is usually to make the overtake impossible — and then a hook
|
|
43
|
+
* that waits for it forever hangs the suite that proves it.
|
|
44
|
+
*/
|
|
45
|
+
holdAppend: ((events: readonly StreamEventInput[]) => Promise<void> | undefined) | undefined;
|
|
46
|
+
/** Set by MemoryStreamNetwork.get(); a detached stream answers `at()` with itself. */
|
|
47
|
+
network: MemoryStreamNetwork | undefined;
|
|
48
|
+
readonly path: string;
|
|
49
|
+
constructor(path?: string);
|
|
50
|
+
__describe(): Promise<{
|
|
51
|
+
instructions: string;
|
|
52
|
+
types: string;
|
|
53
|
+
children: {};
|
|
54
|
+
}>;
|
|
55
|
+
kill(): Promise<void>;
|
|
56
|
+
append(...inputs: StreamEventInput[]): Promise<StreamEvent[]>;
|
|
57
|
+
appendIfStreamId(args: {
|
|
58
|
+
streamId: string;
|
|
59
|
+
events: StreamEventInput[];
|
|
60
|
+
}): Promise<StreamEvent[]>;
|
|
61
|
+
at(path?: string): MemoryStream;
|
|
62
|
+
getEvent(input: {
|
|
63
|
+
offset: number;
|
|
64
|
+
} | {
|
|
65
|
+
idempotencyKey: string;
|
|
66
|
+
}): Promise<StreamEvent | undefined>;
|
|
67
|
+
getEvents(input?: StreamEventReadInput): Promise<StreamEvent[]>;
|
|
68
|
+
getEventPage(input?: StreamEventReadInput): Promise<{
|
|
69
|
+
streamId: `${string}-${string}-${string}-${string}-${string}`;
|
|
70
|
+
streamMaxOffset: number;
|
|
71
|
+
events: {
|
|
72
|
+
type: string;
|
|
73
|
+
offset: number;
|
|
74
|
+
createdAt: string;
|
|
75
|
+
path: string;
|
|
76
|
+
payload?: Record<string, unknown> | undefined;
|
|
77
|
+
metadata?: Record<string, unknown> | undefined;
|
|
78
|
+
source?: {
|
|
79
|
+
processor?: {
|
|
80
|
+
slug: string;
|
|
81
|
+
version: string;
|
|
82
|
+
stream: {
|
|
83
|
+
path: string;
|
|
84
|
+
projectId: string | null;
|
|
85
|
+
streamId: string;
|
|
86
|
+
};
|
|
87
|
+
whileProcessing?: {
|
|
88
|
+
offset: number;
|
|
89
|
+
type: string;
|
|
90
|
+
} | undefined;
|
|
91
|
+
} | undefined;
|
|
92
|
+
copiedFrom?: {
|
|
93
|
+
name: string;
|
|
94
|
+
streamId: string;
|
|
95
|
+
streamCreatedAt: string;
|
|
96
|
+
cursorChangedAtSourceOffset: number;
|
|
97
|
+
createdAt: string;
|
|
98
|
+
offset: number;
|
|
99
|
+
path: string;
|
|
100
|
+
projectId: string | null;
|
|
101
|
+
type: string;
|
|
102
|
+
}[] | undefined;
|
|
103
|
+
} | undefined;
|
|
104
|
+
idempotencyKey?: string | undefined;
|
|
105
|
+
ephemeral?: true | undefined;
|
|
106
|
+
}[];
|
|
107
|
+
}>;
|
|
108
|
+
readEvents(input?: StreamEventReadInput): {
|
|
109
|
+
next: () => Promise<{
|
|
110
|
+
type: string;
|
|
111
|
+
offset: number;
|
|
112
|
+
createdAt: string;
|
|
113
|
+
path: string;
|
|
114
|
+
payload?: Record<string, unknown> | undefined;
|
|
115
|
+
metadata?: Record<string, unknown> | undefined;
|
|
116
|
+
source?: {
|
|
117
|
+
processor?: {
|
|
118
|
+
slug: string;
|
|
119
|
+
version: string;
|
|
120
|
+
stream: {
|
|
121
|
+
path: string;
|
|
122
|
+
projectId: string | null;
|
|
123
|
+
streamId: string;
|
|
124
|
+
};
|
|
125
|
+
whileProcessing?: {
|
|
126
|
+
offset: number;
|
|
127
|
+
type: string;
|
|
128
|
+
} | undefined;
|
|
129
|
+
} | undefined;
|
|
130
|
+
copiedFrom?: {
|
|
131
|
+
name: string;
|
|
132
|
+
streamId: string;
|
|
133
|
+
streamCreatedAt: string;
|
|
134
|
+
cursorChangedAtSourceOffset: number;
|
|
135
|
+
createdAt: string;
|
|
136
|
+
offset: number;
|
|
137
|
+
path: string;
|
|
138
|
+
projectId: string | null;
|
|
139
|
+
type: string;
|
|
140
|
+
}[] | undefined;
|
|
141
|
+
} | undefined;
|
|
142
|
+
idempotencyKey?: string | undefined;
|
|
143
|
+
ephemeral?: true | undefined;
|
|
144
|
+
}[]>;
|
|
145
|
+
[Symbol.dispose](): void;
|
|
146
|
+
};
|
|
147
|
+
waitForEvent(input: {
|
|
148
|
+
afterOffset?: number;
|
|
149
|
+
eventTypes?: readonly string[];
|
|
150
|
+
predicate?: (event: StreamEvent) => boolean | Promise<boolean>;
|
|
151
|
+
timeoutMs: number;
|
|
152
|
+
}): Promise<StreamEvent>;
|
|
153
|
+
getProcessorRuntimeState(): Promise<null>;
|
|
154
|
+
runtimeState(): Promise<{
|
|
155
|
+
coreProcessorState: null;
|
|
156
|
+
runtime: {
|
|
157
|
+
connections: {};
|
|
158
|
+
sending: {};
|
|
159
|
+
metrics: {
|
|
160
|
+
measuredSince: string;
|
|
161
|
+
reportedAt: string;
|
|
162
|
+
ingress: {
|
|
163
|
+
perSecond5s: number;
|
|
164
|
+
bytesPerSecond5s: number;
|
|
165
|
+
lastMinute: {
|
|
166
|
+
count: number;
|
|
167
|
+
bytes: number;
|
|
168
|
+
perSecond: number;
|
|
169
|
+
};
|
|
170
|
+
series: {
|
|
171
|
+
counts: any[];
|
|
172
|
+
bytes: any[];
|
|
173
|
+
};
|
|
174
|
+
};
|
|
175
|
+
egress: {
|
|
176
|
+
perSecond5s: number;
|
|
177
|
+
bytesPerSecond5s: number;
|
|
178
|
+
lastMinute: {
|
|
179
|
+
count: number;
|
|
180
|
+
bytes: number;
|
|
181
|
+
perSecond: number;
|
|
182
|
+
};
|
|
183
|
+
series: {
|
|
184
|
+
counts: any[];
|
|
185
|
+
bytes: any[];
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
storageSizeBytes: number;
|
|
190
|
+
};
|
|
191
|
+
}>;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* In-memory network of streams keyed by path, so router tests can observe
|
|
195
|
+
* the cross-stream forwards (`stream.at(path).append(...)`) next to
|
|
196
|
+
* same-stream appends. `now` feeds every member stream's createdAt stamp, so
|
|
197
|
+
* freshness checks (such as webhook acknowledgement horizons) can be tested on both sides
|
|
198
|
+
* of the horizon. `eventsAt` never creates a stream — `network.streams.size`
|
|
199
|
+
* assertions ("nothing was forwarded anywhere") stay honest.
|
|
200
|
+
*/
|
|
201
|
+
export declare class MemoryStreamNetwork {
|
|
202
|
+
readonly streams: Map<string, MemoryStream>;
|
|
203
|
+
readonly now: () => number;
|
|
204
|
+
constructor(now?: () => number);
|
|
205
|
+
get(path: string): MemoryStream;
|
|
206
|
+
eventsAt(path: string): StreamEvent[];
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* One scenario step. Three built-in kinds plus a function escape hatch:
|
|
210
|
+
*
|
|
211
|
+
* - `["append", ...events]` — typed appends (the contract's `consumes`
|
|
212
|
+
* vocabulary: what the outside world can put on this processor's stream);
|
|
213
|
+
* - `["advanceTime", ms]` — move the virtual clock, releasing any harness
|
|
214
|
+
* `sleep(...)` calls that come due;
|
|
215
|
+
* - `["crash"]` — abandon the incarnation like an eviction (runtime state and
|
|
216
|
+
* pending closures die; stream, progress, and clock survive);
|
|
217
|
+
* - `async () => ...` — anything processor-specific (resolve a fake transport,
|
|
218
|
+
* assert mid-scenario).
|
|
219
|
+
*
|
|
220
|
+
* After every step the harness drives delivery to a fixpoint, so each step
|
|
221
|
+
* observes the stream consequences of the previous one.
|
|
222
|
+
*/
|
|
223
|
+
export type HarnessStep<Contract extends StreamProcessorContract> = readonly ["append", ...ConsumedInput<Contract>[]] | readonly ["advanceTime", number] | readonly ["crash"] | (() => unknown);
|
|
224
|
+
/** The durable substrate shared across incarnations (and zombie twins). */
|
|
225
|
+
export type HarnessSubstrate = {
|
|
226
|
+
clock: {
|
|
227
|
+
now: number;
|
|
228
|
+
};
|
|
229
|
+
stream: MemoryStream;
|
|
230
|
+
progress: ProcessorProgressStore<unknown>;
|
|
231
|
+
};
|
|
232
|
+
/** What {@link makeProcessorHarness}'s factory receives: base deps plus the
|
|
233
|
+
* harness's virtual clock/sleep, for processors that take injectable time. */
|
|
234
|
+
export type HarnessProcessorDeps<Contract extends StreamProcessorContract> = {
|
|
235
|
+
stream: ProcessorStream;
|
|
236
|
+
path: string;
|
|
237
|
+
projectId: string | null;
|
|
238
|
+
now: () => number;
|
|
239
|
+
sleep: (ms: number) => Promise<void>;
|
|
240
|
+
reads: Pick<RegisteredProcessorReads<ProcessorState<Contract>>, "snapshot" | "waitUntilEvent">;
|
|
241
|
+
};
|
|
242
|
+
export type ProcessorHarness<Contract extends StreamProcessorContract, Processor extends StreamProcessor<Contract, object> = StreamProcessor<Contract, object>> = {
|
|
243
|
+
clock: {
|
|
244
|
+
now: number;
|
|
245
|
+
};
|
|
246
|
+
stream: MemoryStream;
|
|
247
|
+
substrate: HarnessSubstrate;
|
|
248
|
+
/** The current incarnation's runner, for tests that need its full surface.
|
|
249
|
+
* A method (not a property) so suites can spread the harness into a wider
|
|
250
|
+
* object without freezing a pre-crash incarnation. */
|
|
251
|
+
runner(): StreamProcessorRunner<Contract>;
|
|
252
|
+
/** The current incarnation's processor instance. */
|
|
253
|
+
processor(): Processor;
|
|
254
|
+
/** Run steps in order, driving delivery to a fixpoint after each. */
|
|
255
|
+
play(...steps: HarnessStep<Contract>[]): Promise<void>;
|
|
256
|
+
/** Typed append (the contract's `consumes` vocabulary) + drive to fixpoint. */
|
|
257
|
+
append(...events: ConsumedInput<Contract>[]): Promise<void>;
|
|
258
|
+
/** Advance the virtual clock, release due sleeps, drive to fixpoint. */
|
|
259
|
+
advanceTime(ms: number): Promise<void>;
|
|
260
|
+
/** Abandon this incarnation like an eviction; a fresh one takes over the
|
|
261
|
+
* same stream/progress/clock. Does NOT deliver — the successor first acts
|
|
262
|
+
* on the next step, exactly like a real revival. */
|
|
263
|
+
crash(): void;
|
|
264
|
+
/** Drive delivery to a fixpoint: repeated catch-up passes (with microtask
|
|
265
|
+
* drains between them, so settled background work can land its appends)
|
|
266
|
+
* until the stream head stops moving. */
|
|
267
|
+
settle(): Promise<void>;
|
|
268
|
+
/** The runner's committed reduced state. */
|
|
269
|
+
state(): ProcessorState<Contract>;
|
|
270
|
+
/** All committed stream rows. */
|
|
271
|
+
events(): StreamEvent[];
|
|
272
|
+
/** Committed rows of one event type, typed when the contract resolves it. */
|
|
273
|
+
events<Type extends string>(type: Type): ResolvedEvent<Contract, Type>[];
|
|
274
|
+
};
|
|
275
|
+
/** In-memory {@link ProcessorProgressStore} with the DO store's fencing check,
|
|
276
|
+
* so progress survives `crash()` into the successor incarnation. Exported so
|
|
277
|
+
* suites can hand a harness a FRESH store over an existing stream — a full
|
|
278
|
+
* replay from offset zero, which is both the re-reduce-from-scratch recipe and the harshest
|
|
279
|
+
* at-least-once redelivery test (every per-event append re-runs).
|
|
280
|
+
*
|
|
281
|
+
* The contract is required because progress and recovery share the same
|
|
282
|
+
* per-processor Durable Object keys. A generic placeholder slug would let the
|
|
283
|
+
* runner commit progress under one key while recovery looks under another.
|
|
284
|
+
*/
|
|
285
|
+
export declare function makeMemoryProgressStore(contract: Pick<StreamProcessorContract, "slug">): ProcessorProgressStore<unknown>;
|
|
286
|
+
/**
|
|
287
|
+
* Build a {@link ProcessorHarness}: the real runner, ProcessorKeepalive, and
|
|
288
|
+
* Durable Object durability adapters over an in-memory stream/KV/alarm
|
|
289
|
+
* substrate. `crash()` is eviction: delivery stays detached until a new
|
|
290
|
+
* append wakes it or a due keepalive alarm appends the revival fact. Pass
|
|
291
|
+
* another harness's `substrate` to run a second incarnation over the same
|
|
292
|
+
* durable state (the zombie-race setup).
|
|
293
|
+
*
|
|
294
|
+
* Appends commit synchronously unless a suite opts out through
|
|
295
|
+
* `harness.stream.holdAppend` — the one seam for reproducing a processor that
|
|
296
|
+
* appends the same lane from two places and orders only one of them.
|
|
297
|
+
*/
|
|
298
|
+
export declare function makeProcessorHarness<Contract extends StreamProcessorContract, Processor extends StreamProcessor<Contract, object> = StreamProcessor<Contract, object>>(args: {
|
|
299
|
+
createProcessor: (deps: HarnessProcessorDeps<Contract>) => Processor;
|
|
300
|
+
path?: string;
|
|
301
|
+
substrate?: HarnessSubstrate;
|
|
302
|
+
}): ProcessorHarness<Contract, Processor>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import "./usingCtx-mZx5nsAW.mjs";
|
|
2
|
+
//#region src/processors/idempotency.ts
|
|
3
|
+
const IDEMPOTENCY_CONFLICT_FRAGMENT = " already names a different event at offset ";
|
|
4
|
+
function isIdempotencyConflict(error) {
|
|
5
|
+
return (error instanceof Error ? error.message : String(error)).includes(IDEMPOTENCY_CONFLICT_FRAGMENT);
|
|
6
|
+
}
|
|
7
|
+
//#endregion
|
|
8
|
+
export { isIdempotencyConflict as t };
|
|
9
|
+
|
|
10
|
+
//# sourceMappingURL=processors-BoNyeBfQ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processors-BoNyeBfQ.mjs","names":[],"sources":["../src/processors/idempotency.ts"],"sourcesContent":["// The Stream DO's idempotency semantics, importable: a same-key append is a\n// dedup ONLY when its body is structurally identical — otherwise it must be\n// rejected. Lives here so the production Stream Durable Object and the\n// MemoryStream test double share ONE predicate and cannot drift.\n\ntype EventBody = {\n type: string;\n payload?: unknown;\n metadata?: unknown;\n ephemeral?: boolean | undefined;\n};\n\n// The wording is a live wire contract: the rejection crosses Workers RPC,\n// which preserves the message but not class identity, so deployed processors\n// classify the conflict by this text. Mint with the builder, match with the\n// predicate — never spell the wording anywhere else.\nconst IDEMPOTENCY_CONFLICT_FRAGMENT = \" already names a different event at offset \";\n\nexport function idempotencyConflictMessage(idempotencyKey: string, existingOffset: number) {\n return `idempotency key \"${idempotencyKey}\"${IDEMPOTENCY_CONFLICT_FRAGMENT}${existingOffset}`;\n}\n\nexport function isIdempotencyConflict(error: unknown) {\n const message = error instanceof Error ? error.message : String(error);\n return message.includes(IDEMPOTENCY_CONFLICT_FRAGMENT);\n}\n\n/** Whether a requested append names the SAME event an idempotency key already committed. */\nexport function sameIdempotentEvent(existing: EventBody, requested: EventBody): boolean {\n return (\n existing.type === requested.type &&\n jsonValuesEqual(existing.payload, requested.payload) &&\n jsonValuesEqual(existing.metadata, requested.metadata) &&\n existing.ephemeral === requested.ephemeral\n );\n}\n\n/** Structural JSON equality (key-order-insensitive). */\nexport function jsonValuesEqual(left: unknown, right: unknown): boolean {\n if (Object.is(left, right)) return true;\n if (Array.isArray(left) || Array.isArray(right)) {\n return (\n Array.isArray(left) &&\n Array.isArray(right) &&\n left.length === right.length &&\n left.every((value, index) => jsonValuesEqual(value, right[index]))\n );\n }\n if (typeof left === \"object\" && typeof right === \"object\" && left !== null && right !== null) {\n const leftKeys = Object.keys(left).sort();\n const rightKeys = Object.keys(right).sort();\n if (leftKeys.length !== rightKeys.length) return false;\n return leftKeys.every(\n (key, index) =>\n key === rightKeys[index] &&\n jsonValuesEqual(\n (left as Record<string, unknown>)[key],\n (right as Record<string, unknown>)[key],\n ),\n );\n }\n return false;\n}\n"],"mappings":";;AAgBA,MAAM,gCAAgC;AAMtC,SAAgB,sBAAsB,OAAgB;CAEpD,QADgB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAA,CACtD,SAAS,6BAA6B;AACvD"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { a as createStreamProcessorRegistry, i as plainAlarmInvocationInfo, n as ProcessorFacet, r as facetProcessorDurableObjectState, t as FACET_IDENTITY_KEY } from "./cloudflare-BTm90gQ4.mjs";
|
|
2
|
+
import { i as processorProgressKey, n as durableObjectRecovery, r as processorKeepaliveKey, t as durableObjectProgressStore } from "./durable-object-processor-durability-CNsTjAJS.mjs";
|
|
3
|
+
export { FACET_IDENTITY_KEY, ProcessorFacet, createStreamProcessorRegistry, durableObjectProgressStore, durableObjectRecovery, facetProcessorDurableObjectState, plainAlarmInvocationInfo, processorKeepaliveKey, processorProgressKey };
|