@johannc-dev/zyrk 0.0.0-stage → 0.2.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.
@@ -0,0 +1,235 @@
1
+ import { type PendingEvent, type ReplayProgress } from "./local-replay.js";
2
+ import { LocalData } from "./local-data.js";
3
+ import { LocalStorage, type AreaConfig } from "./local-storage.js";
4
+ import { accountLimits, execLimits } from "./limits.js";
5
+ import { type JobFailure, type JobResult, type JobStatus, type Json, type Program, type Subscription } from "./sdk.js";
6
+ /** The sandbox bootstrap shipped with the package (see scripts/build.mjs). */
7
+ export declare function sandboxBootstrap(): string;
8
+ export type ProgramSource =
9
+ /** Entry point (`.ts`/`.js`), built as `zyrk deploy` builds it. */
10
+ string
11
+ /** A built bundle (`.functions/program.js`). */
12
+ | {
13
+ readonly code: string;
14
+ }
15
+ /** A program object imported in your test (runs with Node's globals). */
16
+ | Program;
17
+ type Numbers<T> = {
18
+ readonly [K in keyof T]: number;
19
+ };
20
+ export interface LocalLimits {
21
+ readonly exec: Numbers<typeof execLimits>;
22
+ readonly account: Numbers<typeof accountLimits>;
23
+ }
24
+ export interface LocalOptions {
25
+ /** Directory written by `zyrk export`, or a {@link LocalData}. */
26
+ readonly data?: string | LocalData;
27
+ /**
28
+ * Program state: a folder (kept in `<folder>/<program>.json` between
29
+ * runs), or initial values in memory. Default: empty, in memory.
30
+ */
31
+ readonly state?: string | Readonly<Record<string, Json>>;
32
+ /** User storage: a folder, or `"memory"` (default). */
33
+ readonly storage?: string | LocalStorage;
34
+ /** Storage areas and their quotas (default: `short` and `long` as documented). */
35
+ readonly storageAreas?: Readonly<Record<string, AreaConfig>>;
36
+ /** Print logs and emits as they happen (`zyrk dev`), or receive them. */
37
+ readonly console?: boolean | ((line: ConsoleLine) => void);
38
+ /** Program name in `ctx.execution.program` (default `local`). */
39
+ readonly program?: string;
40
+ /** Override limits (default: the service's, `@johannc-dev/zyrk/limits`). */
41
+ readonly limits?: {
42
+ readonly exec?: Partial<Numbers<typeof execLimits>>;
43
+ readonly account?: Partial<Numbers<typeof accountLimits>>;
44
+ };
45
+ /** `zyrk build` type-checking of an entry point (default true). */
46
+ readonly typecheck?: boolean;
47
+ readonly now?: () => number;
48
+ /**
49
+ * The account's webhook, as `PUT /v1/functions/webhook` would set it.
50
+ * Default: none, so `ctx.webhook.send` rejects with
51
+ * `webhook_not_configured`, as on the service. Messages are never sent
52
+ * locally: they stay queued (`queueLimit`, default 1000, then
53
+ * `webhook_queue_full` or `dropped: true` with `onFull: "drop"`).
54
+ */
55
+ readonly webhook?: LocalWebhook;
56
+ }
57
+ /** {@link LocalOptions.webhook}. */
58
+ export interface LocalWebhook {
59
+ /** A webhook is set (default false). */
60
+ readonly configured?: boolean;
61
+ /** Not paused (default true). */
62
+ readonly enabled?: boolean;
63
+ /** Messages waiting before the queue is full (default 1000, the service's). */
64
+ readonly queueLimit?: number;
65
+ }
66
+ export interface ConsoleLine {
67
+ readonly kind: "log" | "emit" | "webhook";
68
+ readonly execution: string;
69
+ readonly function: string;
70
+ readonly value: Json;
71
+ }
72
+ export interface LocalUsage {
73
+ /** Rough: process CPU while the execution ran, reads excluded (parallel jobs overlap). */
74
+ cpuMs: number;
75
+ readMs: number;
76
+ wallMs: number;
77
+ readBytes: number;
78
+ readCalls: number;
79
+ hostOps: number;
80
+ outputBytes: number;
81
+ /** Rough: growth of Node's heap while the execution ran. */
82
+ peakHeapBytes: number;
83
+ }
84
+ /** One execution, as `GET /executions/{id}` would show it. */
85
+ export interface LocalExecution {
86
+ readonly id: string;
87
+ readonly function: string;
88
+ readonly args: Json;
89
+ readonly status: JobStatus;
90
+ readonly result?: Json;
91
+ readonly error?: JobFailure;
92
+ readonly logs: readonly Json[];
93
+ readonly emits: readonly Json[];
94
+ readonly usage: LocalUsage;
95
+ readonly children: readonly string[];
96
+ /** Id of the continuation (`ctx.jobs.continue`), if any. */
97
+ readonly next?: string;
98
+ }
99
+ /** What {@link LocalRunner.run} answers: the last execution of the chain, and the chain. */
100
+ export interface LocalRun {
101
+ readonly id: string;
102
+ readonly status: "succeeded" | "failed" | "cancelled";
103
+ readonly result?: Json;
104
+ /** The result as the sandbox serializes it (the bytes the service stores). */
105
+ readonly resultText?: string;
106
+ readonly error?: JobFailure;
107
+ /** Logs and emits of the whole chain (continuations included). */
108
+ readonly logs: readonly Json[];
109
+ readonly emits: readonly Json[];
110
+ /** `ctx.webhook.send` payloads of the chain (never sent locally). */
111
+ readonly webhooks: readonly Json[];
112
+ readonly executions: readonly LocalExecution[];
113
+ /** Where this run may differ from the service. */
114
+ readonly warnings: readonly string[];
115
+ }
116
+ /**
117
+ * A local account with one program: executions, their jobs, the program's
118
+ * state and subscriptions, and user storage. Keep one runner across calls
119
+ * to keep state between executions, as the service does.
120
+ */
121
+ export declare class LocalRunner {
122
+ #private;
123
+ readonly data: LocalData | undefined;
124
+ readonly storage: LocalStorage;
125
+ readonly limits: LocalLimits;
126
+ /** Committed program state. */
127
+ readonly state: Map<string, Json>;
128
+ /** Active subscriptions (declared, then changed by `ctx.subscriptions`). */
129
+ readonly subscriptions: Map<string, Subscription>;
130
+ readonly warnings: string[];
131
+ private constructor();
132
+ /** Builds (entry path) or takes a bundle, and reads its description as the service does at deploy. */
133
+ static load(source: ProgramSource, options?: LocalOptions): Promise<LocalRunner>;
134
+ /** Resolves when no execution runs or waits any more (jobs, completions). */
135
+ idle(): Promise<void>;
136
+ /** Every job of the account, as `ctx.jobs.result` sees it. */
137
+ jobs(): JobResult[];
138
+ /** Every execution, in start order. */
139
+ executions(): LocalExecution[];
140
+ /**
141
+ * Runs `fn(args)` as `zyrk run` does, follows its continuations, and
142
+ * answers the last execution of the chain. Jobs it started may still run:
143
+ * `await runner.idle()` to wait for them.
144
+ */
145
+ run(fn: string, args?: Json): Promise<LocalRun>;
146
+ /**
147
+ * Replays a subscription over `[sinceMs, untilMs)` from exported history,
148
+ * as the service's replays do (local-replay.ts): the same deliveries, at
149
+ * most 32 events each, one at a time (the next waits for the previous one
150
+ * and its jobs), with `replay: { id, delivery, clockMs, sinceMs, untilMs,
151
+ * simulated: true }`. The deliveries run in an isolated copy of the
152
+ * program: its state starts empty and is not this runner's, and
153
+ * `ctx.subscriptions` fails there (`replay_isolated`). Stops at the first
154
+ * delivery that fails (`delivery_failed`).
155
+ */
156
+ replay(options: ReplayOptions): Promise<LocalReplay>;
157
+ /** The events {@link replay} delivers, without running anything. */
158
+ replayEvents(s: Subscription, o: ReplayOptions): PendingEvent[];
159
+ }
160
+ export interface ReplayOptions {
161
+ /** Name of an active subscription of the program. */
162
+ readonly subscription: string;
163
+ readonly sinceMs: number;
164
+ readonly untilMs: number;
165
+ /** Events per delivery, 1 to 32 (default 32, as the service). */
166
+ readonly eventsPerDelivery?: number;
167
+ /**
168
+ * Events per delivery, 1 to 1,000: the service's `batchSize` (larger
169
+ * batches than live, opt-in). Wins over `eventsPerDelivery`.
170
+ */
171
+ readonly batchSize?: number;
172
+ /** Stop after this many deliveries. */
173
+ readonly maxDeliveries?: number;
174
+ /**
175
+ * Receives the replay's emits and execution records as they come, as the
176
+ * service sends them (`GET /replays/{id}/emits`): `{kind: "emitted",
177
+ * data, seq}` then `{kind: "execution", execution, seq}` per delivery.
178
+ * With it, `runs` and `emits` of the answer stay empty (nothing is kept).
179
+ */
180
+ readonly onFeed?: (item: Record<string, Json>) => void;
181
+ /**
182
+ * Without `onFeed`: bytes of emits and records kept before the replay
183
+ * fails with `replay_feed_full` (the service's bound, 16 MiB).
184
+ */
185
+ readonly feedBytes?: number;
186
+ /** Longest wall-clock time (default 30 min, the service's). */
187
+ readonly maxDurationMs?: number;
188
+ /**
189
+ * Copies what the replay wrote in its own storage space to the runner's
190
+ * storage when it succeeds (otherwise that space is dropped): the
191
+ * objects of area `from` (default `to`), or only `keys`, into `to`,
192
+ * within that area's quota (refused as a whole).
193
+ */
194
+ readonly keepStorage?: KeepStorage;
195
+ }
196
+ /** {@link ReplayOptions.keepStorage}. */
197
+ export interface KeepStorage {
198
+ readonly to: "long" | "durable";
199
+ readonly from?: "short" | "long" | "durable";
200
+ readonly keys?: readonly string[];
201
+ }
202
+ /** The service's `ReplayLimits::max_duration_ms` (30 min). */
203
+ export declare const REPLAY_MAX_DURATION_MS: number;
204
+ /** The service's `FeedLimits::replay_bytes` (16 MiB). */
205
+ export declare const REPLAY_FEED_BYTES: number;
206
+ /** What {@link LocalRunner.replay} answers (the service's replay record, locally). */
207
+ export interface LocalReplay {
208
+ readonly id: string;
209
+ readonly status: "succeeded" | "failed";
210
+ /** `delivery_failed` when a delivery failed for good. */
211
+ readonly error?: JobFailure;
212
+ /** One run per delivery, in order. */
213
+ readonly runs: readonly LocalRun[];
214
+ /** The isolated state at the end (the runner's own state is untouched). */
215
+ readonly state: ReadonlyMap<string, Json>;
216
+ readonly emits: readonly Json[];
217
+ readonly progress: Readonly<ReplayProgress>;
218
+ readonly warnings: readonly string[];
219
+ /** What `keepStorage` copied (or why nothing was). */
220
+ readonly keptStorage?: {
221
+ readonly copied: true;
222
+ readonly objects: number;
223
+ readonly bytes: number;
224
+ } | {
225
+ readonly copied: false;
226
+ readonly error: JobFailure;
227
+ };
228
+ }
229
+ /**
230
+ * Runs one function locally, as `zyrk run` does in the service, and waits
231
+ * for the jobs it started. For several runs sharing state, use
232
+ * {@link LocalRunner}.
233
+ */
234
+ export declare function runLocal(source: ProgramSource, fn: string, args?: Json, options?: LocalOptions): Promise<LocalRun>;
235
+ export {};