@restatedev/restate-sdk-gen 0.0.0 → 1.14.2

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/dist/index.cjs ADDED
@@ -0,0 +1,1129 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+
23
+ //#endregion
24
+ let __restatedev_restate_sdk = require("@restatedev/restate-sdk");
25
+ __restatedev_restate_sdk = __toESM(__restatedev_restate_sdk);
26
+
27
+ //#region src/current.ts
28
+ let CURRENT = null;
29
+ /**
30
+ * Save the previous slot, install `value` as the current. Returns the
31
+ * previous value so `clearCurrent` can restore it (supports nested
32
+ * scheduler invocations on the same thread, even though we don't expect
33
+ * any in production).
34
+ */
35
+ function setCurrent(value) {
36
+ const prev = CURRENT;
37
+ CURRENT = value;
38
+ return prev;
39
+ }
40
+ /** Restore a slot previously captured by `setCurrent`. */
41
+ function clearCurrent(prev) {
42
+ CURRENT = prev;
43
+ }
44
+ /**
45
+ * Read the slot, throwing if no fiber is currently advancing. Callers
46
+ * cast the return type — the slot is intentionally `unknown` here so
47
+ * this module stays free of cycles.
48
+ */
49
+ function getCurrent() {
50
+ if (CURRENT === null) throw new Error("@restatedev/restate-sdk-gen: free-standing API called outside an active fiber. Call from inside `execute(ctx, gen(function*() { ... }))`.");
51
+ return CURRENT;
52
+ }
53
+
54
+ //#endregion
55
+ //#region src/free.ts
56
+ /**
57
+ * Read the active `RestateOperations` from the current-fiber slot.
58
+ * Throws if called outside a fiber's synchronous advance span (e.g.,
59
+ * at module init or inside an `ops.run` async closure that resolved
60
+ * after the fiber returned).
61
+ */
62
+ function currentOps() {
63
+ return getCurrent();
64
+ }
65
+ /**
66
+ * Run a side-effecting closure as a journal entry. See
67
+ * `RestateOperations.run` for full semantics.
68
+ *
69
+ * `name` is derived from `action.name` (works for named functions and
70
+ * arrow functions assigned to a `const`) or specified explicitly via
71
+ * `opts.name`. If neither resolves, throws.
72
+ */
73
+ const run = (action, opts) => currentOps().run(action, opts);
74
+ const sleep = (duration, name) => currentOps().sleep(duration, name);
75
+ const awakeable = (serde) => currentOps().awakeable(serde);
76
+ const resolveAwakeable = (id, payload, serde) => currentOps().resolveAwakeable(id, payload, serde);
77
+ const rejectAwakeable = (id, reason) => currentOps().rejectAwakeable(id, reason);
78
+ const signal = (name, serde) => currentOps().signal(name, serde);
79
+ const attach = (invocationId, serde) => currentOps().attach(invocationId, serde);
80
+ const serviceClient = (api) => currentOps().serviceClient(api);
81
+ const objectClient = (api, key) => currentOps().objectClient(api, key);
82
+ const workflowClient = (api, key) => currentOps().workflowClient(api, key);
83
+ const serviceSendClient = (api) => currentOps().serviceSendClient(api);
84
+ const objectSendClient = (api, key) => currentOps().objectSendClient(api, key);
85
+ const workflowSendClient = (api, key) => currentOps().workflowSendClient(api, key);
86
+ const genericCall = (call) => currentOps().genericCall(call);
87
+ const genericSend = (call) => currentOps().genericSend(call);
88
+ const cancel = (invocationId) => currentOps().cancel(invocationId);
89
+ const channel = () => currentOps().channel();
90
+ const state = () => currentOps().state();
91
+ const sharedState = () => currentOps().sharedState();
92
+ const workflowPromise = (name, serde) => currentOps().workflowPromise(name, serde);
93
+ /**
94
+ * Wait for every future to settle; return their values in input order.
95
+ * Heterogeneous-tuple typing — `all([fA, fB])` where `fA: Future<A>`
96
+ * and `fB: Future<B>` yields `Future<[A, B]>`. Mirrors `Promise.all`.
97
+ */
98
+ const all = (futures) => currentOps().all(futures);
99
+ /**
100
+ * Return the first future to settle; losers continue running but their
101
+ * results are discarded. Heterogeneous-tuple typing — `race([fA, fB])`
102
+ * yields `Future<A | B>`. Mirrors `Promise.race`.
103
+ */
104
+ const race = (futures) => currentOps().race(futures);
105
+ /**
106
+ * First-to-succeed wins (non-rejected). Rejects with `AggregateError(errors)`
107
+ * when every input rejects (including the empty input case). Tuple-aware —
108
+ * `any([fA, fB])` yields `Future<A | B>`. Mirrors `Promise.any`.
109
+ */
110
+ const any = (futures) => currentOps().any(futures);
111
+ /**
112
+ * Wait for every future to settle; never rejects. Tuple-aware —
113
+ * `allSettled([fA, fB])` yields
114
+ * `Future<[FutureSettledResult<A>, FutureSettledResult<B>]>`.
115
+ * Mirrors `Promise.allSettled`.
116
+ */
117
+ const allSettled = (futures) => currentOps().allSettled(futures);
118
+
119
+ //#endregion
120
+ //#region src/operation.ts
121
+ const opTag = Symbol("restateOperation");
122
+ function makePrimitive(node) {
123
+ const op = {
124
+ [opTag]: node,
125
+ *[Symbol.iterator]() {
126
+ return yield op;
127
+ }
128
+ };
129
+ return op;
130
+ }
131
+ function awaitRace(futures) {
132
+ const op = {
133
+ [opTag]: {
134
+ _tag: "AwaitRace",
135
+ futures
136
+ },
137
+ *[Symbol.iterator]() {
138
+ return yield op;
139
+ }
140
+ };
141
+ return op;
142
+ }
143
+ function gen(body) {
144
+ return { [Symbol.iterator]: body };
145
+ }
146
+ function spawn(op) {
147
+ return makePrimitive({
148
+ _tag: "Spawn",
149
+ child: op
150
+ });
151
+ }
152
+ function* select(branches) {
153
+ const tags = Object.keys(branches);
154
+ const tag = tags[(yield* awaitRace(tags.map((t) => branches[t]))).index];
155
+ return {
156
+ tag,
157
+ future: branches[tag]
158
+ };
159
+ }
160
+
161
+ //#endregion
162
+ //#region src/state.ts
163
+ /**
164
+ * Build a `State<TState>` over the given context. The runtime delegates
165
+ * straight to `ctx.get` / `ctx.set` / etc.; the TState generic is purely
166
+ * a TS-level convenience and gets erased at runtime.
167
+ *
168
+ * For shared (read-only) contexts, the returned State has the same
169
+ * runtime shape but the caller should use the `SharedState<TState>`
170
+ * type to drop the write methods. The convenience method
171
+ * `RestateOperations.sharedState()` does this cast.
172
+ */
173
+ function makeState(ctx, sched, adapt$1) {
174
+ const writeCtx = ctx;
175
+ return {
176
+ get(name, serde) {
177
+ return sched.makeJournalFuture(adapt$1(ctx.get(name, serde)));
178
+ },
179
+ keys() {
180
+ return sched.makeJournalFuture(adapt$1(ctx.stateKeys()));
181
+ },
182
+ set(name, value, serde) {
183
+ writeCtx.set(name, value, serde);
184
+ },
185
+ clear(name) {
186
+ writeCtx.clear(name);
187
+ },
188
+ clearAll() {
189
+ writeCtx.clearAll();
190
+ }
191
+ };
192
+ }
193
+
194
+ //#endregion
195
+ //#region src/clients.ts
196
+ /**
197
+ * Wrap an SDK `Client<M>` so each handler-invocation returns
198
+ * `Future<T>` (via the supplied `toFuture` adapter) instead of
199
+ * `InvocationPromise<T>`.
200
+ */
201
+ function wrapClient(client, toFuture) {
202
+ return new Proxy(client, { get(target, prop, receiver) {
203
+ const orig = Reflect.get(target, prop, receiver);
204
+ if (typeof orig !== "function") return orig;
205
+ return (...args) => {
206
+ return toFuture(orig.apply(target, args));
207
+ };
208
+ } });
209
+ }
210
+ /**
211
+ * Wrap an SDK `DurablePromise<T>` so each method returns `Future<...>`
212
+ * instead of `Promise<...>`/`RestatePromise<...>`.
213
+ */
214
+ function wrapDurablePromise(dp, toFuture) {
215
+ return {
216
+ peek: () => toFuture(dp.peek()),
217
+ resolve: (value) => toFuture(dp.resolve(value)),
218
+ reject: (errorMsg) => toFuture(dp.reject(errorMsg)),
219
+ get: () => toFuture(dp.get())
220
+ };
221
+ }
222
+
223
+ //#endregion
224
+ //#region src/default-lib.ts
225
+ const defaultLib = {
226
+ all(items) {
227
+ return __restatedev_restate_sdk.RestatePromise.all(items);
228
+ },
229
+ race(items) {
230
+ return __restatedev_restate_sdk.RestatePromise.race(items);
231
+ },
232
+ any(items) {
233
+ return __restatedev_restate_sdk.RestatePromise.any(items);
234
+ },
235
+ allSettled(items) {
236
+ return __restatedev_restate_sdk.RestatePromise.allSettled(items);
237
+ },
238
+ isCancellation(e) {
239
+ return e instanceof __restatedev_restate_sdk.CancelledError;
240
+ }
241
+ };
242
+
243
+ //#endregion
244
+ //#region src/future.ts
245
+ const futureBacking = Symbol("restateFutureBacking");
246
+ /**
247
+ * Internal accessor — read the backing off a Future. Only the scheduler
248
+ * and fiber call this; user code never sees Backing.
249
+ */
250
+ function getBacking(f) {
251
+ return f[futureBacking];
252
+ }
253
+ function makeFuture(backing) {
254
+ const future = {
255
+ [futureBacking]: backing,
256
+ *[Symbol.iterator]() {
257
+ return yield leafOp;
258
+ }
259
+ };
260
+ const leafOp = makePrimitive({
261
+ _tag: "Leaf",
262
+ future
263
+ });
264
+ return future;
265
+ }
266
+ function isJournalBacked(f) {
267
+ return getBacking(f).kind === "journal";
268
+ }
269
+
270
+ //#endregion
271
+ //#region src/fiber.ts
272
+ var Fiber = class {
273
+ it;
274
+ sched;
275
+ state = {
276
+ kind: "ready",
277
+ resume: null
278
+ };
279
+ waiters = [];
280
+ constructor(op, sched) {
281
+ this.it = op[Symbol.iterator]();
282
+ this.sched = sched;
283
+ }
284
+ isDone() {
285
+ return this.state.kind === "done";
286
+ }
287
+ /**
288
+ * For a fiber known to be done, return its settled outcome. Throws
289
+ * if called on a non-done fiber — callers must check `isDone()` first
290
+ * (or use `awaitCompletion` for the polymorphic version).
291
+ */
292
+ settledValue() {
293
+ if (this.state.kind !== "done") throw new Error("Fiber.settledValue called on non-done fiber");
294
+ return this.state.settled;
295
+ }
296
+ /**
297
+ * Returns the parked sources this fiber is currently racing against.
298
+ * Empty if the fiber is parked only on routine waiters (e.g.,
299
+ * waiting on a sibling fiber to finish), or in any non-parked state.
300
+ * The scheduler reads these to assemble its main-loop race.
301
+ */
302
+ parkedSources() {
303
+ return this.state.kind === "parked" ? this.state.promises : [];
304
+ }
305
+ /**
306
+ * "I want to be notified when this fiber is done." If the fiber is
307
+ * already done, returns its settled outcome immediately (caller
308
+ * should NOT also expect the waiter to be invoked). Otherwise
309
+ * returns null and queues the waiter for invocation when the fiber
310
+ * eventually finishes.
311
+ */
312
+ awaitCompletion(waiter) {
313
+ if (this.state.kind === "done") return this.state.settled;
314
+ this.waiters.push(waiter);
315
+ return null;
316
+ }
317
+ /**
318
+ * Wake this fiber with a resume value. Transitions to ready and
319
+ * notifies the scheduler. May be called from any state except done
320
+ * (waking a done fiber is a programming error and is ignored
321
+ * defensively).
322
+ */
323
+ wake(resume) {
324
+ if (this.state.kind === "done") return;
325
+ this.state = {
326
+ kind: "ready",
327
+ resume
328
+ };
329
+ this.sched.markReady(this);
330
+ }
331
+ /**
332
+ * Drive the fiber's iterator until it parks (yields a primitive
333
+ * whose dispatch ends with the fiber waiting on a source) or
334
+ * finishes (returns or throws).
335
+ *
336
+ * No-op if the fiber is not in the ready state — protects against
337
+ * stale entries in the scheduler's ready queue.
338
+ */
339
+ advance() {
340
+ if (this.state.kind !== "ready") return;
341
+ const prevSlot = setCurrent(this.sched.contextSlot);
342
+ try {
343
+ let resume = this.state.resume;
344
+ while (true) {
345
+ let next;
346
+ try {
347
+ next = stepIterator(this.it, resume);
348
+ } catch (e) {
349
+ this.finish({
350
+ ok: false,
351
+ e
352
+ });
353
+ return;
354
+ }
355
+ if (next.done) {
356
+ this.finish({
357
+ ok: true,
358
+ v: next.value
359
+ });
360
+ return;
361
+ }
362
+ const node = next.value[opTag];
363
+ let outcome;
364
+ switch (node._tag) {
365
+ case "Leaf":
366
+ outcome = this.parkOnLeaf(node);
367
+ break;
368
+ case "Spawn":
369
+ outcome = {
370
+ ok: true,
371
+ v: this.sched.spawnFuture(node.child)
372
+ };
373
+ break;
374
+ case "AwaitRace":
375
+ outcome = this.parkOnAwaitRace(node.futures);
376
+ break;
377
+ }
378
+ if (outcome === null) return;
379
+ resume = outcome;
380
+ }
381
+ } finally {
382
+ clearCurrent(prevSlot);
383
+ }
384
+ }
385
+ /**
386
+ * Park on a single Future, or short-circuit if the Future is already
387
+ * settled. Returns the Settled value to feed back into the iterator
388
+ * if a short-circuit is possible (routine-backed future whose target
389
+ * already finished); returns null if the fiber is parked and the
390
+ * caller should suspend.
391
+ */
392
+ parkOnLeaf(leaf) {
393
+ const backing = getBacking(leaf.future);
394
+ if (backing.kind === "journal") {
395
+ this.state = {
396
+ kind: "parked",
397
+ promises: [{
398
+ promise: backing.promise,
399
+ fire: (s) => this.wake(s)
400
+ }]
401
+ };
402
+ return null;
403
+ }
404
+ const settled = backing.target.awaitCompletion((s) => this.wake(s));
405
+ if (settled !== null) return settled;
406
+ this.state = {
407
+ kind: "parked",
408
+ promises: []
409
+ };
410
+ return null;
411
+ }
412
+ /**
413
+ * Park on the first-to-settle of a list of Futures, or short-circuit
414
+ * if any source is already settled. Returns `{index, settled}`
415
+ * (wrapped as Settled) on short-circuit, or null if parked.
416
+ *
417
+ * On the parked path, every source registers a one-shot fire
418
+ * callback that wakes the fiber with `{index, settled}`. The `won`
419
+ * flag guards against duplicate wakes when multiple sources settle
420
+ * in the same tick. Local sources (fibers, channels) park on the
421
+ * target's waiter list; journal sources race in the main loop's
422
+ * race promise.
423
+ */
424
+ parkOnAwaitRace(futures) {
425
+ for (let i = 0; i < futures.length; i++) {
426
+ const b = getBacking(futures[i]);
427
+ if (b.kind === "local" && b.target.isDone()) return {
428
+ ok: true,
429
+ v: {
430
+ index: i,
431
+ settled: b.target.settledValue()
432
+ }
433
+ };
434
+ }
435
+ let won = false;
436
+ const promises = [];
437
+ for (let i = 0; i < futures.length; i++) {
438
+ const idx = i;
439
+ const b = getBacking(futures[i]);
440
+ const fireOnce = (settled) => {
441
+ if (won) return;
442
+ won = true;
443
+ this.wake({
444
+ ok: true,
445
+ v: {
446
+ index: idx,
447
+ settled
448
+ }
449
+ });
450
+ };
451
+ if (b.kind === "local") b.target.awaitCompletion(fireOnce);
452
+ else promises.push({
453
+ promise: b.promise,
454
+ fire: fireOnce
455
+ });
456
+ }
457
+ this.state = {
458
+ kind: "parked",
459
+ promises
460
+ };
461
+ return null;
462
+ }
463
+ /**
464
+ * Iterator finished or threw. Transition to done, fire all waiters
465
+ * with the settled outcome, notify scheduler.
466
+ */
467
+ finish(settled) {
468
+ this.state = {
469
+ kind: "done",
470
+ settled
471
+ };
472
+ const waiters = this.waiters;
473
+ this.waiters = [];
474
+ for (const w of waiters) w(settled);
475
+ this.sched.markDone(this);
476
+ }
477
+ };
478
+ /**
479
+ * Drive a generator iterator one step, feeding it whatever value or
480
+ * exception the caller is resuming with. `resume === null` is the
481
+ * very first step; `{ok: true, v}` resumes with a value; `{ok: false,
482
+ * e}` throws into the iterator (or, if the iterator has no `throw`
483
+ * method, rethrows so the fiber fails).
484
+ */
485
+ function stepIterator(it, resume) {
486
+ if (resume === null) return it.next(void 0);
487
+ if (resume.ok) return it.next(resume.v);
488
+ if (it.throw) return it.throw(resume.e);
489
+ throw resume.e;
490
+ }
491
+
492
+ //#endregion
493
+ //#region src/channel.ts
494
+ var ChannelImpl = class {
495
+ state = { kind: "pending" };
496
+ waiters = [];
497
+ fire(value) {
498
+ if (this.state.kind === "settled") return;
499
+ this.state = {
500
+ kind: "settled",
501
+ value
502
+ };
503
+ const ws = this.waiters;
504
+ this.waiters = [];
505
+ const settled = {
506
+ ok: true,
507
+ v: value
508
+ };
509
+ for (const w of ws) w(settled);
510
+ }
511
+ isDone() {
512
+ return this.state.kind === "settled";
513
+ }
514
+ settledValue() {
515
+ if (this.state.kind !== "settled") throw new Error("ChannelImpl.settledValue called on a pending channel");
516
+ return {
517
+ ok: true,
518
+ v: this.state.value
519
+ };
520
+ }
521
+ awaitCompletion(waiter) {
522
+ if (this.state.kind === "settled") return {
523
+ ok: true,
524
+ v: this.state.value
525
+ };
526
+ this.waiters.push(waiter);
527
+ return null;
528
+ }
529
+ };
530
+ function makeChannel() {
531
+ const impl = new ChannelImpl();
532
+ return {
533
+ send: (v) => gen(function* () {
534
+ impl.fire(v);
535
+ }),
536
+ receive: makeFuture({
537
+ kind: "local",
538
+ target: impl
539
+ })
540
+ };
541
+ }
542
+
543
+ //#endregion
544
+ //#region src/scheduler.ts
545
+ var Scheduler = class {
546
+ fibers = /* @__PURE__ */ new Set();
547
+ ready = [];
548
+ lib;
549
+ abortController = new AbortController();
550
+ /**
551
+ * Slot for the RestateOperations bound to this scheduler. Set by
552
+ * `execute()` after construction (we can't pass it into the ctor
553
+ * because RestateOperations needs the scheduler to construct itself).
554
+ * `Fiber.advance` publishes this to the module-level current-fiber
555
+ * slot read by free-standing API functions. Typed `unknown` here to
556
+ * keep this module independent of `restate-operations.ts`.
557
+ */
558
+ contextSlot = null;
559
+ constructor(lib) {
560
+ this.lib = lib;
561
+ }
562
+ /**
563
+ * The scheduler's current AbortSignal. Aborts when invocation
564
+ * cancellation is observed (the SDK rejects the main race promise
565
+ * with TerminalError). After cancellation has been delivered to
566
+ * fibers and the scheduler has resumed, this getter returns a
567
+ * *fresh* signal — one that is not aborted, even though the previous
568
+ * cancel was just delivered.
569
+ *
570
+ * Pass `signal` to AbortSignal-aware APIs in `ops.run` closures
571
+ * (e.g. `fetch(url, {signal})`) so they cancel promptly when the
572
+ * surrounding work is cancelled. Cleanup closures yielded after a
573
+ * caught CancelledError get a fresh, unaborted signal — so they can
574
+ * do real work and only abort if a *new* cancellation arrives.
575
+ */
576
+ get abortSignal() {
577
+ return this.abortController.signal;
578
+ }
579
+ markReady(f) {
580
+ this.ready.push(f);
581
+ }
582
+ markDone(f) {
583
+ this.fibers.delete(f);
584
+ }
585
+ spawnFuture(op) {
586
+ return makeFuture({
587
+ kind: "local",
588
+ target: this.createFiber(op)
589
+ });
590
+ }
591
+ createFiber(op) {
592
+ const f = new Fiber(op, this);
593
+ this.fibers.add(f);
594
+ this.ready.push(f);
595
+ return f;
596
+ }
597
+ makeJournalFuture(promise) {
598
+ return makeFuture({
599
+ kind: "journal",
600
+ promise
601
+ });
602
+ }
603
+ /**
604
+ * Spawn an operation as a fresh fiber and return a Future that
605
+ * resolves with its eventual value. Same as the SchedulerOps method;
606
+ * exposed publicly for external callers (combinator helpers, the
607
+ * main run() entry point).
608
+ */
609
+ spawnDetached(op) {
610
+ return this.spawnFuture(op);
611
+ }
612
+ /**
613
+ * Construct a single-shot in-memory channel. Send must be called from
614
+ * a fiber currently advancing under this scheduler. See `channel.ts`
615
+ * for full semantics.
616
+ */
617
+ makeChannel() {
618
+ return makeChannel();
619
+ }
620
+ /**
621
+ * Combinator over Futures. Fast path when every input is journal-
622
+ * backed: use the lib's all/race for a single combinator entry.
623
+ * Otherwise, fall back to a synthesized fiber that yields each in
624
+ * turn.
625
+ *
626
+ * Tuple-aware typing (mirrors `Promise.all` in the standard lib):
627
+ * `all([fA, fB])` where `fA: Future<A>` and `fB: Future<B>`
628
+ * yields `Future<[A, B]>`, not `Future<(A | B)[]>`. The `const T`
629
+ * lets TS infer a tuple from a literal array.
630
+ */
631
+ all(futures) {
632
+ const fs = futures;
633
+ if (fs.every(isJournalBacked)) {
634
+ const promises = fs.map((f) => f[futureBacking].promise);
635
+ return this.makeJournalFuture(this.lib.all(promises));
636
+ }
637
+ return this.spawnDetached(gen(function* () {
638
+ const out = new Array(fs.length);
639
+ for (let i = 0; i < fs.length; i++) out[i] = yield* fs[i];
640
+ return out;
641
+ }));
642
+ }
643
+ race(futures) {
644
+ const fs = futures;
645
+ return this.spawnDetached(gen(function* () {
646
+ const result = yield* awaitRace(fs);
647
+ if (result.settled.ok) return result.settled.v;
648
+ throw result.settled.e;
649
+ }));
650
+ }
651
+ /**
652
+ * First-success combinator. Mirrors `Promise.any` /
653
+ * `RestatePromise.any`: settles with the first input that succeeds
654
+ * (non-rejected); rejects with `AggregateError(errors)` when every
655
+ * input rejects (including the empty-array case).
656
+ *
657
+ * Fast path collapses to a single `lib.any` over journal awaitables.
658
+ * Fallback synthesizes a fiber that loops `awaitAnyOf` over the
659
+ * still-pending subset, accumulating rejections in input order until
660
+ * one input fulfills or all have rejected.
661
+ *
662
+ * Tuple-aware: `any([fA, fB])` where `fA: Future<A>` and `fB:
663
+ * Future<B>` yields `Future<A | B>` (the union of slot types), same
664
+ * shape as `Promise.any`.
665
+ */
666
+ any(futures) {
667
+ const fs = futures;
668
+ if (fs.every(isJournalBacked)) {
669
+ const promises = fs.map((f) => f[futureBacking].promise);
670
+ return this.makeJournalFuture(this.lib.any(promises));
671
+ }
672
+ return this.spawnDetached(gen(function* () {
673
+ const errors = new Array(fs.length);
674
+ const remaining = /* @__PURE__ */ new Set();
675
+ for (let i = 0; i < fs.length; i++) remaining.add(i);
676
+ while (remaining.size > 0) {
677
+ const liveIdx = Array.from(remaining);
678
+ const result = yield* awaitRace(liveIdx.map((i) => fs[i]));
679
+ const original = liveIdx[result.index];
680
+ if (result.settled.ok) return result.settled.v;
681
+ errors[original] = result.settled.e;
682
+ remaining.delete(original);
683
+ }
684
+ throw new AggregateError(errors, "All promises were rejected");
685
+ }));
686
+ }
687
+ /**
688
+ * Settle-all combinator. Mirrors `Promise.allSettled` /
689
+ * `RestatePromise.allSettled`: resolves with an array of
690
+ * `FutureSettledResult` in input order, never rejects.
691
+ *
692
+ * Fast path collapses to a single `lib.allSettled`. Fallback yields
693
+ * each Future in turn — safe because Futures are eager (already in
694
+ * flight); sequential harvesting just reads them as they complete
695
+ * without blocking concurrency.
696
+ *
697
+ * Tuple-aware: `allSettled([fA, fB])` yields
698
+ * `Future<[FutureSettledResult<A>, FutureSettledResult<B>]>`.
699
+ */
700
+ allSettled(futures) {
701
+ const fs = futures;
702
+ if (fs.every(isJournalBacked)) {
703
+ const promises = fs.map((f) => f[futureBacking].promise);
704
+ return this.makeJournalFuture(this.lib.allSettled(promises));
705
+ }
706
+ return this.spawnDetached(gen(function* () {
707
+ const out = new Array(fs.length);
708
+ for (let i = 0; i < fs.length; i++) try {
709
+ out[i] = {
710
+ status: "fulfilled",
711
+ value: yield* fs[i]
712
+ };
713
+ } catch (reason) {
714
+ out[i] = {
715
+ status: "rejected",
716
+ reason
717
+ };
718
+ }
719
+ return out;
720
+ }));
721
+ }
722
+ drainReady() {
723
+ while (this.ready.length > 0) this.ready.shift().advance();
724
+ }
725
+ /**
726
+ * Run an operation to completion. Drain the ready queue, then loop:
727
+ * collect every PromiseSource from every parked fiber, race them,
728
+ * dispatch the winner via its fire callback, drain. Stop when no
729
+ * fiber is alive.
730
+ */
731
+ async run(op) {
732
+ const main = this.createFiber(op);
733
+ this.drainReady();
734
+ while (this.fibers.size > 0) {
735
+ const items = [];
736
+ for (const f of this.fibers) for (const src of f.parkedSources()) items.push(src);
737
+ if (items.length === 0) throw new Error("scheduler stuck: live fibers but nothing pending on a journal promise");
738
+ const tagged = items.map(({ promise }, i$1) => promise.map((v, e) => e !== void 0 ? {
739
+ i: i$1,
740
+ ok: false,
741
+ e
742
+ } : {
743
+ i: i$1,
744
+ ok: true,
745
+ v
746
+ }));
747
+ let raceWinner;
748
+ try {
749
+ raceWinner = await this.lib.race(tagged);
750
+ } catch (e) {
751
+ if (this.lib.isCancellation(e)) {
752
+ this.abortController.abort(e);
753
+ this.abortController = new AbortController();
754
+ }
755
+ const errSettled = {
756
+ ok: false,
757
+ e
758
+ };
759
+ for (const it of items) it.fire(errSettled);
760
+ this.drainReady();
761
+ continue;
762
+ }
763
+ const { i,...settledFields } = raceWinner;
764
+ const settled = settledFields.ok ? {
765
+ ok: true,
766
+ v: settledFields.v
767
+ } : {
768
+ ok: false,
769
+ e: settledFields.e
770
+ };
771
+ items[i].fire(settled);
772
+ this.drainReady();
773
+ }
774
+ if (!main.isDone()) throw new Error("scheduler exited but main fiber never completed");
775
+ const final = main.settledValue();
776
+ if (final.ok) return final.v;
777
+ throw final.e;
778
+ }
779
+ };
780
+
781
+ //#endregion
782
+ //#region src/restate-operations.ts
783
+ function adapt(p) {
784
+ return p;
785
+ }
786
+ /**
787
+ * Wrap a user-supplied `run` closure to surface the abort reason
788
+ * (typically a TerminalError(CANCELLED)) on throw paths if the signal
789
+ * aborted during execution. This converts AbortError (and any other
790
+ * abort-caused failure) into the canonical cancellation TerminalError
791
+ * for journal recording.
792
+ *
793
+ * Defensive coercion: if `signal.reason` is itself not a TerminalError
794
+ * (which shouldn't happen in production but might during testing or
795
+ * with non-cancellation race rejections), we wrap it in one. The
796
+ * journal must record a *terminal* outcome to avoid retries against
797
+ * a cancelled invocation.
798
+ *
799
+ * Exposed for testing — the wrapper's behavior is the part that has
800
+ * semantic bite, separate from the ctx.run plumbing.
801
+ */
802
+ function wrapActionForCancellation(signal$1, action) {
803
+ return async () => {
804
+ try {
805
+ return await action({ signal: signal$1 });
806
+ } catch (e) {
807
+ if (signal$1.aborted) throw asTerminalError(signal$1.reason);
808
+ throw e;
809
+ }
810
+ };
811
+ }
812
+ /**
813
+ * Resolve the journal-entry name; throw `TerminalError` if neither
814
+ * source provides one.
815
+ *
816
+ * `TerminalError` (not a plain `Error`) because a missing name is a
817
+ * programming bug — retrying the invocation will hit the same code
818
+ * path and fail the same way. The SDK treats terminal errors as
819
+ * non-retryable; the invocation fails fast instead of looping.
820
+ */
821
+ function resolveRunName(action, opts) {
822
+ const fromOpts = opts?.name?.trim();
823
+ if (fromOpts) return fromOpts;
824
+ const fromFn = action.name;
825
+ if (fromFn) return fromFn;
826
+ throw new __restatedev_restate_sdk.TerminalError("@restatedev/restate-sdk-gen: run() requires a journal-entry name. Either pass a named function (`run(myFn)`) or supply `{ name: '...' }` in the second argument.");
827
+ }
828
+ /** Translate our `RetryOptions` into the SDK's flat `RunOptions` shape. */
829
+ function toSdkRunOptions(opts) {
830
+ const out = {};
831
+ if (opts?.serde !== void 0) out.serde = opts.serde;
832
+ const r = opts?.retry;
833
+ if (r) {
834
+ if (r.maxAttempts !== void 0) out.maxRetryAttempts = r.maxAttempts;
835
+ if (r.maxDuration !== void 0) out.maxRetryDuration = r.maxDuration;
836
+ if (r.initialInterval !== void 0) out.initialRetryInterval = r.initialInterval;
837
+ if (r.maxInterval !== void 0) out.maxRetryInterval = r.maxInterval;
838
+ if (r.intervalFactor !== void 0) out.retryIntervalFactor = r.intervalFactor;
839
+ }
840
+ return out;
841
+ }
842
+ function asTerminalError(reason) {
843
+ if (reason instanceof __restatedev_restate_sdk.TerminalError) return reason;
844
+ return new __restatedev_restate_sdk.CancelledError();
845
+ }
846
+ var RestateOperations = class {
847
+ ctx;
848
+ sched;
849
+ constructor(context, sched) {
850
+ this.ctx = context;
851
+ this.sched = sched;
852
+ }
853
+ toFuture(p) {
854
+ return this.sched.makeJournalFuture(adapt(p));
855
+ }
856
+ /**
857
+ * Run a side-effecting closure as a journal entry.
858
+ *
859
+ * The closure receives `{ signal }` — an AbortSignal that fires when
860
+ * invocation cancellation arrives. Pass it into AbortSignal-aware
861
+ * APIs (e.g. `fetch(url, { signal })`) to abort in-flight syscalls.
862
+ *
863
+ * `name` is the journal entry's stable identifier (must be
864
+ * deterministic across replay). It can come from either:
865
+ *
866
+ * - `opts.name` — explicit override
867
+ * - `action.name` — the function's own name (works for `function`
868
+ * declarations and arrow functions assigned to a `const`,
869
+ * since JS infers names from the binding site)
870
+ *
871
+ * If neither resolves, `run` throws.
872
+ *
873
+ * @example Named function — name derived
874
+ * async function fetchUser({ signal }: RunActionOpts): Promise<User> {
875
+ * const r = await fetch(`/users/${id}`, { signal });
876
+ * return r.json();
877
+ * }
878
+ * yield* run(fetchUser);
879
+ *
880
+ * @example Named arrow — name derived from binding
881
+ * const fetchUser = async ({ signal }: RunActionOpts) => { ... };
882
+ * yield* run(fetchUser);
883
+ *
884
+ * @example Inline arrow — name explicit
885
+ * yield* run(async ({ signal }) => fetch(url, { signal }), { name: "fetch" });
886
+ *
887
+ * @example With retry policy
888
+ * yield* run(fetchUser, { retry: { maxAttempts: 3 } });
889
+ *
890
+ * Cancellation hygiene: if the closure throws while the signal is
891
+ * aborted, we rethrow `signal.reason` (the original TerminalError)
892
+ * instead of whatever the closure threw. This ensures the journal
893
+ * entry records `TerminalError(CANCELLED)` rather than `AbortError`.
894
+ */
895
+ run(action, opts) {
896
+ const name = resolveRunName(action, opts);
897
+ const wrapped = wrapActionForCancellation(this.sched.abortSignal, action);
898
+ return this.sched.makeJournalFuture(adapt(this.ctx.run(name, wrapped, toSdkRunOptions(opts))));
899
+ }
900
+ sleep(duration, name) {
901
+ return this.sched.makeJournalFuture(adapt(this.ctx.sleep(duration, name)));
902
+ }
903
+ awakeable(serde) {
904
+ const { id, promise } = this.ctx.awakeable(serde);
905
+ return {
906
+ id,
907
+ promise: this.sched.makeJournalFuture(adapt(promise))
908
+ };
909
+ }
910
+ resolveAwakeable(id, payload, serde) {
911
+ this.ctx.resolveAwakeable(id, payload, serde);
912
+ }
913
+ rejectAwakeable(id, reason) {
914
+ this.ctx.rejectAwakeable(id, reason);
915
+ }
916
+ signal(name, serde) {
917
+ return this.sched.makeJournalFuture(adapt(this.ctx.signal(name, serde)));
918
+ }
919
+ attach(invocationId, serde) {
920
+ return this.sched.makeJournalFuture(adapt(this.ctx.attach(invocationId, serde)));
921
+ }
922
+ /**
923
+ * Typed RPC client for a service: `ops.serviceClient(api).foo(arg)`
924
+ * yields a `Future<T>` whose value is the handler's return value.
925
+ *
926
+ * Same shape as `ctx.serviceClient(api)` from the SDK, but each
927
+ * handler-method returns `Future<T>` rather than `InvocationPromise<T>`.
928
+ */
929
+ serviceClient(api) {
930
+ return wrapClient(this.ctx.serviceClient(api), (p) => this.toFuture(p));
931
+ }
932
+ /** Typed RPC client for a virtual object. See {@link serviceClient}. */
933
+ objectClient(api, key) {
934
+ return wrapClient(this.ctx.objectClient(api, key), (p) => this.toFuture(p));
935
+ }
936
+ /** Typed RPC client for a workflow. See {@link serviceClient}. */
937
+ workflowClient(api, key) {
938
+ return wrapClient(this.ctx.workflowClient(api, key), (p) => this.toFuture(p));
939
+ }
940
+ serviceSendClient(api) {
941
+ return this.ctx.serviceSendClient(api);
942
+ }
943
+ objectSendClient(api, key) {
944
+ return this.ctx.objectSendClient(api, key);
945
+ }
946
+ workflowSendClient(api, key) {
947
+ return this.ctx.workflowSendClient(api, key);
948
+ }
949
+ genericCall(call) {
950
+ return this.toFuture(this.ctx.genericCall(call));
951
+ }
952
+ genericSend(call) {
953
+ return this.ctx.genericSend(call);
954
+ }
955
+ /**
956
+ * Cancel another invocation by its id. To observe cancellation
957
+ * arriving at *this* invocation, catch the `TerminalError` thrown by
958
+ * the next `yield*` boundary or use the `signal` exposed inside
959
+ * `ops.run` closures.
960
+ */
961
+ cancel(invocationId) {
962
+ this.ctx.cancel(invocationId);
963
+ }
964
+ /**
965
+ * Workflow-bound durable promise. Use only inside a workflow handler
966
+ * (the underlying context must be `WorkflowContext` or
967
+ * `WorkflowSharedContext`). Returns a wrapper whose `peek`/`get`/
968
+ * `resolve`/`reject` methods return Futures.
969
+ */
970
+ workflowPromise(name, serde) {
971
+ const wfCtx = this.ctx;
972
+ return wrapDurablePromise(wfCtx.promise(name, serde), (p) => this.toFuture(p));
973
+ }
974
+ spawn(op) {
975
+ return spawn(op);
976
+ }
977
+ /**
978
+ * Create a single-shot in-memory channel. Returns a Channel<T> with
979
+ * `send(v)` (fire-and-forget, idempotent — first call settles, rest
980
+ * are dropped) and `receive: Future<T>` (a stable settle-once Future,
981
+ * the same handle on every access).
982
+ *
983
+ * Canonical use: cooperative cancellation. Spawn a routine that
984
+ * selects over its work and `stop.receive`; the canceller calls
985
+ * `stop.send()` to request termination. The receiver decides what
986
+ * to do — return a partial result, do cleanup yields, ignore.
987
+ *
988
+ * Because `receive` is a stable, settle-once Future, multiple readers
989
+ * all observe the same value (one-time broadcast) and the worker can
990
+ * use it in every iteration of a select-loop without leaking orphan
991
+ * receivers.
992
+ *
993
+ * Multi-event streams (producer-consumer, progress events) are NOT
994
+ * supported — Channel is intentionally single-shot. A separate
995
+ * primitive for that use case is yet to be designed.
996
+ */
997
+ channel() {
998
+ return this.sched.makeChannel();
999
+ }
1000
+ /**
1001
+ * Per-invocation read-write key-value store. Use from a handler whose
1002
+ * underlying context is ObjectContext or WorkflowContext.
1003
+ *
1004
+ * The optional `TState` generic gives keyof-checked names and per-key
1005
+ * value types:
1006
+ *
1007
+ * ops.state<{count: number; user: User}>()
1008
+ * // state.get("count") → Future<number | null>
1009
+ *
1010
+ * Without it, names are `string` and values are inferred per call:
1011
+ *
1012
+ * ops.state()
1013
+ * // state.get<number>("count") → Future<number | null>
1014
+ *
1015
+ * Calling write methods from a shared (read-only) context throws at
1016
+ * runtime — for shared handlers, use `sharedState()` below to get a
1017
+ * narrower type that drops the write methods.
1018
+ */
1019
+ state() {
1020
+ return makeState(this.ctx, this.sched, adapt);
1021
+ }
1022
+ /**
1023
+ * Per-invocation read-only key-value store. Use from a handler whose
1024
+ * underlying context is ObjectSharedContext or WorkflowSharedContext.
1025
+ *
1026
+ * Same `TState` generic as `state()`. Returns the read-only subset
1027
+ * (`get`, `keys`); attempting to call writes is a type error.
1028
+ */
1029
+ sharedState() {
1030
+ return makeState(this.ctx, this.sched, adapt);
1031
+ }
1032
+ /**
1033
+ * Wait for every future to settle; return their values in input
1034
+ * order. Heterogeneous-tuple typing — `all([fA, fB])` where
1035
+ * `fA: Future<A>` and `fB: Future<B>` yields `Future<[A, B]>`.
1036
+ * Mirrors `Promise.all` from the standard lib.
1037
+ */
1038
+ all(futures) {
1039
+ return this.sched.all(futures);
1040
+ }
1041
+ /**
1042
+ * Return the first future to settle; losers continue running but
1043
+ * their results are discarded. Heterogeneous-tuple typing —
1044
+ * `race([fA, fB])` yields `Future<A | B>`. Mirrors `Promise.race`.
1045
+ */
1046
+ race(futures) {
1047
+ return this.sched.race(futures);
1048
+ }
1049
+ /**
1050
+ * First-success combinator. Resolves with the first input that
1051
+ * succeeds (non-rejected); rejects with `AggregateError(errors)` when
1052
+ * every input rejects (including an empty input array). See `Promise.any`.
1053
+ *
1054
+ * Tuple-aware typing — `any([fA, fB])` where `fA: Future<A>` and
1055
+ * `fB: Future<B>` yields `Future<A | B>`.
1056
+ */
1057
+ any(futures) {
1058
+ return this.sched.any(futures);
1059
+ }
1060
+ /**
1061
+ * Settle-all combinator. Resolves with an array of
1062
+ * `FutureSettledResult` in input order; never rejects. See
1063
+ * `Promise.allSettled`.
1064
+ *
1065
+ * Tuple-aware typing — `allSettled([fA, fB])` yields
1066
+ * `Future<[FutureSettledResult<A>, FutureSettledResult<B>]>`.
1067
+ */
1068
+ allSettled(futures) {
1069
+ return this.sched.allSettled(futures);
1070
+ }
1071
+ *select(branches) {
1072
+ return yield* select(branches);
1073
+ }
1074
+ };
1075
+ /**
1076
+ * Run a generator-based workflow against a Restate context.
1077
+ *
1078
+ * `op` is an `Operation<T>` — typically the result of
1079
+ * `gen(function*() { ... })`. Inside the generator body, reach for the
1080
+ * free-standing API (`run`, `sleep`, `all`, `state`, …) imported
1081
+ * from `@restatedev/restate-sdk-gen`. They read the active scheduler from a
1082
+ * synchronous current-fiber slot installed by `Fiber.advance`.
1083
+ *
1084
+ * `gen()` already takes a factory, so the same `Operation` is re-
1085
+ * iterable across multiple `execute()` calls — no need for a builder
1086
+ * lambda at this boundary.
1087
+ *
1088
+ * @example
1089
+ * execute(ctx, gen(function* () {
1090
+ * const greeting = yield* run(async () => "hi", { name: "compose" });
1091
+ * return greeting;
1092
+ * }));
1093
+ */
1094
+ async function execute(context, op) {
1095
+ const sched = new Scheduler(defaultLib);
1096
+ sched.contextSlot = new RestateOperations(context, sched);
1097
+ return sched.run(op);
1098
+ }
1099
+
1100
+ //#endregion
1101
+ exports.all = all;
1102
+ exports.allSettled = allSettled;
1103
+ exports.any = any;
1104
+ exports.attach = attach;
1105
+ exports.awakeable = awakeable;
1106
+ exports.cancel = cancel;
1107
+ exports.channel = channel;
1108
+ exports.execute = execute;
1109
+ exports.gen = gen;
1110
+ exports.genericCall = genericCall;
1111
+ exports.genericSend = genericSend;
1112
+ exports.objectClient = objectClient;
1113
+ exports.objectSendClient = objectSendClient;
1114
+ exports.race = race;
1115
+ exports.rejectAwakeable = rejectAwakeable;
1116
+ exports.resolveAwakeable = resolveAwakeable;
1117
+ exports.run = run;
1118
+ exports.select = select;
1119
+ exports.serviceClient = serviceClient;
1120
+ exports.serviceSendClient = serviceSendClient;
1121
+ exports.sharedState = sharedState;
1122
+ exports.signal = signal;
1123
+ exports.sleep = sleep;
1124
+ exports.spawn = spawn;
1125
+ exports.state = state;
1126
+ exports.workflowClient = workflowClient;
1127
+ exports.workflowPromise = workflowPromise;
1128
+ exports.workflowSendClient = workflowSendClient;
1129
+ exports.wrapActionForCancellation = wrapActionForCancellation;