@restatedev/restate-sdk-gen 1.17.1 → 1.17.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 +49 -14
- package/dist/index.d.cts +64 -21
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +64 -21
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -15
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["CURRENT: unknown","id: string","_outputSerde?: restate.Serde<O>","serde","serde","leafOp: PrimitiveOp<T>","resume: Settled | null","next: IteratorResult<unknown, unknown>","outcome: Settled | null","backing: Backing<unknown>","promises: PromiseSource[]","settled: Settled","out: unknown[]","errors: unknown[]","items: PromiseSource[]","raceWinner: { i: number } & Settled","errSettled: Settled","settled: Settled","adapt","serde","call","send","parameter: unknown","opts:\n | ClientCallOptions<unknown, unknown>\n | ClientSendOptions<unknown>\n | undefined","defaultLib: AwaitableLib","signal","out: restate.RunOptions<T>","serde","invocation","selectOp","SchedulerClass","serde","coreHandlers: Record<string, any>","descriptors: Record<string, HandlerDescriptor>","handlerEntries: Record<string, any>","iface","_defineService","_defineObject","_defineWorkflow","connect","clientsConnect","client","sendClient","scope","_coreIface","_implement"],"sources":["../src/current.ts","../src/invocation-reference.ts","../src/free.ts","../src/operation.ts","../src/context.ts","../src/task.ts","../src/future.ts","../src/abort.ts","../src/fiber.ts","../src/channel.ts","../src/scheduler.ts","../src/state.ts","../src/clients.ts","../src/durable-promise.ts","../src/default-lib.ts","../src/restate-operations.ts","../src/define.ts","../src/interface.ts","../src/ingress.ts","../src/internal-operations.ts","../src/index.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Synchronous current-fiber slot.\n// =============================================================================\n//\n// A module-level pointer to the active `RestateOperations`, set on\n// entry to `Fiber.advance()` and cleared in its `finally`. Free-standing\n// API functions (`sleep`, `run`, `all`, …) read it to reach the\n// scheduler/context without an explicit `ops` parameter.\n//\n// Why this is safe without AsyncLocalStorage: user generators yield —\n// they do not `await`. `iterator.next()` returns control synchronously\n// to `Fiber.advance`, so the slot is \"owned\" only during the synchronous\n// span between `setCurrent` and `clearCurrent`. Concurrent `execute()`\n// calls in the same Node process interleave only at scheduler-level\n// `await` boundaries (the main-loop race), never in the middle of a\n// fiber's sync body — Node never preempts sync JS.\n//\n// Failure mode: a free function called while no fiber is advancing\n// (module init, an `ops.run` async closure that resolves later, a\n// timer firing) reads `null` and throws. Loud and immediate; never\n// silent corruption.\n//\n// The slot value is typed `unknown` here to avoid a circular import on\n// `RestateOperations` (which itself imports the scheduler graph). Free\n// functions cast back via the typed `currentOps()` helper that lives\n// next to `RestateOperations`.\n\nlet CURRENT: unknown = null;\n\n/**\n * Save the previous slot, install `value` as the current. Returns the\n * previous value so `clearCurrent` can restore it (supports nested\n * scheduler invocations on the same thread, even though we don't expect\n * any in production).\n */\nexport function setCurrent(value: unknown): unknown {\n const prev = CURRENT;\n CURRENT = value;\n return prev;\n}\n\n/** Restore a slot previously captured by `setCurrent`. */\nexport function clearCurrent(prev: unknown): void {\n CURRENT = prev;\n}\n\n/**\n * Read the slot without throwing — returns `null` when no fiber is\n * currently advancing. For callers that need to distinguish \"inside a\n * fiber\" from \"outside\" rather than fail loudly (e.g. the internal\n * `isProcessing()` probe).\n */\nexport function peekCurrent(): unknown {\n return CURRENT;\n}\n\n/**\n * Read the slot, throwing if no fiber is currently advancing. Callers\n * cast the return type — the slot is intentionally `unknown` here so\n * this module stays free of cycles.\n */\nexport function getCurrent(): unknown {\n if (CURRENT === null) {\n throw new Error(\n \"@restatedev/restate-sdk-gen: free-standing API called outside an active fiber. \" +\n \"Call from inside `execute(ctx, gen(function*() { ... }))`.\"\n );\n }\n return CURRENT;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport type { Future } from \"./future.js\";\nimport { getCurrent } from \"./current.js\";\nimport type { RestateOperations } from \"./restate-operations.js\";\n\n/** Synchronous handle for resolving or rejecting a signal on a target invocation */\nexport interface SignalReference<T> {\n resolve(payload?: T): void;\n reject(reason: string | restate.TerminalError): void;\n}\n\n/**\n * A typed reference to a running invocation. Returned by `sendClient()` methods\n * (wrapped in `Future<InvocationReference<O>>`), or created via `invocation(id)`.\n *\n * - `attach()` returns a `Future<O>` with the serde from the original descriptor.\n * - `signal()` sends a named signal to the target invocation.\n * - `cancel()` cancels the target invocation.\n */\nexport interface InvocationReference<O = unknown> {\n readonly id: string;\n attach(serde?: restate.Serde<O>): Future<O>;\n signal<T = unknown>(\n name: string,\n serde?: restate.Serde<T>\n ): SignalReference<T>;\n cancel(): void;\n}\n\nexport class InvocationReferenceImpl<\n O = unknown,\n> implements InvocationReference<O> {\n constructor(\n readonly id: string,\n private readonly _outputSerde?: restate.Serde<O>\n ) {}\n\n attach(serde?: restate.Serde<O>): Future<O> {\n return (getCurrent() as RestateOperations).attach<O>(\n this.id as restate.InvocationId,\n serde ?? this._outputSerde\n );\n }\n\n signal<T = unknown>(\n name: string,\n serde?: restate.Serde<T>\n ): SignalReference<T> {\n return (getCurrent() as RestateOperations).invocationSignal<T>(\n this.id as restate.InvocationId,\n name,\n serde\n );\n }\n\n cancel(): void {\n (getCurrent() as RestateOperations).cancel(this.id as restate.InvocationId);\n }\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */\n\n// Free-standing API\n// =============================================================================\n//\n// Module-level functions that mirror `RestateOperations` methods but\n// read the active operations from the synchronous current-fiber slot\n// (`current.ts`). User code inside a `gen(function*() { ... })` body\n// can call these directly — no `ops` parameter needed.\n//\n// Each function is a one-liner that resolves the slot via `currentOps()`\n// and delegates to the underlying `RestateOperations` method, so this\n// file stays in lockstep with the class without duplicating logic.\n//\n// Usage:\n//\n// import { gen, execute, sleep, run, all } from \"@restatedev/restate-sdk-gen\";\n//\n// const myWorkflow = gen(function*() {\n// const a = run(() => fetchA(), { name: \"a\" });\n// const b = run(() => fetchB(), { name: \"b\" });\n// const [av, bv] = yield* all([a, b]);\n// yield* sleep(100);\n// return av + bv;\n// });\n//\n// // Handler:\n// execute(ctx, myWorkflow);\n//\n// `select` is already a free function in `operation.ts` and requires no\n// slot — it yields a marker the scheduler dispatches. It is re-exported\n// from `index.ts`.\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport type { Future, FutureValues, FutureSettledResult } from \"./future.js\";\nimport type { Channel } from \"./channel.js\";\nimport type { State, SharedState, TypedState, UntypedState } from \"./state.js\";\nimport type { GenDurablePromise } from \"./durable-promise.js\";\nimport type {\n GenContextDate,\n RestateOperations,\n RunAction,\n RunOpts,\n ScopedOperations,\n} from \"./restate-operations.js\";\nimport type { Descriptor, HandlerDescriptor } from \"./define.js\";\nimport type { ClientFuture, GenClient, GenSendClient } from \"./clients.js\";\nimport type { Operation } from \"./operation.js\";\nimport type { Task } from \"./task.js\";\nimport {\n InvocationReferenceImpl,\n type InvocationReference,\n} from \"./invocation-reference.js\";\nimport { getCurrent } from \"./current.js\";\nimport type { HandlerRequest } from \"./restate-operations.js\";\n\n/**\n * Read the active `RestateOperations` from the current-fiber slot.\n * Throws if called outside a fiber's synchronous advance span (e.g.,\n * at module init or inside an `ops.run` async closure that resolved\n * after the fiber returned).\n */\nexport function currentOps(): RestateOperations {\n return getCurrent() as RestateOperations;\n}\n\n// ---- context properties (rand / date / console) ----\n\nexport const rand = (): restate.Rand => currentOps().rand;\n\nexport const date = (): GenContextDate => currentOps().date;\n\nexport const logger = (): Console => currentOps().console;\n\n// ---- context accessor ----\n\n/**\n * Returns the current invocation's request metadata plus the optional\n * virtual-object / workflow key. The `key` field is only present when\n * the handler belongs to an object or workflow.\n */\nexport const handlerRequest = (): HandlerRequest =>\n currentOps().handlerRequest();\n\n// ---- journal-backed Futures ----\n\n/**\n * Run a side-effecting closure as a journal entry. See\n * `RestateOperations.run` for full semantics.\n *\n * `name` is derived from `action.name` (works for named functions and\n * arrow functions assigned to a `const`) or specified explicitly via\n * `opts.name`. If neither resolves, throws.\n */\nexport const run = <T>(action: RunAction<T>, opts?: RunOpts<T>): Future<T> =>\n currentOps().run(action, opts);\n\nexport const sleep = (\n duration: restate.Duration | number,\n name?: string\n): Future<void> => currentOps().sleep(duration, name);\n\nexport const awakeable = <T>(\n serde?: restate.Serde<T>\n): { id: string; promise: Future<T> } => currentOps().awakeable(serde);\n\nexport const resolveAwakeable = <T>(\n id: string,\n payload?: T,\n serde?: restate.Serde<T>\n): void => currentOps().resolveAwakeable(id, payload, serde);\n\nexport const rejectAwakeable = (\n id: string,\n reason: string | restate.TerminalError\n): void => currentOps().rejectAwakeable(id, reason);\n\nexport const signal = <T>(name: string, serde?: restate.Serde<T>): Future<T> =>\n currentOps().signal(name, serde);\n\nexport const attach = <T>(\n invocationId: restate.InvocationId,\n serde?: restate.Serde<T>\n): Future<T> => currentOps().attach(invocationId, serde);\n\n// ---- unified typed clients ----\n\nexport function client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n): GenClient<H>;\nexport function client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n): GenClient<H>;\nexport function client(\n def: Descriptor<\n string,\n Record<string, HandlerDescriptor>,\n \"service\" | \"object\" | \"workflow\"\n >,\n key?: string\n): GenClient<Record<string, HandlerDescriptor>> {\n return currentOps().client(def as Descriptor<string, any, any>, key as any);\n}\n\nexport function sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n): GenSendClient<H>;\nexport function sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n): GenSendClient<H>;\nexport function sendClient(\n def: Descriptor<\n string,\n Record<string, HandlerDescriptor>,\n \"service\" | \"object\" | \"workflow\"\n >,\n key?: string\n): GenSendClient<Record<string, HandlerDescriptor>> {\n return currentOps().sendClient(\n def as Descriptor<string, any, any>,\n key as any\n );\n}\n\n/**\n * Route all outgoing calls/sends through a named scope. Returns a bundle\n * exposing the same `client`/`sendClient` overloads, with every call/send\n * carrying `scopeKey`. See {@link RestateOperations.scope} for full semantics.\n *\n * @example\n * yield* scope(\"tenant-123\").client(Greeter).greet(name);\n * yield* scope(\"tenant-123\").client(Cart, \"cart-42\").add(item);\n * scope(\"tenant-123\").sendClient(Greeter).greet(name);\n */\nexport const scope = (scopeKey: string): ScopedOperations =>\n currentOps().scope(scopeKey);\n\n// ---- generic call/send (renamed from genericCall/genericSend) ----\n\nexport const call = <REQ = Uint8Array, RES = Uint8Array>(\n c: restate.GenericCall<REQ, RES>\n): ClientFuture<RES> => currentOps().call<REQ, RES>(c);\n\nexport const send = <REQ = Uint8Array, RES = unknown>(\n c: restate.GenericSend<REQ>,\n outputSerde?: restate.Serde<RES>\n): Future<InvocationReference<RES>> =>\n currentOps().send<REQ, RES>(c, outputSerde);\n\n// ---- invocation reference ----\n\n/**\n * Create an InvocationReference from a known invocation ID (e.g. retrieved from state).\n * `attach()` and `cancel()` on the result use the current fiber slot like all free functions.\n */\nexport function invocation<O = unknown>(\n id: string,\n opts?: { outputSerde?: restate.Serde<O> }\n): InvocationReference<O> {\n return new InvocationReferenceImpl<O>(id, opts?.outputSerde);\n}\n\n// ---- cancel another invocation ----\n\nexport const cancel = (invocationId: restate.InvocationId): void =>\n currentOps().cancel(invocationId);\n\n// ---- channels & state ----\n\nexport const channel = <T>(): Channel<T> => currentOps().channel<T>();\n\nexport const state = <\n TState extends TypedState = UntypedState,\n>(): State<TState> => currentOps().state<TState>();\n\nexport const sharedState = <\n TState extends TypedState = UntypedState,\n>(): SharedState<TState> => currentOps().sharedState<TState>();\n\n// ---- workflow durable promise ----\n\nexport const workflowPromise = <T>(\n name: string,\n serde?: restate.Serde<T>\n): GenDurablePromise<T> => currentOps().workflowPromise<T>(name, serde);\n\n// ---- combinators ----\n\n/**\n * Wait for every future to settle; return their values in input order.\n * Heterogeneous-tuple typing — `all([fA, fB])` where `fA: Future<A>`\n * and `fB: Future<B>` yields `Future<[A, B]>`. Mirrors `Promise.all`.\n */\nexport const all = <const T extends readonly Future<unknown>[] | []>(\n futures: T\n): Future<FutureValues<T>> => currentOps().all(futures);\n\n/**\n * Return the first future to settle; losers continue running (until\n * the main operation settles — see `OnMainExit`) but their results are\n * discarded. Heterogeneous-tuple typing — `race([fA, fB])` yields\n * `Future<A | B>`. Mirrors `Promise.race`.\n */\nexport const race = <const T extends readonly Future<unknown>[] | []>(\n futures: T\n): Future<FutureValues<T>[number]> => currentOps().race(futures);\n\n/**\n * First-to-succeed wins (non-rejected). Rejects with `AggregateError(errors)`\n * when every input rejects (including the empty input case). Tuple-aware —\n * `any([fA, fB])` yields `Future<A | B>`. Mirrors `Promise.any`.\n */\nexport const any = <const T extends readonly Future<unknown>[] | []>(\n futures: T\n): Future<FutureValues<T>[number]> => currentOps().any(futures);\n\n/**\n * Wait for every future to settle; never rejects. Tuple-aware —\n * `allSettled([fA, fB])` yields\n * `Future<[FutureSettledResult<A>, FutureSettledResult<B>]>`.\n * Mirrors `Promise.allSettled`.\n */\nexport const allSettled = <const T extends readonly Future<unknown>[] | []>(\n futures: T\n): Future<{\n -readonly [P in keyof T]: FutureSettledResult<\n T[P] extends Future<infer U> ? U : never\n >;\n}> => currentOps().allSettled(futures);\n\n/**\n * Register `op` as a fresh routine and return a `Task<T>` for its\n * eventual outcome — a `Future<T>` plus `interrupt(err?)` to throw into\n * the routine at its next yield point. Eager — the child is already in\n * flight by the time `spawn` returns. A spawned routine still running\n * when the main operation settles is abandoned by default (see\n * `OnMainExit`). See `RestateOperations.spawn` for full semantics.\n */\nexport const spawn = <T>(op: Operation<T>): Task<T> => currentOps().spawn(op);\n\n// `select` is already a free function in `operation.ts` (it yields a\n// marker the scheduler dispatches). It is re-exported from `index.ts`\n// directly.\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Operation<T>\n// =============================================================================\n//\n// Operation<T> is a lazy, one-shot description of work that produces a T.\n// Constructed via gen() for user-authored bodies, or by primitives that\n// yield a marker the scheduler dispatches on (Leaf, AwaitRace).\n//\n// The reuse trap from naked-generator designs is closed at the type level:\n// gen() takes a factory `() => Generator<...>`, not a generator object, so\n// `gen(bare())` doesn't typecheck — you have to write `gen(() => bare())`,\n// which produces a fresh body per `[Symbol.iterator]()` call.\n\nimport type { Future } from \"./future.js\";\nimport type { Settled } from \"./scheduler-types.js\";\n\nexport const opTag = Symbol(\"restateOperation\");\n\nexport interface Operation<T> {\n [Symbol.iterator](): Iterator<unknown, T, unknown>;\n}\n\n// =============================================================================\n// Primitive nodes — only the scheduler interprets these.\n// =============================================================================\n\nexport type LeafNode<T> = {\n readonly _tag: \"Leaf\";\n readonly future: Future<T>;\n};\n\nexport type AwaitRaceResult = { index: number; settled: Settled };\n\nexport type AwaitRace = {\n readonly _tag: \"AwaitRace\";\n readonly futures: ReadonlyArray<Future<unknown>>;\n};\n\nexport interface PrimitiveOp<T> extends Operation<T> {\n readonly [opTag]: LeafNode<T> | AwaitRace;\n}\n\nexport function makePrimitive<T>(node: LeafNode<T>): PrimitiveOp<T> {\n const op = {\n [opTag]: node,\n *[Symbol.iterator]() {\n return (yield op) as T;\n },\n };\n return op;\n}\n\n// AwaitAny is module-internal — used by combinator implementations inside\n// this package (race, select). It never appears in the user API.\nexport function awaitRace<T>(\n futures: ReadonlyArray<Future<T>>\n): Operation<AwaitRaceResult> {\n const op = {\n [opTag]: { _tag: \"AwaitRace\", futures } as AwaitRace,\n *[Symbol.iterator]() {\n return (yield op) as AwaitRaceResult;\n },\n };\n return op as unknown as Operation<AwaitRaceResult>;\n}\n\n// =============================================================================\n// gen — the only way to lift a generator function into an Operation.\n// =============================================================================\n\nexport function gen<T>(\n body: () => Generator<unknown, T, unknown>\n): Operation<T> {\n return { [Symbol.iterator]: body };\n}\n\n// =============================================================================\n// select — wait for one branch to settle, return its tag and the future.\n// =============================================================================\n//\n// The user unwraps the future after switching on the tag — `yield* r.future`\n// is effectively sync at that point since it's already settled. select\n// doesn't propagate the value or the error: telling you which branch is\n// ready is its only job.\n\nexport type SelectResult<B extends Record<string, Future<unknown>>> = {\n [K in keyof B]: { tag: K; future: B[K] };\n}[keyof B];\n\nexport function* select<B extends Record<string, Future<unknown>>>(\n branches: B\n): Generator<unknown, SelectResult<B>, unknown> {\n const tags = Object.keys(branches) as Array<keyof B & string>;\n const futures = tags.map((t) => branches[t]) as Future<unknown>[];\n const result = yield* awaitRace(futures);\n const tag = tags[result.index]!;\n return { tag, future: branches[tag] } as SelectResult<B>;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Context-local storage\n// =============================================================================\n//\n// Ambient, invocation-scoped key/value storage — a typed bag carried by\n// the current invocation that generator code running under it (the main\n// body, nested `gen` helpers, and spawned routines) can read and write\n// without threading a parameter through every call.\n//\n// `get`/`set` must run on the fiber's synchronous advance span, i.e.\n// directly from generator code — NOT from inside an `ops.run` action\n// closure or any other async callback, which run off-advance (after the\n// fiber has parked) and throw \"outside an active fiber\". To capture a\n// journaled value into a slot, set it in the body from the run's result:\n// `slot.set(yield* run(() => fetchTenant(), { name: \"tenant\" }))`, not\n// `run(() => { slot.set(...) })`.\n//\n// const tenant = contextLocal<string>(); // define once, anywhere\n//\n// const handler = gen(function* () {\n// tenant.set(yield* run(() => resolveTenant(), { name: \"tenant\" }));\n// yield* doDeeplyNestedWork(); // reads tenant.get() without a param\n// });\n//\n// Scope and lifetime: ONE bag per `execute()` call. Every fiber that\n// runs under that invocation — the main routine, everything it\n// `spawn`s, and the synthetic fibers behind combinator fallbacks —\n// shares the same bag (this is global-per-invocation, not per-fiber:\n// there is no inheritance or per-strand isolation). The bag lives only\n// in memory for the duration of the invocation; it is never journaled\n// or persisted.\n//\n// Determinism: a value re-derived by deterministic workflow code is\n// itself deterministic, so it survives replay/suspension unchanged —\n// the workflow re-runs from the top and re-`set`s the same values, in\n// the same order (fibers advance one at a time, in a replay-stable\n// order). The same rule as a plain local variable applies: do not store\n// a value you obtained non-deterministically (a bare `Date.now()`, a\n// raw network result) unless it came through `run`/the journal first.\n//\n// NOT durable state: `contextLocal` is in-memory scratch for the current\n// invocation. For values that must outlive the invocation (and be\n// readable by later invocations of the same virtual object), use\n// `state()` / `sharedState()`, which the SDK persists.\n//\n// Footgun: because the bag is shared, two concurrently-interleaving\n// fibers that write the *same* key clobber each other — a reader sees\n// whichever fiber advanced last. That is fine for the dominant use\n// (set once near the top, read everywhere); only reach past it if you\n// need per-strand isolation, which this global flavor does not provide.\n\nimport { getCurrent } from \"./current.js\";\n\n/**\n * The slice of the current-fiber slot that backs context-local storage.\n * Both `Scheduler` (the slot in unit tests) and `RestateOperations` (the\n * slot in production) satisfy it structurally — `RestateOperations`\n * delegates to its scheduler, which owns the single per-invocation Map.\n * Kept here, cast from the `unknown` slot, so this module stays free of a\n * scheduler/operations import cycle (mirrors how `free.ts` reaches `ops`).\n */\ninterface ContextStore {\n /** Read `key`'s value, or `fallback` if it has never been set. */\n getLocal(key: symbol, fallback: unknown): unknown;\n /** Write `key`'s value for the rest of the invocation. */\n setLocal(key: symbol, value: unknown): void;\n}\n\n/**\n * A handle to one invocation-scoped slot. Mint it once with\n * {@link contextLocal} (at module scope is fine — minting touches no\n * fiber), then `get`/`set` it from inside the workflow body.\n */\nexport interface ContextLocal<T> {\n /**\n * Read this slot's value for the current invocation. Returns the\n * value previously {@link set} during this invocation, or the default\n * passed to {@link contextLocal} (or `undefined` if none) when it has\n * not been set. Must be called from generator code on the fiber's\n * synchronous span (a `gen` body running under `execute`); calling it\n * from an `ops.run` closure or other async callback throws.\n */\n // Arrow-property fields (not method shorthand) on purpose: method\n // parameters are checked bivariantly, which would let `ContextLocal<Dog>`\n // be treated as `ContextLocal<Animal>` and a widened `set` poison a `get`\n // that still claims `Dog`. As function-typed properties, `set`'s\n // parameter is contravariant, making the handle correctly invariant in T.\n get: () => T;\n /**\n * Set this slot's value for the rest of the current invocation,\n * visible to every fiber under it. Must be called from generator code\n * on the fiber's synchronous span; calling it from an `ops.run`\n * closure or other async callback throws.\n */\n set: (value: T) => void;\n}\n\n/**\n * Create a context-local storage slot.\n *\n * The returned handle's `get`/`set` read and write a bag scoped to the\n * current invocation (`execute` call) and shared by every fiber under\n * it. Each `contextLocal()` call mints an independent slot — two handles\n * never collide, even with the same value type.\n *\n * Minting is pure (it allocates a unique key and captures the default),\n * so a slot can be defined at module scope and reused across\n * invocations; only `get`/`set` touch the current fiber.\n *\n * @example A required value with a default\n * const region = contextLocal(\"us-east-1\"); // ContextLocal<string>\n * // inside a handler:\n * region.set(\"eu-west-1\");\n * const r = region.get(); // string\n *\n * @example An optional value (no default)\n * const traceId = contextLocal<string>(); // ContextLocal<string | undefined>\n * const t = traceId.get(); // string | undefined\n */\nexport function contextLocal<T>(defaultValue: T): ContextLocal<T>;\nexport function contextLocal<T>(): ContextLocal<T | undefined>;\nexport function contextLocal<T>(defaultValue?: T): ContextLocal<T | undefined> {\n // Identity-only key: the bag is keyed by this symbol, never serialized,\n // and lives only in-memory per invocation — so symbol identity (stable\n // within a process, irrelevant across processes) is the right key.\n const key = Symbol(\"restate.contextLocal\");\n return {\n get: () =>\n (getCurrent() as ContextStore).getLocal(key, defaultValue) as\n | T\n | undefined,\n set: (value: T | undefined) =>\n (getCurrent() as ContextStore).setLocal(key, value),\n };\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Task<T>\n// =============================================================================\n//\n// The handle returned by `spawn`. A `Task<T>` is a `Future<T>` (yieldable,\n// composable into all/race/any/allSettled exactly like any other Future)\n// plus a control method: `interrupt(err?)`, which throws `err` into the\n// spawned routine at its next yield point and aborts its in-flight `run`\n// I/O.\n//\n// Only `spawn` produces a Task — combinator results (race/all/…) stay plain\n// Future<T>, since their journal fast path has no fiber to target and their\n// fallback runs SDK-authored loop code with no user-owned try/catch.\n\nimport type { Future } from \"./future.js\";\n\n/**\n * A handle to a spawned routine: its `Future<T>` plus `interrupt`.\n */\nexport interface Task<T> extends Future<T> {\n /**\n * Throw `err` into the spawned routine at its next yield point, and\n * abort its in-flight `run` I/O. `err` is delivered verbatim — the\n * routine's own try/catch may catch and recover (interrupt is\n * swallowable). When `err` is omitted, an {@link InterruptedError} is\n * thrown instead.\n *\n * Interrupt only affects a still-running routine: interrupting one\n * that has already settled is a no-op. Under the default\n * `onMainExit: \"abandon\"`, interrupting a child and then returning\n * from the main operation delivers nothing — the scheduler stops\n * before the child is driven. To run the child's `catch`/`finally`,\n * interrupt then `yield*` the task (interrupt-then-join).\n *\n * Call from within the workflow (an advancing fiber), so the delivery\n * point is deterministic across replay.\n */\n interrupt(err?: unknown): void;\n}\n\n/**\n * The default error thrown by `interrupt()` when no explicit error is\n * given. A plain `Error` (not a `TerminalError`) — interrupt imposes no\n * blast radius of its own; if you want an uncaught interrupt to fail the\n * invocation terminally, pass a `TerminalError` to `interrupt(err)`.\n */\nexport class InterruptedError extends Error {\n constructor(message = \"Task interrupted\") {\n super(message);\n this.name = \"InterruptedError\";\n }\n}\n\n/**\n * Augment a spawned routine's Future with `interrupt`, producing a Task.\n * Takes a plain `(err) => void` callback (the fiber's `interrupt`) rather\n * than the Fiber itself, so this module stays free of scheduler/fiber\n * imports. `Object.assign` mutates and returns the same Future object —\n * its `[Symbol.iterator]` and symbol-keyed backing are untouched, so the\n * Task remains fully yieldable and composable.\n */\nexport function makeTask<T>(\n future: Future<T>,\n interruptFiber: (err: unknown) => void\n): Task<T> {\n const interrupt = (err?: unknown): void =>\n interruptFiber(err === undefined ? new InterruptedError() : err);\n return Object.assign(future as object, { interrupt }) as Task<T>;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Future<T>\n// =============================================================================\n//\n// One user-visible type. Two internal backings, distinguished only inside\n// combinator implementations and the scheduler. The user sees uniform\n// behavior — all Futures yield and compose the same way regardless of\n// backing.\n//\n// Two kinds of backing:\n//\n// - \"journal\" — wraps a remote promise (RestatePromise in production,\n// TestPromise in tests). Resolution is observed by Restate's runtime\n// and journaled. Goes through the scheduler's main-loop `lib.race`.\n//\n// - \"local\" — wraps an in-memory `WaitTarget`. Resolution lives only\n// in the JS heap; never touches the journal, never goes through\n// `lib.race`. Fibers (settled by their iterator finishing) and\n// Channels (settled by `send()`) both implement `WaitTarget`.\n// Future in-memory primitives — semaphores, latches — slot in here\n// too without further changes to the scheduler/fiber.\n\nimport type { Awaitable } from \"./awaitable.js\";\nimport {\n type Operation,\n type PrimitiveOp,\n type LeafNode,\n makePrimitive,\n} from \"./operation.js\";\nimport type { Settled, Waiter } from \"./scheduler-types.js\";\n\n// `futureBacking` is the symbol slot where each Future stashes its backing\n// (journal-backed promise or local WaitTarget). NOT exported from index.ts:\n// the symbol-keyed property is an implementation detail, accessed only by\n// the scheduler/fiber via the internal `getBacking` helper below.\nexport const futureBacking = Symbol(\"restateFutureBacking\");\n\n// Nominal brand that prevents arbitrary iterables (e.g. `Future<T>[]`) from\n// accidentally satisfying `Future<unknown>`. The symbol is NOT exported, so\n// external code cannot construct a value that satisfies the property without\n// a deliberate type assertion.\ndeclare const futureBrand: unique symbol;\n\nexport type JournalBacking<T> = {\n readonly kind: \"journal\";\n readonly promise: Awaitable<T>;\n};\n\n/**\n * In-memory completion source. Anything that gets settled exactly once\n * and notifies waiters can be a `WaitTarget` — fibers, channels, and\n * any future in-memory primitive we add (latch, semaphore, …).\n *\n * Contract mirrors `Fiber`'s lifecycle methods:\n * - `isDone()` and `settledValue()` for a synchronous short-circuit\n * when the target is already settled at park time.\n * - `awaitCompletion(waiter)` registers a one-shot callback;\n * returns the settled value if already done so the caller can\n * short-circuit without queuing.\n */\nexport interface WaitTarget<T> {\n isDone(): boolean;\n settledValue(): Settled;\n awaitCompletion(waiter: Waiter): Settled | null;\n // The generic parameter T is documentation; the concrete settle path\n // already carries the value via `Settled`. Kept on the interface so\n // call-site types match `Fiber<T>` / `ChannelImpl<T>` cleanly.\n readonly _phantom?: T;\n}\n\nexport type LocalBacking<T> = {\n readonly kind: \"local\";\n readonly target: WaitTarget<T>;\n};\n\nexport type Backing<T> = JournalBacking<T> | LocalBacking<T>;\n\n// Public Future is opaque — only the iterable shape is visible. The\n// `[futureBacking]: Backing<T>` storage lives on the internal type, kept\n// off the published API so we don't drag JournalBacking/LocalBacking/\n// WaitTarget/Awaitable/Settled/Waiter into the public surface.\nexport interface Future<T> extends Operation<T> {\n readonly [futureBrand]: unknown;\n}\n\n/**\n * Internal shape — Future plus its symbol-keyed backing slot. Kept off\n * the public `Future<T>` interface so `Backing`/`JournalBacking`/\n * `LocalBacking`/`WaitTarget` (and their transitive deps) don't leak\n * into the published `.d.ts`.\n */\nexport interface FutureWithBacking<T> extends Future<T> {\n readonly [futureBacking]: Backing<T>;\n}\n\n/** Like `FutureWithBacking<T>` but narrowed to a journal backing. */\nexport interface JournalBackedFuture<T> extends Future<T> {\n readonly [futureBacking]: JournalBacking<T>;\n}\n\n/**\n * Internal accessor — read the backing off a Future. Only the scheduler\n * and fiber call this; user code never sees Backing.\n */\nexport function getBacking<T>(f: Future<T>): Backing<T> {\n return (f as FutureWithBacking<T>)[futureBacking];\n}\n\nexport function makeFuture<T>(backing: Backing<T>): Future<T> {\n // Each Future carries a single Leaf op that the scheduler dispatches on.\n // Reused across [Symbol.iterator]() calls since it's stateless — just a\n // back-reference to this future for the scheduler to inspect.\n //\n // The forward-reference inside the iterator closure is safe: the\n // generator body only runs when [Symbol.iterator]() is iterated, which\n // can only happen after this function returns and `leafOp` is bound.\n const future = {\n [futureBacking]: backing,\n *[Symbol.iterator]() {\n return (yield leafOp) as T;\n },\n } as unknown as FutureWithBacking<T>;\n const leafOp: PrimitiveOp<T> = makePrimitive<T>({\n _tag: \"Leaf\",\n future,\n } as LeafNode<T>);\n return future;\n}\n\nexport function isJournalBacked<T>(f: Future<T>): f is JournalBackedFuture<T> {\n return getBacking(f).kind === \"journal\";\n}\n\n// =============================================================================\n// Helper types for heterogeneous combinator inputs.\n// =============================================================================\n//\n// `all([fA, fB, fC])` where each Future has a different value type\n// should yield `[A, B, C]`, not `(A | B | C)[]`. Mirrors the standard\n// lib's `Promise.all` pattern (see `lib.es2015.iterable.d.ts`):\n//\n// all<T extends readonly unknown[] | []>(values: T):\n// Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>\n//\n// Same idea here, but unwrapping `Future<U>` to `U` instead of\n// awaiting a Promise.\n\n/** Extract the value type from a `Future<U>`; `never` for non-Futures. */\nexport type FutureValue<F> = F extends Future<infer U> ? U : never;\n\n/**\n * Map a tuple of Futures to the tuple of their value types.\n * For `[Future<A>, Future<B>]` produces `[A, B]`.\n * For an unbounded `Future<X>[]` produces `X[]`.\n */\nexport type FutureValues<T extends readonly Future<unknown>[] | []> = {\n -readonly [P in keyof T]: T[P] extends Future<infer U> ? U : never;\n};\n\n// =============================================================================\n// FutureSettledResult variants — re-declared here with `reason: unknown`\n// instead of the std-lib's `reason: any`, which leaks `any` into allSettled's\n// return type and every caller that pattern-matches on the result.\n// =============================================================================\n\nexport interface FutureFulfilledResult<T> {\n readonly status: \"fulfilled\";\n readonly value: T;\n}\n\nexport interface FutureRejectedResult {\n readonly status: \"rejected\";\n readonly reason: unknown;\n}\n\nexport type FutureSettledResult<T> =\n | FutureFulfilledResult<T>\n | FutureRejectedResult;\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Linked AbortControllers.\n// =============================================================================\n//\n// A child AbortController whose signal aborts when its parent fires.\n// Used at two levels: the scheduler links its controller to the SDK's\n// attempt signal, and each fiber links its run-closure controller to the\n// scheduler's current signal — so invocation cancellation / attempt-end\n// cascade into in-flight `run` closures, while a targeted `interrupt`\n// can abort just one fiber's controller.\n\n/**\n * Create a controller whose signal is a child of `parent`: pre-aborted\n * if the parent has already fired, otherwise aborted the moment it does.\n *\n * The subscription uses `{ once, signal: c.signal }` so it self-detaches\n * on either exit — when the parent fires (`once`) or when this controller\n * is aborted by some other path (`signal`). A controller that is retired\n * and replaced therefore drops its listener immediately, so at most one\n * listener per child lives on the parent at a time — no accumulation\n * across cancel/recover or interrupt/recover cycles.\n */\nexport function linkAbortController(parent: AbortSignal): AbortController {\n const c = new AbortController();\n if (parent.aborted) {\n c.abort(parent.reason);\n } else {\n parent.addEventListener(\"abort\", () => c.abort(parent.reason), {\n once: true,\n signal: c.signal,\n });\n }\n return c;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Fiber<T>\n// =============================================================================\n//\n// A single strand of cooperative execution. Owns its iterator, its\n// lifecycle state (ready / parked / done), and its waiter list. The\n// scheduler orchestrates many fibers: keeping a ready queue, polling\n// parked fibers' sources, telling fibers to advance.\n//\n// Design boundary:\n//\n// Fiber owns: iterator, state transitions, dispatch of yielded\n// Leaf/AwaitRace ops, waiter notification.\n// Scheduler owns: the set of live fibers, the ready queue, the\n// Awaitable lib (race/all primitives), the main loop,\n// and cancellation broadcast.\n//\n// Communication is narrow:\n//\n// Scheduler → Fiber: new Fiber(op, sched), fiber.advance(),\n// fiber.wake(resume), fiber.parkedSources(),\n// fiber.awaitCompletion(waiter), fiber.isDone(),\n// fiber.settledValue().\n// Fiber → Scheduler: sched.markReady(this), sched.markDone(this).\n//\n// Invariants (the rules that make the rest reason-about-able):\n//\n// I1. A generator step runs ONLY inside `advance`, which the scheduler\n// calls ONLY from `drainReady`. `wake`, source `fire` callbacks,\n// and `finish`'s waiter notifications never run a step — they only\n// set state to `ready` and enqueue. So at most one fiber's body\n// runs at any instant (cooperative, single-threaded).\n// I2. `wake` is the sole transition into `ready`, and it bumps `epoch`\n// — the park-episode id. A waiter registered while parked is valid\n// only for that episode; once the fiber wakes (epoch advances) the\n// waiter is void. `epochGuarded` enforces this.\n// I3. A parked fiber normally leaves `parked` only when one of its own\n// sources fires. `interrupt`/cancellation are the exceptions: they\n// wake it OUT OF BAND, reusing the same resume path. The epoch\n// guard (stale waiters) and the `wokenDuringStep` check in\n// `advance` (self-interrupt) exist solely to keep those out-of-band\n// wakes safe.\n// I4. Journal-source fires need no epoch guard: the scheduler\n// re-collects parked sources fresh every tick, so a journal source\n// fires only in the tick it was collected, before the owner can\n// move on. Local waiters (channels, sibling fibers) are pruned by\n// nothing, so they MUST be epoch-guarded.\n\nimport type { Operation, PrimitiveOp, LeafNode } from \"./operation.js\";\nimport { opTag } from \"./operation.js\";\nimport type { Future, Backing, WaitTarget } from \"./future.js\";\nimport { getBacking } from \"./future.js\";\nimport type { Settled, PromiseSource, Waiter } from \"./scheduler-types.js\";\nimport { setCurrent, clearCurrent } from \"./current.js\";\nimport { linkAbortController } from \"./abort.js\";\n\n/**\n * Narrow interface a Fiber needs from its scheduler. Avoids a wide\n * coupling to Scheduler's full API; Fiber only ever calls these.\n */\nexport interface SchedulerOps {\n markReady(f: Fiber<unknown>): void;\n markDone(f: Fiber<unknown>): void;\n /**\n * The \"current fiber\" slot — the value installed by `execute()` as\n * the active `RestateOperations`. `Fiber.advance` publishes this to\n * the module-level slot so free-standing API functions can read it.\n * Typed `unknown` to avoid cycles with `restate-operations.ts`.\n */\n readonly contextSlot: unknown;\n /**\n * The scheduler's current AbortSignal. A fiber's per-fiber run signal\n * is a child of this, so invocation cancellation / attempt-end cascade\n * into in-flight `run` closures (see `Fiber.runSignal`).\n */\n readonly abortSignal: AbortSignal;\n}\n\ntype FiberState =\n | { kind: \"ready\"; resume: Settled | null }\n | { kind: \"parked\"; promises: PromiseSource[] }\n | { kind: \"done\"; settled: Settled };\n\nexport class Fiber<T = unknown> implements WaitTarget<T> {\n private readonly it: Iterator<unknown, unknown, unknown>;\n private readonly sched: SchedulerOps;\n private state: FiberState = { kind: \"ready\", resume: null };\n private waiters: Waiter[] = [];\n /**\n * Monotonic park-episode id, bumped on every `wake` (invariant I2).\n * Consumed by `epochGuarded` (waiter validity) and `wokenDuringStep`\n * (self-interrupt detection). Generalizes the old per-AwaitRace `won`\n * flag into a persistent, per-fiber guard.\n */\n private epoch = 0;\n /**\n * Whether the generator has been started (`it.next()` called at least\n * once). `it.throw()` on a not-yet-started generator propagates the\n * error out *without* running any body code, bypassing the routine's\n * own try/catch/finally — so an interrupt delivered before the first\n * advance must prime the generator first (see `stepIterator`).\n */\n private started = false;\n /**\n * Lazily-created AbortController for this fiber's `run` closures. Born\n * a child of the scheduler's current signal (so invocation cancellation\n * / attempt-end abort it) and aborted directly by `interrupt`. Recreated\n * when aborted, so cleanup `run`s after a swallowed interrupt see a\n * fresh, unaborted signal. Null until the fiber first needs a run signal.\n */\n private runController: AbortController | null = null;\n /**\n * Spawn-tree links. `parent` is the fiber that was advancing when this\n * one was created; `children` are the fibers it spawned (including the\n * synth fibers behind combinator fallbacks). `interrupt` cascades down\n * `children`. On `finish`, a fiber's still-live children are re-homed\n * onto its `parent` (not dropped) so the subtree stays connected to a\n * live ancestor and a later cascade still reaches them — `parent` is\n * therefore reassignable as ancestors complete.\n */\n private parent: Fiber<unknown> | null;\n private readonly children = new Set<Fiber<unknown>>();\n\n constructor(\n op: Operation<T>,\n sched: SchedulerOps,\n parent: Fiber<unknown> | null = null\n ) {\n this.it = op[Symbol.iterator]() as Iterator<unknown, unknown, unknown>;\n this.sched = sched;\n this.parent = parent;\n parent?.children.add(this as Fiber<unknown>);\n }\n\n // ---- lifecycle queries ----\n\n isDone(): boolean {\n return this.state.kind === \"done\";\n }\n\n /**\n * For a fiber known to be done, return its settled outcome. Throws\n * if called on a non-done fiber — callers must check `isDone()` first\n * (or use `awaitCompletion` for the polymorphic version).\n */\n settledValue(): Settled {\n if (this.state.kind !== \"done\") {\n throw new Error(\"Fiber.settledValue called on non-done fiber\");\n }\n return this.state.settled;\n }\n\n /**\n * Returns the parked sources this fiber is currently racing against.\n * Empty if the fiber is parked only on routine waiters (e.g.,\n * waiting on a sibling fiber to finish), or in any non-parked state.\n * The scheduler reads these to assemble its main-loop race.\n */\n parkedSources(): readonly PromiseSource[] {\n return this.state.kind === \"parked\" ? this.state.promises : [];\n }\n\n /**\n * \"I want to be notified when this fiber is done.\" If the fiber is\n * already done, returns its settled outcome immediately (caller\n * should NOT also expect the waiter to be invoked). Otherwise\n * returns null and queues the waiter for invocation when the fiber\n * eventually finishes.\n */\n awaitCompletion(waiter: Waiter): Settled | null {\n if (this.state.kind === \"done\") return this.state.settled;\n this.waiters.push(waiter);\n return null;\n }\n\n // ---- driving ----\n\n /**\n * Wake this fiber with a resume value. Transitions to ready and\n * notifies the scheduler. May be called from any state except done\n * (waking a done fiber is a programming error and is ignored\n * defensively).\n *\n * Bumps the park epoch so any waiters left registered on the targets\n * of the park we're leaving become stale no-ops (see `epoch`).\n */\n wake(resume: Settled | null): void {\n if (this.state.kind === \"done\") return;\n this.epoch++;\n this.state = { kind: \"ready\", resume };\n this.sched.markReady(this);\n }\n\n /**\n * Wrap a handler as a waiter that fires only while the fiber is still\n * in the park episode that registered it (see `epoch`, invariant I2).\n * A waiter left on a target after the fiber moved on — a re-park after\n * interrupt, or a losing race source — becomes a no-op. This is the\n * single mechanism behind both the AwaitRace \"first source wins\" dedup\n * and the cross-episode stale-waiter guard.\n */\n private epochGuarded(handler: (s: Settled) => void): Waiter {\n const at = this.epoch;\n return (s) => {\n if (this.epoch !== at) return;\n handler(s);\n };\n }\n\n /**\n * Whether a re-entrant `wake` fired during the step that began at\n * `epochBefore` — i.e. the fiber interrupted *itself* while advancing\n * (the only wake that can target the currently-advancing fiber). It\n * leaves a fresh resume in `this.state` to deliver at this yield rather\n * than parking on the op the body just produced.\n */\n private wokenDuringStep(epochBefore: number): boolean {\n return this.epoch !== epochBefore && this.state.kind === \"ready\";\n }\n\n /**\n * The AbortSignal handed to this fiber's `run` closures. Lazily\n * created as a child of the scheduler's current signal, so invocation\n * cancellation and attempt-end abort it like before; additionally,\n * `interrupt` aborts it directly to stop just this fiber's in-flight\n * I/O. Recreated once aborted, so a `run` issued after a swallowed\n * interrupt (or after cancellation recovery) gets a fresh signal.\n */\n runSignal(): AbortSignal {\n if (this.runController === null || this.runController.signal.aborted) {\n this.runController = linkAbortController(this.sched.abortSignal);\n }\n return this.runController.signal;\n }\n\n /**\n * Throw `err` into this fiber at its next yield point, and abort its\n * in-flight `run` I/O.\n *\n * Two effects: (1) abort the per-fiber run signal so an in-flight\n * `run(fetch(url, { signal }))` stops promptly — harmless if the fiber\n * has no live controller; the next `runSignal()` makes a fresh one for\n * post-interrupt cleanup. (2) wake the fiber with a failure resume so\n * `stepIterator` delivers `it.throw(err)` at the next advance — the\n * fiber's own try/catch may catch and recover (interrupt is\n * swallowable / non-sticky). A done fiber is left untouched (`wake`\n * no-ops). Same machinery as the cancellation fan-out, scoped to one\n * fiber.\n *\n * Self-interrupt (a fiber interrupting its own task while advancing)\n * is uniform: the re-entrant `wake` fires during the fiber's own\n * step, and `advance` detects the epoch bump and delivers the throw at\n * the fiber's next yield rather than parking (see `advance`). If the\n * body returns before reaching another yield, the self-interrupt is\n * moot — there is no yield point to throw at.\n */\n interrupt(err: unknown): void {\n this.runController?.abort(err);\n this.wake({ ok: false, e: err });\n // Cascade down the spawn subtree: a task's interrupt also interrupts\n // every routine it spawned (transitively). Synchronous and in-memory,\n // issued from a fiber advance — same determinism as a single\n // interrupt. The walk doesn't mutate `children` (interrupt only\n // wakes; finish/prune happens later in a drain), so iterating is safe.\n // The cascade is a single snapshot: routines a descendant spawns\n // *after* this fires (e.g. in its own interrupt-catch) are not\n // retroactively interrupted — interrupt is one-shot and non-sticky.\n for (const child of this.children) child.interrupt(err);\n }\n\n /**\n * Drive the fiber's iterator until it parks (yields a primitive\n * whose dispatch ends with the fiber waiting on a source) or\n * finishes (returns or throws).\n *\n * No-op if the fiber is not in the ready state — protects against\n * stale entries in the scheduler's ready queue.\n */\n advance(): void {\n if (this.state.kind !== \"ready\") return;\n // Publish the scheduler's RestateOperations slot to the module-level\n // pointer that free-standing API functions (sleep, run, all, …)\n // read. The slot lifetime is exactly the synchronous span of this\n // method; restored in `finally` so concurrent schedulers (different\n // execute() calls) don't clobber each other.\n const prevSlot = setCurrent(this.sched.contextSlot);\n try {\n let resume: Settled | null = this.state.resume;\n while (true) {\n // Snapshot the epoch around the step. A re-entrant `wake` during\n // user code (the fiber interrupting *itself* — the only way a\n // wake can target the fiber that is currently advancing) bumps\n // the epoch and installs a fresh resume in `this.state`. Stale\n // epoch-guarded waiters from a prior park return early without\n // waking, so they never bump it here — an epoch change across\n // the step means, unambiguously, a self-interrupt.\n const epochBefore = this.epoch;\n let next: IteratorResult<unknown, unknown>;\n try {\n next = stepIterator(this.it, resume, this.started);\n } catch (e) {\n this.finish({ ok: false, e });\n return;\n }\n this.started = true;\n if (next.done) {\n // The body returned before reaching another yield, so a\n // self-interrupt has no yield point to land on and is moot.\n this.finish({ ok: true, v: next.value });\n return;\n }\n\n // Self-interrupt during the step: deliver its resume at this\n // yield point instead of parking on the op the body just yielded.\n if (this.wokenDuringStep(epochBefore)) {\n resume = this.state.resume;\n continue;\n }\n\n const op = next.value as PrimitiveOp<unknown>;\n const node = op[opTag];\n // Each branch returns null to mean \"I parked, the fiber is\n // suspended\" or a Settled to mean \"resume the iterator with\n // this value.\" Leaf and AwaitRace may or may not park\n // depending on whether their target is already settled.\n let outcome: Settled | null;\n switch (node._tag) {\n case \"Leaf\":\n outcome = this.parkOnLeaf(node);\n break;\n case \"AwaitRace\":\n outcome = this.parkOnAwaitRace(node.futures);\n break;\n }\n\n if (outcome === null) return;\n resume = outcome;\n }\n } finally {\n clearCurrent(prevSlot);\n }\n }\n\n // ---- yield dispatch ----\n\n /**\n * Park on a single Future, or short-circuit if the Future is already\n * settled. Returns the Settled value to feed back into the iterator\n * if a short-circuit is possible (routine-backed future whose target\n * already finished); returns null if the fiber is parked and the\n * caller should suspend.\n */\n private parkOnLeaf(leaf: LeafNode<unknown>): Settled | null {\n const backing: Backing<unknown> = getBacking(leaf.future);\n if (backing.kind === \"journal\") {\n // Journal fires need no epoch guard (invariant I4): the scheduler\n // re-collects parked sources fresh each tick, so this source only\n // fires in the tick it was collected, before the fiber can move on.\n this.state = {\n kind: \"parked\",\n promises: [{ promise: backing.promise, fire: (s) => this.wake(s) }],\n };\n return null;\n }\n // Local-backed: ask the target (fiber, channel, …) for its settled\n // outcome (sync short-circuit) or register an epoch-guarded waiter —\n // the target never prunes it, so if we're interrupted and re-park it\n // must not wake the moved-on fiber.\n const settled = backing.target.awaitCompletion(\n this.epochGuarded((s) => this.wake(s))\n );\n if (settled !== null) return settled;\n this.state = { kind: \"parked\", promises: [] };\n return null;\n }\n\n /**\n * Park on the first-to-settle of a list of Futures, or short-circuit\n * if any source is already settled. Returns `{index, settled}`\n * (wrapped as Settled) on short-circuit, or null if parked.\n *\n * On the parked path, every source registers a one-shot fire\n * callback that wakes the fiber with `{index, settled}`. The epoch\n * guard ensures only the first source to settle wakes the fiber\n * (`wake` bumps the epoch, so any later same-tick fire sees a stale\n * epoch and no-ops) and that a waiter surviving an interrupt-and-\n * re-park can't fire onto the moved-on fiber. Local sources (fibers,\n * channels) park on the target's waiter list; journal sources race in\n * the main loop's race promise.\n */\n private parkOnAwaitRace(\n futures: ReadonlyArray<Future<unknown>>\n ): Settled | null {\n // Sync-check first: a local source whose target is already done\n // wins immediately. Journal sources can't be sync-checked — they\n // always defer to the race.\n for (let i = 0; i < futures.length; i++) {\n const b = getBacking(futures[i]!);\n if (b.kind === \"local\" && b.target.isDone()) {\n return { ok: true, v: { index: i, settled: b.target.settledValue() } };\n }\n }\n\n const promises: PromiseSource[] = [];\n for (let i = 0; i < futures.length; i++) {\n const idx = i;\n const b = getBacking(futures[i]!);\n // Epoch-guarded so only the first source to settle wakes the fiber\n // (later same-tick fires see the bumped epoch and no-op), and a\n // loser surviving an interrupt-and-re-park can't fire onto it.\n const fireOnce = this.epochGuarded((settled) =>\n this.wake({ ok: true, v: { index: idx, settled } })\n );\n if (b.kind === \"local\") {\n // The target may already be done — but we sync-checked above\n // and short-circuited if so. So awaitCompletion here will queue\n // the waiter (returning null). We ignore its return.\n b.target.awaitCompletion(fireOnce);\n } else {\n promises.push({ promise: b.promise, fire: fireOnce });\n }\n }\n this.state = { kind: \"parked\", promises };\n return null;\n }\n\n // ---- termination ----\n\n /**\n * Iterator finished or threw. Transition to done, fire all waiters\n * with the settled outcome, notify scheduler.\n */\n private finish(settled: Settled): void {\n this.state = { kind: \"done\", settled };\n // Re-home still-live children onto the grandparent before detaching,\n // so an ancestor's interrupt cascade still reaches them. A done fiber\n // is never interrupted again, so leaving children pointing at it would\n // sever the whole subtree from any live ancestor.\n const gp = this.parent;\n for (const child of this.children) {\n child.parent = gp;\n gp?.children.add(child);\n }\n this.children.clear();\n gp?.children.delete(this as Fiber<unknown>);\n const waiters = this.waiters;\n this.waiters = [];\n for (const w of waiters) w(settled);\n this.sched.markDone(this);\n }\n}\n\n/**\n * Drive a generator iterator one step, feeding it whatever value or\n * exception the caller is resuming with. `resume === null` is the\n * very first step; `{ok: true, v}` resumes with a value; `{ok: false,\n * e}` throws into the iterator (or, if the iterator has no `throw`\n * method, rethrows so the fiber fails).\n *\n * `started` is whether the generator has run at least once. Throwing\n * into a *not-yet-started* generator propagates the error straight out\n * without executing any body code (its try/catch/finally never engage).\n * That happens when a spawned routine is interrupted before its first\n * advance. To honor the \"delivered at the next yield point\" /\n * swallowable contract, we prime the generator with one `next()` first,\n * so the throw lands at the body's first yield. If the body returns\n * before reaching a yield, there is no yield point and the throw is moot.\n */\nfunction stepIterator(\n it: Iterator<unknown, unknown, unknown>,\n resume: Settled | null,\n started: boolean\n): IteratorResult<unknown, unknown> {\n if (resume === null) return it.next(undefined);\n if (resume.ok) return it.next(resume.v);\n if (!started) {\n const first = it.next(undefined);\n if (first.done) return first;\n }\n if (it.throw) return it.throw(resume.e);\n throw resume.e;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Channel<T>\n// =============================================================================\n//\n// A single-shot in-memory communication primitive. Cooperative — the\n// receiver chooses when to read, by yielding the channel's `receive`\n// Future. Composes with select, race, and any other Future-shaped\n// primitive.\n//\n// Semantics:\n//\n// send(v) — yieldable. `yield* ch.send(v)` settles the channel\n// with v. The first send wins; subsequent sends are\n// silently dropped (idempotent).\n// receive — a Future<T> that resolves with the sent value once\n// send fires. Always the same Future on every access;\n// settles once, stays settled forever, safe to share\n// across multiple selects/races.\n//\n// `send` returns `Operation<void>` so the only way to fire it is via\n// `yield*` from inside a generator body. This keeps channels\n// intra-workflow by construction — external code (setTimeout,\n// webhooks, cross-handler signals) doesn't have a generator to\n// `yield*` from, and should use `ops.awakeable()` instead, which is\n// durably journaled.\n//\n// Implementation: ChannelImpl is a `WaitTarget` (see future.ts). The\n// receive Future has `LocalBacking` pointing at this impl. When a\n// fiber yields receive, parkOnAwaitAny / parkOnLeaf treats it the\n// same as a routine-backed target — register a waiter, fire on\n// settle. `lib.race` never sees the channel; production's\n// RestatePromise.race is not involved.\n\nimport type { Settled, Waiter } from \"./scheduler-types.js\";\nimport { type Future, makeFuture, type WaitTarget } from \"./future.js\";\nimport { type Operation, gen } from \"./operation.js\";\n\nclass ChannelImpl<T> implements WaitTarget<T> {\n private state: { kind: \"pending\" } | { kind: \"settled\"; value: T } = {\n kind: \"pending\",\n };\n private waiters: Waiter[] = [];\n\n // Synchronous side-effect; only invoked from inside the gen body\n // returned by Channel.send (which itself is only iterable via\n // yield* inside a fiber).\n fire(value: T): void {\n if (this.state.kind === \"settled\") return;\n this.state = { kind: \"settled\", value };\n const ws = this.waiters;\n this.waiters = [];\n const settled: Settled = { ok: true, v: value };\n for (const w of ws) w(settled);\n }\n\n isDone(): boolean {\n return this.state.kind === \"settled\";\n }\n\n settledValue(): Settled {\n if (this.state.kind !== \"settled\") {\n throw new Error(\"ChannelImpl.settledValue called on a pending channel\");\n }\n return { ok: true, v: this.state.value };\n }\n\n awaitCompletion(waiter: Waiter): Settled | null {\n if (this.state.kind === \"settled\") {\n return { ok: true, v: this.state.value };\n }\n this.waiters.push(waiter);\n return null;\n }\n}\n\nexport interface Channel<T> {\n /**\n * Yieldable. Use as `yield* ch.send(value)` from within a gen body.\n * The first call settles the channel; subsequent calls are silently\n * dropped (idempotent).\n *\n * Return value is `Operation<void>` rather than `void` so the only\n * way to fire send is via `yield*` inside a fiber — which enforces\n * the channel-is-intra-workflow contract at the type level.\n */\n send(value: T): Operation<void>;\n readonly receive: Future<T>;\n}\n\nexport function makeChannel<T>(): Channel<T> {\n const impl = new ChannelImpl<T>();\n return {\n send: (v: T): Operation<void> =>\n // The generator body is intentionally yield-less: send's purpose\n // is a synchronous side effect that runs only when iterated via\n // `yield*`. The Operation wrapper exists for the type-level\n // enforcement, not because there's anything to suspend on.\n gen<void>(function* () {\n impl.fire(v);\n }),\n receive: makeFuture<T>({ kind: \"local\", target: impl }),\n };\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Scheduler\n// =============================================================================\n//\n// The runtime that drives Operations. Decoupled from Restate via the\n// Awaitable abstraction — production wires it to RestatePromise, tests\n// wire it to a hand-controlled promise type.\n//\n// The scheduler's job is orchestration:\n//\n// - Maintain the set of live fibers.\n// - Maintain the ready queue (which fibers want to run next).\n// - Run the main loop: assemble the parked sources from every live\n// fiber, race them via the lib, dispatch the winner.\n// - Broadcast invocation cancellation when the race rejects.\n// - Construct journal-backed and routine-backed Futures for users.\n//\n// The fiber's job is execution. The boundary between Scheduler and\n// Fiber is narrow (see `fiber.ts` and `SchedulerOps` interface).\n//\n// Invariants:\n//\n// S1. The ONLY async suspension point is the single `await lib.race`\n// per main-loop iteration. In production `lib.race` is a journaled\n// combinator, so its winner replays identically — this is the\n// determinism boundary. Drains, dispatch, and wakes are all\n// synchronous between two such awaits.\n// S2. Fibers advance ONLY inside `drainReady`. `advancingFiber` names\n// the one currently advancing (so `run` can hand it a per-fiber\n// signal); it is null between advances.\n// S3. Invocation cancellation is observed as the race promise\n// rejecting. It is fanned out to every parked source's `fire`,\n// reusing the normal wake path; the AbortController is aborted\n// then replaced so post-cancel recovery sees a fresh signal.\n\nimport type { Awaitable, AwaitableLib } from \"./awaitable.js\";\nimport {\n type Future,\n type FutureValue,\n type FutureValues,\n type FutureSettledResult,\n futureBacking,\n makeFuture,\n isJournalBacked,\n} from \"./future.js\";\nimport { type Operation, awaitRace, gen } from \"./operation.js\";\nimport type { Settled, PromiseSource } from \"./scheduler-types.js\";\nimport { Fiber, type SchedulerOps } from \"./fiber.js\";\nimport { type Channel, makeChannel } from \"./channel.js\";\nimport { type Task, makeTask } from \"./task.js\";\nimport { linkAbortController } from \"./abort.js\";\n\n/**\n * Policy for what happens to still-running spawned routines when the\n * main operation settles.\n *\n * - `\"abandon\"` (default): `run()` returns as soon as the main\n * operation settles. Still-running spawned routines (including\n * fibers synthesized internally by combinator fallbacks) are\n * abandoned at their current suspension point — they are never\n * resumed again, so no `catch`/`finally` blocks run and the sources\n * they were parked on are dropped. Durable work they already\n * started is journaled as usual; only the in-memory continuation is\n * discarded.\n * - `\"join\"`: `run()` keeps driving until *every* routine has\n * finished. A spawned routine parked on a source that never settles\n * keeps the handler from returning forever — prefer `\"abandon\"`\n * unless the workflow relies on fire-and-forget routines completing.\n */\nexport type OnMainExit = \"abandon\" | \"join\";\n\nexport interface SchedulerOptions {\n /** See {@link OnMainExit}. Defaults to `\"abandon\"`. */\n onMainExit?: OnMainExit;\n}\n\nexport class Scheduler implements SchedulerOps {\n private readonly fibers: Set<Fiber<unknown>> = new Set();\n private readonly ready: Fiber<unknown>[] = [];\n private readonly lib: AwaitableLib;\n private readonly onMainExit: OnMainExit;\n /**\n * The root fiber of the current `run()`. Assigned at the top of each\n * `run` call. Note the scheduler does not support concurrent `run`\n * calls (`fibers`/`ready`/`abortController` are equally shared);\n * production `execute()` always constructs a fresh scheduler.\n */\n private main: Fiber<unknown> | null = null;\n /**\n * The fiber currently being advanced by `drainReady`, or null between\n * advances. `run` reads this (via `currentRunSignal`) to hand a `run`\n * closure the *current fiber's* signal rather than a single global one,\n * so a targeted `interrupt` aborts only that fiber's in-flight I/O.\n */\n private advancingFiber: Fiber<unknown> | null = null;\n // Replaced (not just re-aborted) each time the scheduler observes\n // invocation cancellation. AbortControllers are one-way — once\n // aborted, signal.aborted stays true forever — so the scheduler-\n // level signal must be a fresh controller per cancel event to\n // preserve recoverability. Closures that captured the old signal\n // still see it as aborted (correctly, since their work was caught\n // by the cancellation); closures created after recovery see the new,\n // unaborted signal.\n private abortController: AbortController;\n\n /**\n * Parent AbortSignal supplied at construction (production: the SDK's\n * `attemptCompletedSignal`). Every controller this scheduler creates\n * is a child of it — born aborted if the parent has already fired,\n * aborted the moment it fires otherwise. Unlike cancellation, a\n * parent abort is sticky: an ended attempt never resumes. Defaults\n * to a signal that never fires.\n */\n private readonly parentSignal: AbortSignal;\n\n /**\n * Slot for the operations object bound to this scheduler. Defaults\n * to the scheduler itself so tests (which don't construct a\n * `RestateOperations`) still get a slot exposing `.spawn`. Production\n * `execute()` overrides this with a `RestateOperations` instance\n * after construction (we can't pass it into the ctor because\n * `RestateOperations` needs the scheduler to construct itself).\n * `Fiber.advance` publishes this to the module-level current-fiber\n * slot read by free-standing API functions. Typed `unknown` here to\n * keep this module independent of `restate-operations.ts`.\n */\n contextSlot: unknown;\n\n /**\n * Context-local storage: an ambient key/value bag scoped to this\n * scheduler — i.e. to this one `execute()` call, since production\n * builds a fresh scheduler per invocation (like `fibers` / `ready` /\n * `abortController`, this is per-run state, not shared across runs).\n * Every fiber under this scheduler reaches the same bag (global-per-\n * invocation; see `context.ts`). Keyed by the opaque symbol a\n * `contextLocal()` handle owns. In-memory only — never journaled.\n */\n private readonly localStore = new Map<symbol, unknown>();\n\n constructor(\n lib: AwaitableLib,\n parentSignal?: AbortSignal,\n options?: SchedulerOptions\n ) {\n this.lib = lib;\n this.onMainExit = options?.onMainExit ?? \"abandon\";\n this.contextSlot = this;\n this.parentSignal = parentSignal ?? new AbortController().signal;\n this.abortController = this.newAbortController();\n }\n\n /**\n * The scheduler's current AbortSignal. Aborts when invocation\n * cancellation is observed (the SDK rejects the main race promise\n * with TerminalError), or when the parent signal passed at\n * construction fires (production passes the SDK's\n * `attemptCompletedSignal`). After cancellation has been delivered\n * to fibers and the scheduler has resumed, this getter returns a\n * *fresh* signal — one that is not aborted, even though the previous\n * cancel was just delivered.\n *\n * Pass `signal` to AbortSignal-aware APIs in `ops.run` closures\n * (e.g. `fetch(url, {signal})`) so they cancel promptly when the\n * surrounding work is cancelled. Cleanup closures yielded after a\n * caught CancelledError get a fresh, unaborted signal — so they can\n * do real work and only abort if a *new* cancellation arrives.\n */\n get abortSignal(): AbortSignal {\n return this.abortController.signal;\n }\n\n /**\n * Fresh controller, born linked to the parent signal: pre-aborted if\n * the parent has already fired, otherwise subscribed to it. Births\n * the initial controller and each cancellation-recovery replacement.\n * Recovery closures must not see an unaborted signal once the\n * attempt itself is over — a parent abort is sticky.\n */\n private newAbortController(): AbortController {\n return linkAbortController(this.parentSignal);\n }\n\n /**\n * The AbortSignal for the currently-advancing fiber's `run` closures —\n * scoped per fiber so a targeted `interrupt(task)` aborts only that\n * task's in-flight I/O, while invocation cancellation / attempt-end\n * still cascade in (the fiber signal is a child of `abortSignal`).\n * Falls back to the scheduler signal when no fiber is advancing (a\n * defensive case — `run` is always called from inside a fiber).\n */\n currentRunSignal(): AbortSignal {\n return this.advancingFiber !== null\n ? this.advancingFiber.runSignal()\n : this.abortSignal;\n }\n\n // ---- SchedulerOps: narrow interface for Fiber ----\n\n markReady(f: Fiber<unknown>): void {\n this.ready.push(f);\n }\n\n markDone(f: Fiber<unknown>): void {\n // Remove from the live set so long-running loops that spawn (e.g.,\n // race in a while-true) don't accumulate dead-fiber objects. Safe\n // here because markDone is called from Fiber.advance, which only\n // runs between main-loop awaits — no other code is iterating\n // `fibers` now.\n this.fibers.delete(f);\n }\n\n private createFiber<U>(op: Operation<U>): Fiber<U> {\n // The fiber advancing right now (if any) is the spawning parent — so\n // `interrupt` can cascade down the spawn subtree. The root `main`\n // fiber is created outside any advance, so it has no parent.\n const f = new Fiber<U>(op, this, this.advancingFiber);\n this.fibers.add(f as Fiber<unknown>);\n this.ready.push(f as Fiber<unknown>);\n return f;\n }\n\n // ---- public construction helpers ----\n\n makeJournalFuture<U>(promise: Awaitable<U>): Future<U> {\n return makeFuture<U>({ kind: \"journal\", promise });\n }\n\n /**\n * Register an Operation as a fresh fiber, returning both its\n * local-backed Future and the underlying Fiber. Eager: by the time\n * this returns, the fiber is queued ready and will be advanced on the\n * next drain.\n *\n * Lifetime is bounded by the main fiber under the default\n * `\"abandon\"` policy: a spawned fiber still running when the main\n * fiber settles is abandoned (see {@link OnMainExit}). Under\n * `\"join\"` it keeps the scheduler alive until it finishes.\n *\n * Internal: combinator fallbacks (race, allSettled, …) use this to get\n * a plain Future. The public `spawn` wraps the same pair into a `Task`.\n */\n private spawnRoutine<U>(op: Operation<U>): {\n future: Future<U>;\n fiber: Fiber<U>;\n } {\n const fiber = this.createFiber(op);\n return { future: makeFuture<U>({ kind: \"local\", target: fiber }), fiber };\n }\n\n /** Spawn returning just the Future — for combinator fallbacks, which\n * never expose `interrupt` on their synthesized fibers. */\n private spawnFuture<U>(op: Operation<U>): Future<U> {\n return this.spawnRoutine(op).future;\n }\n\n /**\n * Register an Operation as a fresh fiber and return a `Task<U>` — a\n * `Future<U>` for its eventual value, plus `interrupt(err?)` to throw\n * into it at its next yield point. Eager: by the time this returns the\n * fiber is queued ready. Reached by `RestateOperations.spawn` and the\n * free `spawn` function.\n */\n spawn<U>(op: Operation<U>): Task<U> {\n const { future, fiber } = this.spawnRoutine(op);\n return makeTask(future, (err) => fiber.interrupt(err));\n }\n\n /**\n * Construct a single-shot in-memory channel. Send must be called from\n * a fiber currently advancing under this scheduler. See `channel.ts`\n * for full semantics.\n */\n makeChannel<U>(): Channel<U> {\n return makeChannel<U>();\n }\n\n // ---- context-local storage (see context.ts) ----\n\n /**\n * Read a context-local value, or `fallback` if `key` was never set in\n * this invocation. `has`-checked so an explicit `setLocal(key,\n * undefined)` reads back as `undefined` rather than falling through to\n * the handle's default.\n */\n getLocal(key: symbol, fallback: unknown): unknown {\n return this.localStore.has(key) ? this.localStore.get(key) : fallback;\n }\n\n /** Write a context-local value for the rest of this invocation. */\n setLocal(key: symbol, value: unknown): void {\n this.localStore.set(key, value);\n }\n\n // ---- combinator helpers (used by RestateOperations) ----\n\n /**\n * Combinator over Futures. Fast path when every input is journal-\n * backed: use the lib's all/race for a single combinator entry.\n * Otherwise, fall back to a synthesized fiber that yields each in\n * turn.\n *\n * Tuple-aware typing (mirrors `Promise.all` in the standard lib):\n * `all([fA, fB])` where `fA: Future<A>` and `fB: Future<B>`\n * yields `Future<[A, B]>`, not `Future<(A | B)[]>`. The `const T`\n * lets TS infer a tuple from a literal array.\n */\n all<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>> {\n // Cast to a uniform shape so `every(isJournalBacked)`'s type\n // predicate narrows elements correctly; the input tuple's\n // heterogeneous element types are recovered via the return cast.\n const fs = futures as ReadonlyArray<Future<unknown>>;\n if (fs.every(isJournalBacked)) {\n const promises = fs.map((f) => f[futureBacking].promise);\n return this.makeJournalFuture(this.lib.all(promises)) as Future<\n FutureValues<T>\n >;\n }\n return this.spawnFuture(\n gen<FutureValues<T>>(function* () {\n const out: unknown[] = new Array(fs.length);\n for (let i = 0; i < fs.length; i++) {\n // In case of failure, this throws, respecting the contract that all shortcircuits on failure\n out[i] = yield* fs[i]!;\n }\n return out as FutureValues<T>;\n })\n );\n }\n\n race<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>[number]> {\n type R = FutureValues<T>[number];\n const fs = futures as ReadonlyArray<Future<unknown>>;\n // No need here to try downcasting to RestateFuture's, awaitRace will anyway produce the same UnresolvedFuture tree!\n return this.spawnFuture(\n gen<R>(function* () {\n const result = yield* awaitRace(fs);\n if (result.settled.ok) return result.settled.v as R;\n throw result.settled.e;\n })\n );\n }\n\n /**\n * First-success combinator. Mirrors `Promise.any` /\n * `RestatePromise.any`: settles with the first input that succeeds\n * (non-rejected); rejects with `AggregateError(errors)` when every\n * input rejects (including the empty-array case).\n *\n * Fast path collapses to a single `lib.any` over journal awaitables.\n * Fallback synthesizes a fiber that loops `awaitAnyOf` over the\n * still-pending subset, accumulating rejections in input order until\n * one input fulfills or all have rejected.\n *\n * Tuple-aware: `any([fA, fB])` where `fA: Future<A>` and `fB:\n * Future<B>` yields `Future<A | B>` (the union of slot types), same\n * shape as `Promise.any`.\n */\n any<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>[number]> {\n type R = FutureValues<T>[number];\n const fs = futures as ReadonlyArray<Future<unknown>>;\n if (fs.every(isJournalBacked)) {\n const promises = fs.map((f) => f[futureBacking].promise);\n return this.makeJournalFuture(this.lib.any(promises)) as Future<R>;\n }\n return this.spawnFuture(\n gen<R>(function* () {\n const errors: unknown[] = new Array(fs.length);\n const remaining = new Set<number>();\n for (let i = 0; i < fs.length; i++) remaining.add(i);\n while (remaining.size > 0) {\n const liveIdx = Array.from(remaining);\n const live = liveIdx.map((i) => fs[i]!);\n const result = yield* awaitRace(live);\n const original = liveIdx[result.index]!;\n if (result.settled.ok) return result.settled.v as R;\n errors[original] = result.settled.e;\n remaining.delete(original);\n }\n throw new AggregateError(errors, \"All promises were rejected\");\n })\n );\n }\n\n /**\n * Settle-all combinator. Mirrors `Promise.allSettled` /\n * `RestatePromise.allSettled`: resolves with an array of\n * `FutureSettledResult` in input order, never rejects.\n *\n * Fast path collapses to a single `lib.allSettled`. Fallback yields\n * each Future in turn — safe because Futures are eager (already in\n * flight); sequential harvesting just reads them as they complete\n * without blocking concurrency.\n *\n * Tuple-aware: `allSettled([fA, fB])` yields\n * `Future<[FutureSettledResult<A>, FutureSettledResult<B>]>`.\n */\n allSettled<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<{\n -readonly [P in keyof T]: FutureSettledResult<FutureValue<T[P]>>;\n }> {\n type R = {\n -readonly [P in keyof T]: FutureSettledResult<FutureValue<T[P]>>;\n };\n const fs = futures as ReadonlyArray<Future<unknown>>;\n if (fs.every(isJournalBacked)) {\n const promises = fs.map((f) => f[futureBacking].promise);\n return this.makeJournalFuture(this.lib.allSettled(promises)) as Future<R>;\n }\n return this.spawnFuture(\n gen<R>(function* () {\n const out = new Array<FutureSettledResult<unknown>>(fs.length);\n for (let i = 0; i < fs.length; i++) {\n try {\n const value = yield* fs[i]!;\n out[i] = { status: \"fulfilled\", value };\n } catch (reason) {\n out[i] = { status: \"rejected\", reason };\n }\n }\n return out as R;\n })\n );\n }\n\n // ---- driving ----\n\n /**\n * True once the main fiber has settled under the `\"abandon\"` policy —\n * the signal to stop driving everything else. Checked by the main\n * loop *and* by `drainReady`, so the drain stops promptly mid-queue:\n * nothing observable (journal writes, channel sends, side effects)\n * happens after the main fiber's outcome is decided. Always false\n * under `\"join\"`.\n */\n private mainExited(): boolean {\n return (\n this.onMainExit === \"abandon\" && this.main !== null && this.main.isDone()\n );\n }\n\n private drainReady(): void {\n while (this.ready.length > 0 && !this.mainExited()) {\n const f = this.ready.shift()!;\n // Track the advancing fiber so `run` (called synchronously from\n // inside `f.advance()`) can read this fiber's run signal. Saved/\n // restored to tolerate any nesting, though advances don't nest.\n const prev = this.advancingFiber;\n this.advancingFiber = f;\n try {\n f.advance();\n } finally {\n this.advancingFiber = prev;\n }\n }\n }\n\n /**\n * Run an operation to completion. Drain the ready queue, then loop:\n * collect every PromiseSource from every parked fiber, race them,\n * dispatch the winner via its fire callback, drain.\n *\n * When to stop is governed by `onMainExit`: under `\"abandon\"` (the\n * default) the loop ends as soon as the main fiber settles and any\n * still-running spawned fibers are abandoned; under `\"join\"` it ends\n * only when no fiber is alive.\n */\n async run<T>(op: Operation<T>): Promise<T> {\n const main = this.createFiber(op);\n this.main = main as Fiber<unknown>;\n this.drainReady();\n\n // Under \"join\", mainExited() is always false and the loop runs\n // until every fiber is done. Under \"abandon\", main ∈ fibers while\n // it is alive, so the conjunction reduces to !main.isDone().\n while (!this.mainExited() && this.fibers.size > 0) {\n const items: PromiseSource[] = [];\n for (const f of this.fibers) {\n for (const src of f.parkedSources()) items.push(src);\n }\n if (items.length === 0) {\n // Live fibers exist but no journal promises are pending — a\n // wait-cycle deadlock, or fibers parked only on routine waiters\n // whose targets can't progress.\n throw new Error(\n \"scheduler stuck: live fibers but nothing pending on a journal promise\"\n );\n }\n\n const tagged = items.map(({ promise }, i) =>\n promise.map((v, e): { i: number } & Settled =>\n e !== undefined ? { i, ok: false, e } : { i, ok: true, v }\n )\n );\n\n // The race promise itself can be settled with a rejection by\n // the SDK when invocation cancellation arrives. Per-source\n // promises are unaffected — the rejection lives on this\n // aggregate race promise. We fan the rejection out to every\n // parked fiber: each was, in effect, contributing a source to\n // this race, so each gets the TerminalError delivered at its\n // current yield point. Fibers may catch and continue normally;\n // subsequent iterations build fresh race promises that are not\n // infected by this rejection.\n //\n // Before fanning out, abort the current AbortController so\n // in-flight syscalls inside ops.run closures (those listening\n // on the captured signal) start cancelling immediately. Then\n // replace the controller with a fresh one so that closures\n // created during recovery (cleanup yields, etc.) see an\n // unaborted signal — cancellation is not a sticky state.\n let raceWinner: { i: number } & Settled;\n try {\n raceWinner = (await this.lib.race(tagged)) as { i: number } & Settled;\n } catch (e) {\n if (this.lib.isCancellation(e)) {\n this.abortController.abort(e);\n this.abortController = this.newAbortController();\n }\n const errSettled: Settled = { ok: false, e };\n for (const it of items) it.fire(errSettled);\n this.drainReady();\n continue;\n }\n\n const { i, ...settledFields } = raceWinner;\n const settled: Settled = settledFields.ok\n ? { ok: true, v: settledFields.v }\n : { ok: false, e: settledFields.e };\n items[i]!.fire(settled);\n this.drainReady();\n }\n\n if (!main.isDone()) {\n throw new Error(\"scheduler exited but main fiber never completed\");\n }\n const final = main.settledValue();\n if (final.ok) return final.v as T;\n throw final.e;\n }\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// State<TState>\n// =============================================================================\n//\n// Wrapper around Restate's KeyValueStore — the per-key state attached\n// to a virtual object or workflow invocation. Available via\n// `ops.state()` (read-write) or `ops.sharedState()` (read-only) from\n// within `execute()`.\n//\n// Read-only vs read-write is a real distinction:\n// - ObjectContext / WorkflowContext expose the full KeyValueStore\n// (get + keys + set + clear + clearAll).\n// - ObjectSharedContext / WorkflowSharedContext expose only the\n// reads. Calling `set` etc. on the underlying context throws at\n// runtime; we surface that at the type level by giving shared\n// handlers a narrower interface.\n//\n// Both interfaces are generic over `TState extends TypedState`:\n// - Default `UntypedState` keeps the loose `(name: string)` shape\n// and a per-call value type — same as the SDK's untyped mode.\n// - Pass an explicit shape to get keyof-checked names and per-key\n// value types: `ops.state<{count: number; user: User}>()` then\n// `state.get(\"count\")` infers `Future<number | null>`.\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport type { Awaitable } from \"./awaitable.js\";\nimport type { Future } from \"./future.js\";\nimport type { Scheduler } from \"./scheduler.js\";\n\n/**\n * Marker types matching the SDK's typed-state convention. Pass a\n * concrete shape (e.g. `{count: number; name: string}`) to enable\n * keyof-checked names; leave the default to keep names as `string`\n * with a per-call value generic.\n */\nexport type TypedState = Record<string, unknown>;\nexport type UntypedState = { _: never };\n\n/**\n * Read-only state, for handlers running under an\n * ObjectSharedContext or WorkflowSharedContext.\n */\nexport interface SharedState<TState extends TypedState = UntypedState> {\n /** Read a state value. Returns null if the key isn't set. */\n get<TValue, TKey extends keyof TState = string>(\n name: TState extends UntypedState ? string : TKey,\n serde?: restate.Serde<TState extends UntypedState ? TValue : TState[TKey]>\n ): Future<(TState extends UntypedState ? TValue : TState[TKey]) | null>;\n\n /** List all currently-known state keys. */\n keys(): Future<string[]>;\n}\n\n/**\n * Read-write state, for handlers running under an ObjectContext or\n * WorkflowContext. Extends SharedState with mutation methods.\n *\n * Writes are synchronous in the SDK — the journal entry is recorded\n * immediately, no yield required — so `set` / `clear` / `clearAll`\n * return `void` rather than `Operation<void>`.\n */\nexport interface State<\n TState extends TypedState = UntypedState,\n> extends SharedState<TState> {\n /** Write a state value. Sync; journal entry recorded immediately. */\n set<TValue, TKey extends keyof TState = string>(\n name: TState extends UntypedState ? string : TKey,\n value: TState extends UntypedState ? TValue : TState[TKey],\n serde?: restate.Serde<TState extends UntypedState ? TValue : TState[TKey]>\n ): void;\n\n /** Clear a single key. */\n clear<TKey extends keyof TState>(\n name: TState extends UntypedState ? string : TKey\n ): void;\n\n /** Clear all state for this invocation. */\n clearAll(): void;\n}\n\n// Loose type covering every Restate context flavor that exposes any\n// state methods. We only call KeyValueStore methods on this; the rest\n// of Context is unused here.\ntype StateContext =\n | restate.ObjectContext\n | restate.ObjectSharedContext\n | restate.WorkflowContext\n | restate.WorkflowSharedContext;\n\n/**\n * Build a `State<TState>` over the given context. The runtime delegates\n * straight to `ctx.get` / `ctx.set` / etc.; the TState generic is purely\n * a TS-level convenience and gets erased at runtime.\n *\n * For shared (read-only) contexts, the returned State has the same\n * runtime shape but the caller should use the `SharedState<TState>`\n * type to drop the write methods. The convenience method\n * `RestateOperations.sharedState()` does this cast.\n */\nexport function makeState<TState extends TypedState = UntypedState>(\n ctx: StateContext,\n sched: Scheduler,\n adapt: <T>(p: restate.RestatePromise<T>) => Awaitable<T>\n): State<TState> {\n // Cast for write methods: the typed shared variants don't have them\n // on the type, but the runtime object does carry them in writable\n // contexts. Calling write() from a shared handler throws naturally.\n const writeCtx = ctx as restate.ObjectContext;\n\n // Internally we use the loose UntypedState signatures and cast the\n // resulting object to the narrower State<TState>. Runtime is identical;\n // the conditional types only matter at the call site.\n const impl: State<UntypedState> = {\n get<T>(name: string, serde?: restate.Serde<T>): Future<T | null> {\n return sched.makeJournalFuture(\n adapt(\n ctx.get<T>(name, serde) as unknown as restate.RestatePromise<T | null>\n )\n );\n },\n keys(): Future<string[]> {\n return sched.makeJournalFuture(\n adapt(ctx.stateKeys() as unknown as restate.RestatePromise<string[]>)\n );\n },\n set<T>(name: string, value: T, serde?: restate.Serde<T>): void {\n writeCtx.set(name, value, serde);\n },\n clear(name: string): void {\n writeCtx.clear(name);\n },\n clearAll(): void {\n writeCtx.clearAll();\n },\n };\n return impl as unknown as State<TState>;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport * as restate from \"@restatedev/restate-sdk\";\nimport type { Future } from \"./future.js\";\nimport type { InvocationReference } from \"./invocation-reference.js\";\nimport type { HandlerDescriptor, Descriptor } from \"./define.js\";\nimport {\n ClientCallOptions,\n ClientSendOptions,\n Opts,\n SendOpts,\n} from \"@restatedev/restate-sdk\";\n\n/**\n * A Future<O> that also carries an `invocation` field — a Future<InvocationReference<O>>\n * for accessing the invocationId, attach, cancel, and signal of the underlying call.\n */\nexport type ClientFuture<O> = Future<O> & {\n invocation: Future<InvocationReference<O>>;\n};\n\n/** Client type returned by client() — each method returns ClientFuture<O> */\nexport type GenClient<H extends Record<string, HandlerDescriptor>> = {\n readonly [K in keyof H]: H[K] extends HandlerDescriptor<infer I, infer O>\n ? [I] extends [void]\n ? (opts?: Opts<I, O>) => ClientFuture<O>\n : (input: I, opts?: Opts<I, O>) => ClientFuture<O>\n : never;\n};\n\n/** Client type returned by sendClient() — each method returns Future<InvocationReference<O>> */\nexport type GenSendClient<H extends Record<string, HandlerDescriptor>> = {\n readonly [K in keyof H]: H[K] extends HandlerDescriptor<infer I, infer O>\n ? [I] extends [void]\n ? (opts?: SendOpts<I>) => Future<InvocationReference<O>>\n : (input: I, opts?: SendOpts<I>) => Future<InvocationReference<O>>\n : never;\n};\n\n// =============================================================================\n// makeClient / makeSendClient — proxy factories used by RestateOperations\n// =============================================================================\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport function makeClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, any>,\n key: string | undefined,\n call: (opts: restate.GenericCall<unknown, unknown>) => ClientFuture<unknown>,\n scope?: string\n): GenClient<H> {\n return new Proxy({} as any, {\n get(_target, methodName: string) {\n return (...args: unknown[]) => {\n const { parameter, opts } = optsFromArgs(args);\n const callOpts = opts as ClientCallOptions<unknown, unknown>;\n const desc = def._handlers[methodName];\n const outputSerde = callOpts?.output ?? desc?._outputSerde;\n return call({\n service: def.name,\n key,\n method: String(methodName),\n parameter,\n inputSerde: (callOpts?.input ??\n desc?._inputSerde ??\n restate.serde.json) as restate.Serde<unknown>,\n outputSerde: (outputSerde ??\n restate.serde.json) as restate.Serde<unknown>,\n idempotencyKey: callOpts?.idempotencyKey,\n limitKey: callOpts?.limitKey,\n scope,\n headers: callOpts?.headers,\n name: callOpts?.name,\n });\n };\n },\n }) as GenClient<H>;\n}\n\nexport function makeSendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, any>,\n key: string | undefined,\n send: (\n opts: restate.GenericSend<unknown>,\n outputSerde?: restate.Serde<unknown>\n ) => Future<InvocationReference<unknown>>,\n scope?: string\n): GenSendClient<H> {\n return new Proxy({} as any, {\n get(_target, methodName: string) {\n return (...args: unknown[]) => {\n const { parameter, opts } = optsFromArgs(args);\n const sendOpts = opts as ClientSendOptions<unknown>;\n const desc = def._handlers[methodName];\n return send(\n {\n service: def.name,\n key,\n method: String(methodName),\n parameter,\n inputSerde: (sendOpts?.input ??\n desc?._inputSerde ??\n restate.serde.json) as restate.Serde<unknown>,\n delay: sendOpts?.delay,\n idempotencyKey: sendOpts?.idempotencyKey,\n limitKey: sendOpts?.limitKey,\n scope,\n headers: sendOpts?.headers,\n name: sendOpts?.name,\n },\n desc?._outputSerde as restate.Serde<unknown> | undefined\n );\n };\n },\n }) as GenSendClient<H>;\n}\n\nfunction optsFromArgs(args: unknown[]): {\n parameter?: unknown;\n opts?:\n | ClientCallOptions<unknown, unknown>\n | ClientSendOptions<unknown>\n | undefined;\n} {\n let parameter: unknown;\n let opts:\n | ClientCallOptions<unknown, unknown>\n | ClientSendOptions<unknown>\n | undefined;\n switch (args.length) {\n case 0: {\n break;\n }\n case 1: {\n if (args[0] instanceof Opts) {\n opts = args[0].getOpts();\n } else if (args[0] instanceof SendOpts) {\n opts = args[0].getOpts();\n } else {\n parameter = args[0];\n }\n break;\n }\n case 2: {\n parameter = args[0];\n if (args[1] instanceof Opts) {\n opts = args[1].getOpts();\n } else if (args[1] instanceof SendOpts) {\n opts = args[1].getOpts();\n } else {\n throw new TypeError(\n \"The second argument must be either Opts or SendOpts\"\n );\n }\n break;\n }\n default: {\n throw new TypeError(\"unexpected number of arguments\");\n }\n }\n return {\n parameter,\n opts,\n };\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport type { Future } from \"./future.js\";\n\n/** Same shape as the SDK's DurablePromise<T> but each method returns Future<...>. */\nexport type GenDurablePromise<T> = {\n peek(): Future<T | undefined>;\n resolve(value?: T): Future<void>;\n reject(errorMsg: string): Future<void>;\n get(): Future<T>;\n};\n\nexport function wrapDurablePromise<T>(\n dp: restate.DurablePromise<T>,\n toFuture: <U>(p: restate.RestatePromise<U> | Promise<U>) => Future<U>\n): GenDurablePromise<T> {\n return {\n peek: () =>\n toFuture(dp.peek() as unknown as restate.RestatePromise<T | undefined>),\n resolve: (value?: T) =>\n toFuture(dp.resolve(value) as unknown as restate.RestatePromise<void>),\n reject: (errorMsg: string) =>\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n toFuture(dp.reject(errorMsg) as unknown as restate.RestatePromise<void>),\n get: () => toFuture(dp.get()),\n };\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Production wiring: an AwaitableLib backed by restate.RestatePromise.\n//\n// RestatePromise is structurally compatible with Awaitable<T> already — it\n// has `.map((v, e) => U)` and is thenable. The adapter is a simple cast\n// at the boundary; the four combinators forward to RestatePromise's\n// static methods, preserving the tuple-aware result types declared on\n// AwaitableLib.\n\nimport * as restate from \"@restatedev/restate-sdk\";\nimport type { Awaitable, AwaitableLib } from \"./awaitable.js\";\nimport type { FutureSettledResult } from \"./future.js\";\n\nexport const defaultLib: AwaitableLib = {\n all<const T extends readonly Awaitable<unknown>[]>(\n items: T\n ): Awaitable<{ -readonly [P in keyof T]: Awaited<T[P]> }> {\n return restate.RestatePromise.all(\n items as unknown as readonly restate.RestatePromise<unknown>[]\n ) as unknown as Awaitable<{ -readonly [P in keyof T]: Awaited<T[P]> }>;\n },\n race<const T extends readonly Awaitable<unknown>[]>(\n items: T\n ): Awaitable<Awaited<T[number]>> {\n return restate.RestatePromise.race(\n items as unknown as readonly restate.RestatePromise<unknown>[]\n ) as unknown as Awaitable<Awaited<T[number]>>;\n },\n any<const T extends readonly Awaitable<unknown>[]>(\n items: T\n ): Awaitable<Awaited<T[number]>> {\n return restate.RestatePromise.any(\n items as unknown as readonly restate.RestatePromise<unknown>[]\n ) as unknown as Awaitable<Awaited<T[number]>>;\n },\n allSettled<const T extends readonly Awaitable<unknown>[]>(\n items: T\n ): Awaitable<{\n -readonly [P in keyof T]: FutureSettledResult<Awaited<T[P]>>;\n }> {\n return restate.RestatePromise.allSettled(\n items as unknown as readonly restate.RestatePromise<unknown>[]\n ) as unknown as Awaitable<{\n -readonly [P in keyof T]: FutureSettledResult<Awaited<T[P]>>;\n }>;\n },\n // Invocation cancellation arrives at the aggregate race promise as a\n // CancelledError (the SDK's terminal-error subclass with code 409).\n isCancellation(e: unknown): boolean {\n return e instanceof restate.CancelledError;\n },\n};\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unnecessary-type-assertion */\n\n// RestateOperations\n// =============================================================================\n//\n// Production-side wrapper around restate.Context. Produces journal-backed\n// Futures by delegating to the Restate SDK; defers to the scheduler for\n// spawn/all/race/select.\n//\n// Tests don't need this class — they construct Futures via\n// `Scheduler.makeJournalFuture(testPromise)` directly, build operations via\n// `gen()`, and run them via `Scheduler.run()`. This module's only job is\n// gluing the Restate SDK to the scheduler for production use.\n\nimport * as restate from \"@restatedev/restate-sdk\";\nimport type { Awaitable } from \"./awaitable.js\";\nimport type { Future, FutureSettledResult, FutureValues } from \"./future.js\";\nimport type { Task } from \"./task.js\";\nimport type { Channel } from \"./channel.js\";\nimport {\n gen,\n type Operation,\n select as selectOp,\n type SelectResult,\n} from \"./operation.js\";\nimport type { Scheduler, SchedulerOptions } from \"./scheduler.js\";\nimport { Scheduler as SchedulerClass } from \"./scheduler.js\";\nimport {\n makeState,\n type SharedState,\n type State,\n type TypedState,\n type UntypedState,\n} from \"./state.js\";\nimport {\n type ClientFuture,\n type GenClient,\n type GenSendClient,\n makeClient,\n makeSendClient,\n} from \"./clients.js\";\nimport {\n type GenDurablePromise,\n wrapDurablePromise,\n} from \"./durable-promise.js\";\nimport type { Descriptor, HandlerDescriptor } from \"./define.js\";\nimport {\n type InvocationReference,\n InvocationReferenceImpl,\n type SignalReference,\n} from \"./invocation-reference.js\";\nimport { defaultLib } from \"./default-lib.js\";\nimport { RestatePromise } from \"@restatedev/restate-sdk\";\n\n// Adapt a real RestatePromise to our Awaitable interface. RestatePromise\n// already has `.map((v, e) => U)` and is thenable, so the adapter is a\n// structural pass-through.\nfunction adapt<T>(p: restate.RestatePromise<T>): Awaitable<T> {\n return p as unknown as Awaitable<T>;\n}\n\nexport type HandlerRequest = Omit<restate.Request, \"attemptCompletedSignal\"> & {\n /**\n * Object key or Workflow key\n */\n readonly key?: string;\n};\n\n/**\n * Retry policy for `run`. Mirrors the SDK's `RunOptions` retry knobs\n * but namespaced (no `Retry` prefix on each field) and grouped under\n * `RunOpts.retry` for readability.\n */\nexport type RetryOptions = {\n /**\n * Max attempts (including the initial). When reached, `run` throws\n * a `TerminalError` wrapping the original error message.\n */\n maxAttempts?: number;\n /**\n * Max total duration of retries before giving up. Number is ms.\n */\n maxDuration?: restate.Duration | number;\n /**\n * First retry delay. Subsequent delays grow by `exponentiationFactor`.\n * Number is ms. Defaults to 50 ms.\n */\n initialInterval?: restate.Duration | number;\n /**\n * Cap on retry delay. Number is ms. Defaults to 10 s.\n */\n maxInterval?: restate.Duration | number;\n /**\n * Exponentiation factor applied to the previous delay. Defaults to 2.\n */\n exponentiationFactor?: number;\n /**\n * @deprecated Renamed to {@link exponentiationFactor}.\n */\n intervalFactor?: number;\n};\n\n/**\n * Options for `run`. Both fields are optional; if `name` is omitted,\n * the action's `Function.name` is used (works for named functions and\n * for arrow functions assigned to a `const` since JS infers names from\n * the binding site). If neither resolves, `run` throws.\n */\nexport type RunOpts<T> = {\n /** Journal entry name. Falls back to `action.name` if absent. */\n name?: string;\n /** Retry policy. Defaults to the SDK's defaults if absent. */\n retry?: RetryOptions;\n /** Custom serde for the journaled value. */\n serde?: restate.Serde<T>;\n};\n\n/**\n * Options object passed to the closure of `run(...)`. Carries an\n * AbortSignal that fires when invocation cancellation arrives.\n *\n * Using an object (rather than positional args) leaves room to extend\n * the closure's API surface — additional fields may be added later\n * without breaking existing closures.\n */\nexport type RunActionOpts = {\n readonly signal: AbortSignal;\n};\n\n/**\n * The closure that `run` invokes. Receives `{ signal }` — pass the\n * signal into AbortSignal-aware APIs (e.g. `fetch(url, { signal })`)\n * to cancel in-flight syscalls promptly.\n */\nexport type RunAction<T> = (opts: RunActionOpts) => Promise<T>;\n\n/**\n * Wrap a user-supplied `run` closure to surface the abort reason\n * (typically a TerminalError(CANCELLED)) on throw paths if the signal\n * aborted during execution. This converts AbortError (and any other\n * abort-caused failure) into the canonical cancellation TerminalError\n * for journal recording.\n *\n * Defensive coercion: if `signal.reason` is itself not a TerminalError\n * (which shouldn't happen in production but might during testing or\n * with non-cancellation race rejections), we wrap it in one. The\n * journal must record a *terminal* outcome to avoid retries against\n * a cancelled invocation.\n *\n * Exposed for testing — the wrapper's behavior is the part that has\n * semantic bite, separate from the ctx.run plumbing.\n */\nexport function wrapActionForCancellation<T>(\n signal: AbortSignal,\n action: RunAction<T>\n): () => Promise<T> {\n return async () => {\n try {\n return await action({ signal });\n } catch (e) {\n if (signal.aborted) {\n throw asTerminalError(signal.reason);\n }\n throw e;\n }\n };\n}\n\n/**\n * Resolve the journal-entry name; throw `TerminalError` if neither\n * source provides one.\n *\n * `TerminalError` (not a plain `Error`) because a missing name is a\n * programming bug — retrying the invocation will hit the same code\n * path and fail the same way. The SDK treats terminal errors as\n * non-retryable; the invocation fails fast instead of looping.\n */\nfunction resolveRunName<T>(action: RunAction<T>, opts?: RunOpts<T>): string {\n const fromOpts = opts?.name?.trim();\n if (fromOpts) return fromOpts;\n const fromFn = action.name;\n if (fromFn) return fromFn;\n throw new restate.TerminalError(\n \"@restatedev/restate-sdk-gen: run() requires a journal-entry name. \" +\n \"Either pass a named function (`run(myFn)`) or supply \" +\n \"`{ name: '...' }` in the second argument.\"\n );\n}\n\n/** Translate our `RetryOptions` into the SDK's flat `RunOptions` shape. */\nfunction toSdkRunOptions<T>(opts?: RunOpts<T>): restate.RunOptions<T> {\n const out: restate.RunOptions<T> = {};\n if (opts?.serde !== undefined) out.serde = opts.serde;\n const r = opts?.retry;\n if (r) {\n if (r.maxAttempts !== undefined) out.maxRetryAttempts = r.maxAttempts;\n if (r.maxDuration !== undefined) out.maxRetryDuration = r.maxDuration;\n if (r.initialInterval !== undefined)\n out.initialRetryInterval = r.initialInterval;\n if (r.maxInterval !== undefined) out.maxRetryInterval = r.maxInterval;\n // `exponentiationFactor` is the aligned name; `intervalFactor` is the\n // deprecated alias, honored only as a fallback.\n const exponentiationFactor = r.exponentiationFactor ?? r.intervalFactor;\n if (exponentiationFactor !== undefined)\n out.retryIntervalFactor = exponentiationFactor;\n }\n return out;\n}\n\nfunction asTerminalError(reason: unknown): restate.TerminalError {\n if (reason instanceof restate.TerminalError) return reason;\n // Non-Terminal reason: wrap as CancelledError. The SDK's CancelledError\n // is the canonical type for \"invocation was cancelled\" — TerminalError\n // subclass with the proper error code (409). The original reason is\n // discarded; defensible since this branch should never fire in\n // production (cancellation rejections from the SDK are always Terminal).\n return new restate.CancelledError();\n}\n\n/**\n * Deterministic date methods that return journal-backed Futures.\n * Wraps the SDK's `ContextDate` (which returns Promises via internal\n * `ctx.run()` calls) so that gen-SDK user code can `yield*` them.\n */\nexport interface GenContextDate {\n now(): Future<number>;\n toJSON(): Future<string>;\n}\n\n/**\n * Client bundle bound to a specific scope, returned by\n * {@link RestateOperations.scope} (and the free-standing `scope`).\n *\n * Exposes the same `client`/`sendClient` overloads as the unscoped\n * variants — for services, no key; for objects/workflows, the key —\n * but every call/send routes within the bound scope.\n */\nexport interface ScopedOperations {\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): GenClient<H>;\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): GenClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): GenSendClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): GenSendClient<H>;\n}\n\nexport class RestateOperations {\n private readonly ctx: restate.internal.ContextInternal;\n private readonly sched: Scheduler;\n\n constructor(context: restate.Context, sched: Scheduler) {\n this.ctx = context as restate.internal.ContextInternal;\n this.sched = sched;\n }\n\n // Internal: wrap an SDK RestatePromise as a journal-backed Future.\n // Not part of the public surface — every primitive that needs it\n // (run/sleep/awakeable/typed clients/genericCall/workflowPromise)\n // funnels through here so the adapt + makeJournalFuture wiring\n // stays in one place.\n private toFuture<T>(p: restate.RestatePromise<T>): Future<T> {\n return this.sched.makeJournalFuture(adapt(p));\n }\n\n // ---- context properties (rand / date / console) ----\n\n get rand(): restate.Rand {\n return this.ctx.rand;\n }\n\n get date(): GenContextDate {\n return {\n now: () => this.toFuture(this.ctx.date.now() as RestatePromise<number>),\n toJSON: () =>\n this.toFuture(this.ctx.date.toJSON() as RestatePromise<string>),\n };\n }\n\n get console(): Console {\n return this.ctx.console;\n }\n\n isProcessing(): boolean {\n return this.ctx.isProcessing();\n }\n\n // ---- context-local storage ----\n // Delegate to the scheduler, which owns the single per-invocation bag.\n // Present here because `RestateOperations` is the current-fiber slot in\n // production; `contextLocal()` handles cast the slot to this shape.\n\n getLocal(key: symbol, fallback: unknown): unknown {\n return this.sched.getLocal(key, fallback);\n }\n\n setLocal(key: symbol, value: unknown): void {\n this.sched.setLocal(key, value);\n }\n\n // ---- journal-backed Futures ----\n\n /**\n * Run a side-effecting closure as a journal entry.\n *\n * The closure receives `{ signal }` — an AbortSignal that fires when\n * invocation cancellation arrives. Pass it into AbortSignal-aware\n * APIs (e.g. `fetch(url, { signal })`) to abort in-flight syscalls.\n *\n * `name` is the journal entry's stable identifier (must be\n * deterministic across replay). It can come from either:\n *\n * - `opts.name` — explicit override\n * - `action.name` — the function's own name (works for `function`\n * declarations and arrow functions assigned to a `const`,\n * since JS infers names from the binding site)\n *\n * If neither resolves, `run` throws.\n *\n * @example Named function — name derived\n * async function fetchUser({ signal }: RunActionOpts): Promise<User> {\n * const r = await fetch(`/users/${id}`, { signal });\n * return r.json();\n * }\n * yield* run(fetchUser);\n *\n * @example Named arrow — name derived from binding\n * const fetchUser = async ({ signal }: RunActionOpts) => { ... };\n * yield* run(fetchUser);\n *\n * @example Inline arrow — name explicit\n * yield* run(async ({ signal }) => fetch(url, { signal }), { name: \"fetch\" });\n *\n * @example With retry policy\n * yield* run(fetchUser, { retry: { maxAttempts: 3 } });\n *\n * Cancellation hygiene: if the closure throws while the signal is\n * aborted, we rethrow `signal.reason` (the original TerminalError)\n * instead of whatever the closure threw. This ensures the journal\n * entry records `TerminalError(CANCELLED)` rather than `AbortError`.\n */\n run<T>(action: RunAction<T>, opts?: RunOpts<T>): Future<T> {\n const name = resolveRunName(action, opts);\n // Per-fiber signal: a targeted `interrupt(task)` aborts only this\n // fiber's in-flight run; invocation cancellation / attempt-end still\n // cascade in (the fiber signal is a child of the scheduler signal).\n const wrapped = wrapActionForCancellation(\n this.sched.currentRunSignal(),\n action\n );\n return this.sched.makeJournalFuture(\n adapt(this.ctx.run(name, wrapped, toSdkRunOptions(opts)))\n );\n }\n\n sleep(duration: restate.Duration | number, name?: string): Future<void> {\n return this.sched.makeJournalFuture(adapt(this.ctx.sleep(duration, name)));\n }\n\n awakeable<T>(serde?: restate.Serde<T>): { id: string; promise: Future<T> } {\n const { id, promise } = this.ctx.awakeable(serde);\n return { id, promise: this.sched.makeJournalFuture(adapt(promise)) };\n }\n\n resolveAwakeable<T>(id: string, payload?: T, serde?: restate.Serde<T>) {\n this.ctx.resolveAwakeable(id, payload, serde);\n }\n\n rejectAwakeable(id: string, reason: string | restate.TerminalError) {\n this.ctx.rejectAwakeable(id, reason);\n }\n\n signal<T>(name: string, serde?: restate.Serde<T>): Future<T> {\n return this.sched.makeJournalFuture(adapt(this.ctx.signal(name, serde)));\n }\n\n attach<T>(\n invocationId: restate.InvocationId,\n serde?: restate.Serde<T>\n ): Future<T> {\n return this.sched.makeJournalFuture(\n adapt(this.ctx.attach(invocationId, serde))\n );\n }\n\n // ---- context accessor ----\n\n /**\n * Returns the current invocation's request metadata plus the optional\n * virtual-object / workflow key. The `key` field is only present when\n * the handler belongs to an object or workflow.\n */\n handlerRequest(): HandlerRequest {\n const req = this.ctx.request();\n const ctx = this.ctx;\n return {\n attemptHeaders: req.attemptHeaders,\n body: req.body,\n extraArgs: req.extraArgs,\n headers: req.headers,\n id: req.id,\n target: req.target,\n get key(): string | undefined {\n return (ctx as unknown as { key: string }).key;\n },\n scope: req.scope,\n idempotencyKey: req.idempotencyKey,\n limitKey: req.limitKey,\n };\n }\n\n // ---- typed clients (call + send) backed by call()/send() ----\n\n /**\n * Unified client for any Descriptor (service, object, or workflow).\n * Each method yields a Future<O> backed by call().\n * For services, key is not needed. For objects/workflows, pass the key.\n */\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): GenClient<H>;\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): GenClient<H>;\n client(def: Descriptor<string, any, any>, key?: string): GenClient<any> {\n return makeClient(def, key, (o) => this.call(o as any)) as any;\n }\n\n /**\n * Fire-and-forget send client for any Descriptor.\n * Each method returns an InvocationHandle synchronously.\n */\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): GenSendClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): GenSendClient<H>;\n sendClient(\n def: Descriptor<string, any, any>,\n key?: string\n ): GenSendClient<any> {\n return makeSendClient(def, key, (o, serde) =>\n this.send(o as any, serde)\n ) as any;\n }\n\n /**\n * Route all outgoing calls/sends through a named scope.\n *\n * Returns a bundle with the same `client`/`sendClient` overloads as the\n * unscoped variants; every call or send built from it carries the given\n * `scopeKey`. A scope is a sub-grouping of resources within the cluster\n * and becomes part of the target identity (it contributes to the\n * partition key, co-locating resources in the same scope).\n *\n * `scopeKey` must match `[a-zA-Z0-9_.-]`, 1..36 chars. Per-call\n * `limitKey` (via `Opts`/`SendOpts`) can only be used within a scope.\n *\n * @example\n * yield* scope(\"tenant-123\").client(Greeter).greet(name);\n * yield* scope(\"tenant-123\").client(Cart, \"cart-42\").add(item);\n * scope(\"tenant-123\").sendClient(Greeter).greet(name);\n */\n scope(scopeKey: string): ScopedOperations {\n return {\n client: (def: Descriptor<string, any, any>, key?: string) =>\n makeClient(def, key, (o) => this.call(o as any), scopeKey),\n sendClient: (def: Descriptor<string, any, any>, key?: string) =>\n makeSendClient(\n def,\n key,\n (o, serde) => this.send(o as any, serde),\n scopeKey\n ),\n } as ScopedOperations;\n }\n\n // ---- generic call/send (renamed from genericCall/genericSend) ----\n\n call<REQ = Uint8Array, RES = Uint8Array>(\n opts: restate.GenericCall<REQ, RES>\n ): ClientFuture<RES> {\n const restatePromise = this.ctx.genericCall<REQ, RES>(opts);\n const resultFuture = this.toFuture(restatePromise);\n const invocation = this.invocationReferenceFromHandle(\n restatePromise as unknown as restate.InvocationHandle,\n opts.outputSerde\n ) as Future<InvocationReference<RES>>;\n return Object.assign(resultFuture, { invocation }) as ClientFuture<RES>;\n }\n\n send<REQ = Uint8Array, RES = unknown>(\n opts: restate.GenericSend<REQ>,\n outputSerde?: restate.Serde<RES>\n ): Future<InvocationReference<RES>> {\n const handle = this.ctx.genericSend<REQ>(opts);\n return this.invocationReferenceFromHandle(handle, outputSerde) as Future<\n InvocationReference<RES>\n >;\n }\n\n // ---- invocation reference helpers ----\n\n invocationReferenceFromHandle<O>(\n handle: restate.InvocationHandle,\n outputSerde: restate.Serde<O> | undefined\n ): Future<InvocationReference<O>> {\n // handle.invocationId is Promise<InvocationId> typed, but under the hood\n // it is a RestatePromise — adapt it to a journal-backed Future.\n const idFuture = this.toFuture(\n handle.invocationId as unknown as restate.RestatePromise<restate.InvocationId>\n );\n return this.sched.spawn(\n gen(function* (): Generator<unknown, InvocationReference<O>, unknown> {\n const id = (yield* idFuture) as string;\n return new InvocationReferenceImpl<O>(id, outputSerde);\n })\n );\n }\n\n invocationSignal<T>(\n invocationId: restate.InvocationId,\n name: string,\n serde?: restate.Serde<T>\n ): SignalReference<T> {\n const internalCtx = this.ctx as unknown as restate.internal.ContextInternal;\n const ref = internalCtx.invocation(invocationId);\n return ref.signal<T>(name, serde) as SignalReference<T>;\n }\n\n // ---- cancel another invocation ----\n\n /**\n * Cancel another invocation by its id. To observe cancellation\n * arriving at *this* invocation, catch the `TerminalError` thrown by\n * the next `yield*` boundary or use the `signal` exposed inside\n * `ops.run` closures.\n */\n cancel(invocationId: restate.InvocationId): void {\n this.ctx.cancel(invocationId);\n }\n\n // ---- workflow durable promise ----\n\n /**\n * Workflow-bound durable promise. Use only inside a workflow handler\n * (the underlying context must be `WorkflowContext` or\n * `WorkflowSharedContext`). Returns a wrapper whose `peek`/`get`/\n * `resolve`/`reject` methods return Futures.\n */\n workflowPromise<T>(\n name: string,\n serde?: restate.Serde<T>\n ): GenDurablePromise<T> {\n const wfCtx = this.ctx as unknown as restate.WorkflowSharedContext;\n return wrapDurablePromise(wfCtx.promise<T>(name, serde), <U>(p: unknown) =>\n this.toFuture(p as restate.RestatePromise<U>)\n );\n }\n\n // ---- spawn ----\n\n /**\n * Register `op` as a fresh routine and return a `Future<T>` for its\n * eventual outcome. Eager: by the time `spawn` returns, the child is\n * already queued and will advance on the next scheduler tick — same\n * model as `run`/`sleep`/`awakeable`. The returned Future can be\n * yielded on, handed to combinators, or stored.\n *\n * A spawned routine still running when the main operation settles is\n * abandoned by default (its handler returns without it); pass\n * `{ onMainExit: \"join\" }` to `execute` to wait for it instead.\n *\n * Returns a `Task<T>` — a `Future<T>` plus `interrupt(err?)` to throw\n * into the routine at its next yield point.\n */\n spawn<T>(op: Operation<T>): Task<T> {\n return this.sched.spawn(op);\n }\n\n // ---- channels ----\n\n /**\n * Create a single-shot in-memory channel. Returns a Channel<T> with\n * `send(v)` (fire-and-forget, idempotent — first call settles, rest\n * are dropped) and `receive: Future<T>` (a stable settle-once Future,\n * the same handle on every access).\n *\n * Canonical use: cooperative cancellation. Spawn a routine that\n * selects over its work and `stop.receive`; the canceller calls\n * `stop.send()` to request termination. The receiver decides what\n * to do — return a partial result, do cleanup yields, ignore.\n *\n * Because `receive` is a stable, settle-once Future, multiple readers\n * all observe the same value (one-time broadcast) and the worker can\n * use it in every iteration of a select-loop without leaking orphan\n * receivers.\n *\n * Multi-event streams (producer-consumer, progress events) are NOT\n * supported — Channel is intentionally single-shot. A separate\n * primitive for that use case is yet to be designed.\n */\n channel<T>(): Channel<T> {\n return this.sched.makeChannel<T>();\n }\n\n // ---- state ----\n\n /**\n * Per-invocation read-write key-value store. Use from a handler whose\n * underlying context is ObjectContext or WorkflowContext.\n *\n * The optional `TState` generic gives keyof-checked names and per-key\n * value types:\n *\n * ops.state<{count: number; user: User}>()\n * // state.get(\"count\") → Future<number | null>\n *\n * Without it, names are `string` and values are inferred per call:\n *\n * ops.state()\n * // state.get<number>(\"count\") → Future<number | null>\n *\n * Calling write methods from a shared (read-only) context throws at\n * runtime — for shared handlers, use `sharedState()` below to get a\n * narrower type that drops the write methods.\n */\n state<TState extends TypedState = UntypedState>(): State<TState> {\n return makeState<TState>(\n this.ctx as unknown as restate.ObjectContext,\n this.sched,\n adapt\n );\n }\n\n /**\n * Per-invocation read-only key-value store. Use from a handler whose\n * underlying context is ObjectSharedContext or WorkflowSharedContext.\n *\n * Same `TState` generic as `state()`. Returns the read-only subset\n * (`get`, `keys`); attempting to call writes is a type error.\n */\n sharedState<TState extends TypedState = UntypedState>(): SharedState<TState> {\n return makeState<TState>(\n this.ctx as unknown as restate.ObjectSharedContext,\n this.sched,\n adapt\n );\n }\n\n // ---- combinators ----\n\n /**\n * Wait for every future to settle; return their values in input\n * order. Heterogeneous-tuple typing — `all([fA, fB])` where\n * `fA: Future<A>` and `fB: Future<B>` yields `Future<[A, B]>`.\n * Mirrors `Promise.all` from the standard lib.\n */\n all<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>> {\n return this.sched.all(futures);\n }\n\n /**\n * Return the first future to settle; losers continue running (until\n * the main operation settles — see `OnMainExit`) but their results\n * are discarded. Heterogeneous-tuple typing — `race([fA, fB])`\n * yields `Future<A | B>`. Mirrors `Promise.race`.\n */\n race<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>[number]> {\n return this.sched.race(futures);\n }\n\n /**\n * First-success combinator. Resolves with the first input that\n * succeeds (non-rejected); rejects with `AggregateError(errors)` when\n * every input rejects (including an empty input array). See `Promise.any`.\n *\n * Tuple-aware typing — `any([fA, fB])` where `fA: Future<A>` and\n * `fB: Future<B>` yields `Future<A | B>`.\n */\n any<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>[number]> {\n return this.sched.any(futures);\n }\n\n /**\n * Settle-all combinator. Resolves with an array of\n * `FutureSettledResult` in input order; never rejects. See\n * `Promise.allSettled`.\n *\n * Tuple-aware typing — `allSettled([fA, fB])` yields\n * `Future<[FutureSettledResult<A>, FutureSettledResult<B>]>`.\n */\n allSettled<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<{\n -readonly [P in keyof T]: FutureSettledResult<\n T[P] extends Future<infer U> ? U : never\n >;\n }> {\n return this.sched.allSettled(futures);\n }\n\n // Wait for one branch to settle, return its tag and the future itself.\n // The user unwraps the future after switching on the tag — `yield* r.future`\n // is effectively sync at that point since it's already settled.\n *select<B extends Record<string, Future<unknown>>>(\n branches: B\n ): Generator<unknown, SelectResult<B>, unknown> {\n return yield* selectOp(branches);\n }\n}\n\n// =============================================================================\n// Production execute() entry point.\n// =============================================================================\n\n/**\n * Options for {@link execute}.\n */\nexport type ExecuteOptions = SchedulerOptions;\n\n/**\n * Run a generator-based workflow against a Restate context.\n *\n * `op` is an `Operation<T>` — typically the result of\n * `gen(function*() { ... })`. Inside the generator body, reach for the\n * free-standing API (`run`, `sleep`, `all`, `state`, …) imported\n * from `@restatedev/restate-sdk-gen`. They read the active scheduler from a\n * synchronous current-fiber slot installed by `Fiber.advance`.\n *\n * `gen()` already takes a factory, so the same `Operation` is re-\n * iterable across multiple `execute()` calls — no need for a builder\n * lambda at this boundary.\n *\n * By default `execute` resolves as soon as the main operation settles;\n * spawned fibers (and race losers) still running at that point are\n * abandoned. Pass `{ onMainExit: \"join\" }` to instead keep driving\n * until every spawned fiber has finished.\n *\n * @example\n * execute(ctx, gen(function* () {\n * const greeting = yield* run(async () => \"hi\", { name: \"compose\" });\n * return greeting;\n * }));\n */\nexport async function execute<T>(\n context: restate.Context,\n op: Operation<T>,\n options?: ExecuteOptions\n): Promise<T> {\n // The attempt's lifecycle signal is the parent of the scheduler's\n // AbortSignal: when the current attempt completes (suspension,\n // stream close, success or failure), in-flight `run` closures\n // listening on the signal stop promptly instead of running on\n // detached.\n const sched = new SchedulerClass(\n defaultLib,\n context.request().attemptCompletedSignal,\n options\n );\n // Publish a private `RestateOperations` on the scheduler so\n // `Fiber.advance` can install it on the module-level current-fiber\n // slot read by the free-standing API.\n sched.contextSlot = new RestateOperations(context, sched);\n return sched.run(op);\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unnecessary-type-assertion */\n\nimport * as restate from \"@restatedev/restate-sdk\";\nimport type { StandardSchemaV1 } from \"@restatedev/restate-sdk-core\";\nimport {\n type HandlerDescriptor,\n type Descriptor,\n type ServiceDescriptor,\n type ObjectDescriptor,\n type WorkflowDescriptor,\n type ImplementedServiceDefinition,\n type ImplementedObjectDefinition,\n type ImplementedWorkflowDefinition,\n type ImplementedDefinition,\n makeHandlerDescriptor,\n serde,\n} from \"@restatedev/restate-sdk-core\";\nimport { execute } from \"./restate-operations.js\";\nimport { type Operation } from \"./operation.js\";\nimport { ServiceHandlerOpts } from \"@restatedev/restate-sdk\";\n\n// =============================================================================\n// Shared interface/descriptor layer — moved to @restatedev/restate-sdk-core and\n// re-exported here so this package's public API is unchanged.\n// =============================================================================\nexport type {\n HandlerDescriptor,\n Descriptor,\n ServiceDescriptor,\n ObjectDescriptor,\n WorkflowDescriptor,\n ImplementedServiceDefinition,\n ImplementedObjectDefinition,\n ImplementedWorkflowDefinition,\n ImplementedDefinition,\n};\n\n// =============================================================================\n// HandlerDef — result of serdes()\n// =============================================================================\n\n/** @internal\n * @internal - Wraps a generator function with optional serde. Produced by typed().\n * Discriminated by _genFn for runtime detection (distinct from bare gen fns,\n * which are plain functions rather than objects).\n */\nexport type HandlerDef<I = any, O = any> = {\n readonly _genFn: (input: I) => Operation<O>;\n} & HandlerDescriptor<I, O>;\n\n/** @internal */\nexport type EntryToDescriptor<E> =\n E extends HandlerDef<infer I, infer O>\n ? HandlerDescriptor<I, O>\n : E extends () => Operation<infer O>\n ? HandlerDescriptor<void, O> // no-arg generator → void input\n : E extends (input: infer I) => Operation<infer O>\n ? HandlerDescriptor<I, O>\n : HandlerDescriptor;\n\n/** Map a full handler map type to the corresponding descriptor map type */\nexport type HandlerDescriptors<\n H extends Record<string, HandlerOrHandlerDescriptor>,\n> = {\n [K in keyof H]: EntryToDescriptor<H[K]>;\n};\n\n// =============================================================================\n// Per-handler options\n// =============================================================================\n\n/** Options valid for all handler types. To set input and output serde, check {@link serdes()} */\nexport type GenHandlerOpts = Omit<\n ServiceHandlerOpts<unknown, unknown>,\n \"input\" | \"output\"\n>;\n\n/** Handler options for virtual object handlers */\nexport type GenObjectHandlerOpts = GenHandlerOpts & {\n /**\n * When true, the handler will be marked as shared.\n * Shared object handlers can only read state, not write it.\n */\n shared?: boolean;\n\n /**\n * When set to `true`, lazy state will be enabled for all invocations to this handler.\n *\n * *NOTE:* You can set this field only if you register this endpoint against restate-server >= 1.4,\n * otherwise the service discovery will fail.\n */\n enableLazyState?: boolean;\n};\n\n/** Handler options for workflow handlers (shared is implicit from name) */\nexport type GenWorkflowHandlerOpts = {\n /**\n * When set to `true`, lazy state will be enabled for all invocations to this handler.\n *\n * *NOTE:* You can set this field only if you register this endpoint against restate-server >= 1.4,\n * otherwise the service discovery will fail.\n */\n enableLazyState?: boolean;\n};\n\n// =============================================================================\n// Handler entry types\n// =============================================================================\n\n/** @internal */\nexport type AnyGenFn = (input: any) => Operation<any>;\n\n/** A handler entry: either a bare generator fn or the result of {@link serdes()} */\nexport type HandlerOrHandlerDescriptor = AnyGenFn | HandlerDef<any, any>;\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/** HandlerDef has _genFn as an object property; bare gen fns are plain functions */\nfunction isHandlerDef(\n entry: HandlerOrHandlerDescriptor\n): entry is HandlerDef<any, any> {\n return (\n typeof entry === \"object\" &&\n entry !== null &&\n typeof (entry as any)._genFn === \"function\"\n );\n}\n\nfunction extractEntry(entry: HandlerOrHandlerDescriptor): {\n genFn: AnyGenFn;\n inputSerde: restate.Serde<any> | undefined;\n outputSerde: restate.Serde<any> | undefined;\n} {\n if (isHandlerDef(entry)) {\n return {\n genFn: entry._genFn as AnyGenFn,\n inputSerde: entry._inputSerde,\n outputSerde: entry._outputSerde,\n };\n }\n return {\n genFn: entry as AnyGenFn,\n inputSerde: undefined,\n outputSerde: undefined,\n };\n}\n\n// =============================================================================\n// Handler definition helpers — produce HandlerDef for use in service/object/workflow\n// =============================================================================\n\n/** serdes(opts, fn) — explicit Serde per field */\nexport function serdes<I, O>(\n opts: { input: restate.Serde<I>; output: restate.Serde<O> },\n fn: (input: I) => Operation<O>\n): HandlerDef<I, O> {\n return {\n _genFn: fn as AnyGenFn,\n _inputSerde: opts.input,\n _outputSerde: opts.output,\n };\n}\n\n/** schemas(opts, fn) — Standard Schema (Zod, TypeBox, Valibot, …) per field */\nexport function schemas<\n SI extends StandardSchemaV1<any>,\n SO extends StandardSchemaV1<any>,\n>(\n opts: { input: SI; output: SO },\n fn: (\n input: StandardSchemaV1.InferOutput<SI>\n ) => Operation<StandardSchemaV1.InferOutput<SO>>\n): HandlerDef<\n StandardSchemaV1.InferOutput<SI>,\n StandardSchemaV1.InferOutput<SO>\n> {\n return {\n _genFn: fn as AnyGenFn,\n _inputSerde: serde.schema(opts.input),\n _outputSerde: serde.schema(opts.output),\n };\n}\n\n// =============================================================================\n// service() factory\n// =============================================================================\n\nexport function service<\n P extends string,\n H extends Record<string, HandlerOrHandlerDescriptor>,\n>(config: {\n name: P;\n description?: string;\n metadata?: Record<string, string>;\n handlers: H;\n options?: restate.ServiceOptions & {\n handlers?: Partial<Record<keyof H, GenHandlerOpts>>;\n };\n}): ImplementedServiceDefinition<P, HandlerDescriptors<H>> {\n const { name, description, metadata, handlers, options } = config;\n const { handlers: perHandlerOpts, ...serviceOpts } = options ?? {};\n\n const coreHandlers: Record<string, any> = {};\n const descriptors: Record<string, HandlerDescriptor> = {};\n\n for (const [handlerName, entry] of Object.entries(handlers)) {\n const { genFn, inputSerde, outputSerde } = extractEntry(entry);\n const handlerOpts =\n ((perHandlerOpts as any)?.[handlerName] as GenHandlerOpts) ?? {};\n\n coreHandlers[handlerName] = restate.handlers.handler(\n { input: inputSerde, output: outputSerde, ...handlerOpts } as any,\n async (ctx: restate.Context, input: any) => execute(ctx, genFn(input))\n );\n\n descriptors[handlerName] = makeHandlerDescriptor(inputSerde, outputSerde);\n }\n\n const coreDef = restate.service({\n name,\n handlers: coreHandlers as any,\n description,\n metadata,\n options: serviceOpts,\n });\n\n return Object.assign(coreDef, {\n _kind: \"service\" as const,\n _handlers: descriptors,\n }) as unknown as ImplementedServiceDefinition<P, HandlerDescriptors<H>>;\n}\n\n// =============================================================================\n// object() factory\n// =============================================================================\n\nexport function object<\n P extends string,\n H extends Record<string, HandlerOrHandlerDescriptor>,\n>(config: {\n name: P;\n description?: string;\n metadata?: Record<string, string>;\n handlers: H;\n options?: restate.ObjectOptions & {\n handlers?: Partial<Record<keyof H, GenObjectHandlerOpts>>;\n };\n}): ImplementedObjectDefinition<P, HandlerDescriptors<H>> {\n const { name, description, metadata, handlers, options } = config;\n const { handlers: perHandlerOpts, ...objectOpts } = options ?? {};\n\n const coreHandlers: Record<string, any> = {};\n const descriptors: Record<string, HandlerDescriptor> = {};\n\n for (const [handlerName, entry] of Object.entries(handlers)) {\n const { genFn, inputSerde, outputSerde } = extractEntry(entry);\n const handlerOpts: GenObjectHandlerOpts =\n ((perHandlerOpts as any)?.[handlerName] as GenObjectHandlerOpts) ?? {};\n const { shared, ...restOpts } = handlerOpts;\n\n const sdkOpts = {\n input: inputSerde,\n output: outputSerde,\n ...restOpts,\n } as any;\n const fn = async (\n ctx: restate.ObjectContext | restate.ObjectSharedContext,\n input: any\n ) => execute(ctx as restate.Context, genFn(input));\n\n coreHandlers[handlerName] = shared\n ? restate.handlers.object.shared(sdkOpts, fn as any)\n : restate.handlers.object.exclusive(sdkOpts, fn as any);\n\n descriptors[handlerName] = makeHandlerDescriptor(inputSerde, outputSerde);\n }\n\n const coreDef = restate.object({\n name,\n handlers: coreHandlers as any,\n description,\n metadata,\n options: objectOpts,\n });\n\n return Object.assign(coreDef, {\n _kind: \"object\" as const,\n _handlers: descriptors,\n }) as unknown as ImplementedObjectDefinition<P, HandlerDescriptors<H>>;\n}\n\n// =============================================================================\n// workflow() factory\n// =============================================================================\n\nexport function workflow<\n P extends string,\n H extends Record<string, HandlerOrHandlerDescriptor>,\n>(config: {\n name: P;\n description?: string;\n metadata?: Record<string, string>;\n handlers: H;\n options?: restate.WorkflowOptions & {\n handlers?: Partial<Record<keyof H, GenWorkflowHandlerOpts>>;\n };\n}): ImplementedWorkflowDefinition<P, HandlerDescriptors<H>> {\n const { name, description, metadata, handlers, options } = config;\n const { handlers: perHandlerOpts, ...workflowOpts } = options ?? {};\n\n const coreHandlers: Record<string, any> = {};\n const descriptors: Record<string, HandlerDescriptor> = {};\n\n for (const [handlerName, entry] of Object.entries(handlers)) {\n const { genFn, inputSerde, outputSerde } = extractEntry(entry);\n const handlerOpts =\n ((perHandlerOpts as any)?.[handlerName] as GenWorkflowHandlerOpts) ?? {};\n\n const sdkOpts = {\n input: inputSerde,\n output: outputSerde,\n ...handlerOpts,\n } as any;\n const fn = async (\n ctx: restate.WorkflowContext | restate.WorkflowSharedContext,\n input: any\n ) => execute(ctx as restate.Context, genFn(input));\n\n coreHandlers[handlerName] =\n handlerName === \"run\"\n ? restate.handlers.workflow.workflow(sdkOpts, fn as any)\n : restate.handlers.workflow.shared(sdkOpts, fn as any);\n\n descriptors[handlerName] = makeHandlerDescriptor(inputSerde, outputSerde);\n }\n\n const coreDef = restate.workflow({\n name,\n handlers: coreHandlers as any,\n description,\n metadata,\n options: workflowOpts,\n });\n\n return Object.assign(coreDef, {\n _kind: \"workflow\" as const,\n _handlers: descriptors,\n }) as unknown as ImplementedWorkflowDefinition<P, HandlerDescriptors<H>>;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-assignment */\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport {\n type HandlerDescriptor,\n type Descriptor,\n type ServiceDescriptor,\n type ObjectDescriptor,\n type WorkflowDescriptor,\n type ImplementedServiceDefinition,\n type ImplementedObjectDefinition,\n type ImplementedWorkflowDefinition,\n type ImplementedDefinition,\n type InferInput,\n type InferOutput,\n} from \"@restatedev/restate-sdk-core\";\nimport type { Operation } from \"./operation.js\";\nimport {\n type GenHandlerOpts,\n type GenObjectHandlerOpts,\n type GenWorkflowHandlerOpts,\n service as _defineService,\n object as _defineObject,\n workflow as _defineWorkflow,\n} from \"./define.js\";\n\n// The pure interface declarators (`json`/`serdes`/`schemas`) and the\n// `iface.service/object/workflow` factories now live in\n// @restatedev/restate-sdk-core and are re-exported through this package's\n// `iface` namespace (see index.ts). InferInput/InferOutput are re-exported for\n// API Extractor traceability.\nexport type { InferInput, InferOutput };\n\n// =============================================================================\n// implement() — bind generator handlers to a service interface (contract)\n// =============================================================================\n\n/** @internal */\nexport type ImplementHandlers<H extends Record<string, HandlerDescriptor>> = {\n [K in keyof H]: (input: InferInput<H[K]>) => Operation<InferOutput<H[K]>>;\n};\n\nexport function implement<\n P extends string,\n H extends Record<string, HandlerDescriptor>,\n>(\n iface: ServiceDescriptor<P, H>,\n config: {\n handlers: ImplementHandlers<H>;\n options?: restate.ServiceOptions & {\n handlers?: Partial<Record<keyof H, GenHandlerOpts>>;\n };\n }\n): ImplementedServiceDefinition<P, H>;\n\nexport function implement<\n P extends string,\n H extends Record<string, HandlerDescriptor>,\n>(\n iface: ObjectDescriptor<P, H>,\n config: {\n handlers: ImplementHandlers<H>;\n options?: restate.ObjectOptions & {\n handlers?: Partial<Record<keyof H, GenObjectHandlerOpts>>;\n };\n }\n): ImplementedObjectDefinition<P, H>;\n\nexport function implement<\n P extends string,\n H extends Record<string, HandlerDescriptor>,\n>(\n iface: WorkflowDescriptor<P, H>,\n config: {\n handlers: ImplementHandlers<H>;\n options?: restate.WorkflowOptions & {\n handlers?: Partial<Record<keyof H, GenWorkflowHandlerOpts>>;\n };\n }\n): ImplementedWorkflowDefinition<P, H>;\n\nexport function implement(\n iface: Descriptor<any, any, any>,\n config: { handlers: Record<string, any>; options?: any }\n): ImplementedDefinition<any, any, any> {\n // Build HandlerDef entries from interface descriptors + implementation fns\n const handlerEntries: Record<string, any> = {};\n for (const [name, desc] of Object.entries(\n iface._handlers as Record<string, HandlerDescriptor>\n )) {\n const genFn = config.handlers[name];\n if (!genFn) throw new Error(`implement(): missing handler \"${name}\"`);\n // Object with _genFn triggers isHandlerDef() check in define.ts factories\n handlerEntries[name] = {\n _genFn: genFn,\n _inputSerde: desc._inputSerde,\n _outputSerde: desc._outputSerde,\n };\n }\n\n if (iface._kind === \"service\") {\n return _defineService({\n name: iface.name,\n handlers: handlerEntries,\n options: config.options,\n }) as any;\n } else if (iface._kind === \"object\") {\n return _defineObject({\n name: iface.name,\n handlers: handlerEntries,\n options: config.options,\n }) as any;\n } else {\n return _defineWorkflow({\n name: iface.name,\n handlers: handlerEntries,\n options: config.options,\n }) as any;\n }\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */\n\n/**\n * @deprecated The `clients` ingress adapter is superseded by\n * `@restatedev/restate-sdk-clients`. The service interface / `Descriptor`\n * values produced by this package (`service`/`object`/`workflow`/`iface` /\n * `implement`) are now first-class inputs to that package's ingress client,\n * which reuses their declared serdes automatically:\n *\n * ```ts\n * import { connect } from \"@restatedev/restate-sdk-clients\";\n * const ingress = connect({ url });\n * await ingress.client(greeter).greet(req); // service\n * await ingress.client(counter, \"k\").add(1); // virtual object / workflow (with key)\n * ```\n *\n * Every export here now delegates to that client and will be removed in a\n * future release.\n */\n\nimport {\n Opts,\n SendOpts,\n type Send,\n type Ingress,\n type IngressClient,\n type IngressWorkflowClient,\n type IngressSendClient,\n type ConnectionOpts,\n type RetryPolicy,\n type RetryFailure,\n connect as clientsConnect,\n defaultShouldRetry,\n HttpCallError,\n} from \"@restatedev/restate-sdk-clients\";\nimport type { HandlerDescriptor, Descriptor } from \"./define.js\";\n\n// Re-export connect, Ingress, SendOpts so consumers can use clients.connect / clients.Ingress\nexport {\n Opts,\n SendOpts,\n defaultShouldRetry,\n HttpCallError,\n type ConnectionOpts,\n type RetryPolicy,\n type RetryFailure,\n type Ingress,\n type Send,\n type IngressClient,\n type IngressWorkflowClient,\n type IngressSendClient,\n};\n\n/**\n * @deprecated Use `connect` from `@restatedev/restate-sdk-clients` and its typed\n * client methods, e.g. `connect({ url }).serviceClient(def)`\n */\nexport function connect(opts: ConnectionOpts): GenIngress {\n return clientsConnect(opts);\n}\n\n/**\n * @deprecated Use `connect` from `@restatedev/restate-sdk-clients` and its typed\n * client methods, e.g. `connect({ url }).serviceClient(def)`\n */\nexport type GenIngress = Ingress;\n\n// =============================================================================\n// Typed ingress client types\n// =============================================================================\n\ntype InferInput<D> = D extends HandlerDescriptor<infer I, any> ? I : unknown;\ntype InferOutput<D> = D extends HandlerDescriptor<any, infer O> ? O : unknown;\n\n/**\n * Typed ingress call client — each method returns Promise<O>.\n *\n * @deprecated Use the client returned by `ingress.serviceClient(def)` /\n * `ingress.objectClient(def, key)` from `@restatedev/restate-sdk-clients`.\n */\nexport type IngressHandlerClient<H extends Record<string, HandlerDescriptor>> =\n {\n readonly [K in keyof H]: (\n input: InferInput<H[K]>,\n opts?: Opts<InferInput<H[K]>, InferOutput<H[K]>>\n ) => Promise<InferOutput<H[K]>>;\n };\n\n/**\n * Typed ingress send client — each method returns Promise<Send>.\n *\n * @deprecated Use the client returned by `ingress.serviceSendClient(def)` /\n * `ingress.objectSendClient(def, key)` from `@restatedev/restate-sdk-clients`.\n */\nexport type IngressSendHandlerClient<\n H extends Record<string, HandlerDescriptor>,\n> = {\n readonly [K in keyof H]: [InferInput<H[K]>] extends [void]\n ? (opts?: SendOpts<void>) => Promise<Send>\n : (\n input: InferInput<H[K]>,\n opts?: SendOpts<InferInput<H[K]>>\n ) => Promise<Send>;\n};\n\n// =============================================================================\n// client / sendClient — thin wrappers over the regular ingress client.\n// =============================================================================\n\n/**\n * @deprecated Call the regular ingress client directly: `ingress.client(def)`\n * for a service, or `ingress.client(def, key)` for a virtual object / workflow.\n */\nexport function client<H extends Record<string, HandlerDescriptor>>(\n ingress: GenIngress,\n def: Descriptor<string, H, \"service\">\n): IngressHandlerClient<H>;\nexport function client<H extends Record<string, HandlerDescriptor>>(\n ingress: GenIngress,\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n): IngressHandlerClient<H>;\nexport function client(\n ingress: GenIngress,\n def: Descriptor<string, any, any>,\n key?: string\n): IngressHandlerClient<any> {\n return (key === undefined\n ? ingress.client(def as any)\n : ingress.client(def as any, key)) as unknown as IngressHandlerClient<any>;\n}\n\n/**\n * @deprecated Call the regular ingress client directly: `ingress.sendClient(def)`\n * for a service, or `ingress.sendClient(def, key)` for a virtual object / workflow.\n */\nexport function sendClient<H extends Record<string, HandlerDescriptor>>(\n ingress: GenIngress,\n def: Descriptor<string, H, \"service\">\n): IngressSendHandlerClient<H>;\nexport function sendClient<H extends Record<string, HandlerDescriptor>>(\n ingress: GenIngress,\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n): IngressSendHandlerClient<H>;\nexport function sendClient(\n ingress: GenIngress,\n def: Descriptor<string, any, any>,\n key?: string\n): IngressSendHandlerClient<any> {\n return (key === undefined\n ? ingress.sendClient(def as any)\n : ingress.sendClient(\n def as any,\n key\n )) as unknown as IngressSendHandlerClient<any>;\n}\n\n/**\n * @deprecated Use `ingress.scope(scopeKey)` from\n * `@restatedev/restate-sdk-clients` and its `client`/`sendClient` methods.\n */\nexport interface ScopedGenIngress {\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): IngressHandlerClient<H>;\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): IngressHandlerClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): IngressSendHandlerClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): IngressSendHandlerClient<H>;\n}\n\n/**\n * @deprecated Use `ingress.scope(scopeKey)` from\n * `@restatedev/restate-sdk-clients`, then `.client(def)` / `.sendClient(def)`\n * on the returned scoped ingress.\n */\nexport function scope(ingress: GenIngress, scopeKey: string): ScopedGenIngress {\n const scoped = ingress.scope(scopeKey);\n return {\n client: (def: Descriptor<string, any, any>, key?: string) =>\n (key === undefined\n ? scoped.client(def as any)\n : scoped.client(def as any, key)) as unknown,\n sendClient: (def: Descriptor<string, any, any>, key?: string) =>\n (key === undefined\n ? scoped.sendClient(def as any)\n : scoped.sendClient(def as any, key)) as unknown,\n } as ScopedGenIngress;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Internal operations\n// =============================================================================\n//\n// Free-standing functions that are deliberately NOT part of the main\n// API surface (`free.ts` / top-level `index.ts` exports). They expose\n// sharp tools whose misuse leads straight to non-determinism errors,\n// so they live behind the `internal` namespace as an \"I know what I'm\n// doing\" gate:\n//\n// import { internal } from \"@restatedev/restate-sdk-gen\";\n// if (internal.isProcessing()) { ... }\n\nimport { peekCurrent } from \"./current.js\";\nimport { RestateOperations } from \"./restate-operations.js\";\n\n/**\n * Whether the current invocation is in the processing phase (as opposed\n * to replaying its journal). Aligns with the core SDK's\n * `ContextInternal.isProcessing()`.\n *\n * Returns `true`/`false` when called inside an active fiber backed by a\n * real Restate context, and `undefined` when there is no such context\n * (outside `execute()`, or in scheduler-only tests with no SDK context).\n *\n * **WARNING**: this is the same mechanism `ctx.console` uses to decide\n * whether to log during replay. Do **not** use it to influence control\n * flow — doing so will **surely** lead to non-determinism errors. It is\n * intended for observability concerns only (logging, metrics).\n *\n * @experimental\n */\nexport function isProcessing(): boolean | undefined {\n const current = peekCurrent();\n return current instanceof RestateOperations\n ? current.isProcessing()\n : undefined;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Public API.\n\nexport type { Channel } from \"./channel.js\";\nexport type { GenClient, GenSendClient, ClientFuture } from \"./clients.js\";\nexport type { GenDurablePromise } from \"./durable-promise.js\";\nexport type {\n InvocationReference,\n SignalReference,\n} from \"./invocation-reference.js\";\nexport {\n all,\n allSettled,\n any,\n attach,\n awakeable,\n call,\n cancel,\n channel,\n client,\n date,\n handlerRequest,\n invocation,\n logger,\n race,\n rand,\n rejectAwakeable,\n resolveAwakeable,\n run,\n scope,\n send,\n sendClient,\n sharedState,\n signal,\n sleep,\n spawn,\n state,\n workflowPromise,\n} from \"./free.js\";\n\nexport type {\n Future,\n FutureFulfilledResult,\n FutureRejectedResult,\n FutureSettledResult,\n FutureValue,\n FutureValues,\n} from \"./future.js\";\nexport { gen, type Operation, select, type SelectResult } from \"./operation.js\";\nexport { contextLocal, type ContextLocal } from \"./context.js\";\nexport { type Task, InterruptedError } from \"./task.js\";\nexport {\n execute,\n type ExecuteOptions,\n type GenContextDate,\n type RetryOptions,\n type RunAction,\n type RunActionOpts,\n type RunOpts,\n type ScopedOperations,\n wrapActionForCancellation,\n type HandlerRequest,\n} from \"./restate-operations.js\";\nexport type { OnMainExit, SchedulerOptions } from \"./scheduler.js\";\nexport type { SharedState, State, TypedState, UntypedState } from \"./state.js\";\n\n// Service/object/workflow definition API\nexport {\n serdes,\n schemas,\n service,\n object,\n workflow,\n type Descriptor,\n type HandlerDescriptor,\n type HandlerOrHandlerDescriptor,\n type HandlerDescriptors,\n type ServiceDescriptor,\n type ObjectDescriptor,\n type WorkflowDescriptor,\n type ImplementedServiceDefinition,\n type ImplementedObjectDefinition,\n type ImplementedWorkflowDefinition,\n type ImplementedDefinition,\n type GenHandlerOpts,\n type GenObjectHandlerOpts,\n type GenWorkflowHandlerOpts,\n} from \"./define.js\";\n\n// Interface / implement pattern.\n// The declarators/factories (`service`/`object`/`workflow`/`json`/`serdes`/\n// `schemas`/`shared`) live in @restatedev/restate-sdk-core; `implement` is\n// generator-specific and lives here. Merge them under one `iface` namespace.\nexport { implement } from \"./interface.js\";\nimport { iface as _coreIface } from \"@restatedev/restate-sdk-core\";\nimport { implement as _implement } from \"./interface.js\";\nexport const iface = { ..._coreIface, implement: _implement };\n\n// Ingress adapters, exported as `clients` namespace\nimport * as _ingress from \"./ingress.js\";\nexport { _ingress as clients };\n\n// Internal functions\nexport * as internal from \"./internal-operations.js\";\n\n// External types that appear in our public API surface — re-exported for consumers\nexport { serde } from \"@restatedev/restate-sdk-core\";\nexport type {\n StandardSchemaV1,\n Serde,\n VirtualObjectDefinitionFrom,\n VirtualObject,\n Service,\n ServiceDefinition,\n ServiceDefinitionFrom,\n Workflow,\n WorkflowDefinition,\n WorkflowDefinitionFrom,\n VirtualObjectDefinition,\n Duration,\n StandardTypedV1,\n ServiceInterface,\n SerdeType,\n} from \"@restatedev/restate-sdk-core\";\n\nexport type { ContextDate, Rand } from \"@restatedev/restate-sdk\";\n\n// Internal types exposed only for API Extractor traceability — not part of the public API\n/** @internal */\nexport type { EntryToDescriptor, AnyGenFn, HandlerDef } from \"./define.js\";\n/** @internal */\nexport type {\n ImplementHandlers,\n InferInput,\n InferOutput,\n} from \"./interface.js\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["CURRENT: unknown","id: string","_outputSerde?: restate.Serde<O>","serde","serde","leafOp: PrimitiveOp<T>","resume: Settled | null","next: IteratorResult<unknown, unknown>","outcome: Settled | null","backing: Backing<unknown>","promises: PromiseSource[]","settled: Settled","out: unknown[]","errors: unknown[]","items: PromiseSource[]","raceWinner: { i: number } & Settled","errSettled: Settled","settled: Settled","adapt","serde","call","send","parameter: unknown","opts:\n | ClientCallOptions<unknown, unknown>\n | ClientSendOptions<unknown>\n | undefined","defaultLib: AwaitableLib","signal","out: restate.RunOptions<T>","serde","invocation","selectOp","SchedulerClass","serde","coreHandlers: Record<string, any>","descriptors: Record<string, HandlerDescriptor>","handlerEntries: Record<string, any>","contractHandlerOpts: Record<string, Record<string, unknown>>","iface","mergedHandlerOpts: Record<string, Record<string, unknown>>","merged: Record<string, unknown>","_defineService","_defineObject","_defineWorkflow","connect","clientsConnect","client","sendClient","scope","_coreIface","_implement"],"sources":["../src/current.ts","../src/invocation-reference.ts","../src/free.ts","../src/operation.ts","../src/context.ts","../src/task.ts","../src/future.ts","../src/abort.ts","../src/fiber.ts","../src/channel.ts","../src/scheduler.ts","../src/state.ts","../src/clients.ts","../src/durable-promise.ts","../src/default-lib.ts","../src/restate-operations.ts","../src/define.ts","../src/interface.ts","../src/ingress.ts","../src/internal-operations.ts","../src/index.ts"],"sourcesContent":["/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Synchronous current-fiber slot.\n// =============================================================================\n//\n// A module-level pointer to the active `RestateOperations`, set on\n// entry to `Fiber.advance()` and cleared in its `finally`. Free-standing\n// API functions (`sleep`, `run`, `all`, …) read it to reach the\n// scheduler/context without an explicit `ops` parameter.\n//\n// Why this is safe without AsyncLocalStorage: user generators yield —\n// they do not `await`. `iterator.next()` returns control synchronously\n// to `Fiber.advance`, so the slot is \"owned\" only during the synchronous\n// span between `setCurrent` and `clearCurrent`. Concurrent `execute()`\n// calls in the same Node process interleave only at scheduler-level\n// `await` boundaries (the main-loop race), never in the middle of a\n// fiber's sync body — Node never preempts sync JS.\n//\n// Failure mode: a free function called while no fiber is advancing\n// (module init, an `ops.run` async closure that resolves later, a\n// timer firing) reads `null` and throws. Loud and immediate; never\n// silent corruption.\n//\n// The slot value is typed `unknown` here to avoid a circular import on\n// `RestateOperations` (which itself imports the scheduler graph). Free\n// functions cast back via the typed `currentOps()` helper that lives\n// next to `RestateOperations`.\n\nlet CURRENT: unknown = null;\n\n/**\n * Save the previous slot, install `value` as the current. Returns the\n * previous value so `clearCurrent` can restore it (supports nested\n * scheduler invocations on the same thread, even though we don't expect\n * any in production).\n */\nexport function setCurrent(value: unknown): unknown {\n const prev = CURRENT;\n CURRENT = value;\n return prev;\n}\n\n/** Restore a slot previously captured by `setCurrent`. */\nexport function clearCurrent(prev: unknown): void {\n CURRENT = prev;\n}\n\n/**\n * Read the slot without throwing — returns `null` when no fiber is\n * currently advancing. For callers that need to distinguish \"inside a\n * fiber\" from \"outside\" rather than fail loudly (e.g. the internal\n * `isProcessing()` probe).\n */\nexport function peekCurrent(): unknown {\n return CURRENT;\n}\n\n/**\n * Read the slot, throwing if no fiber is currently advancing. Callers\n * cast the return type — the slot is intentionally `unknown` here so\n * this module stays free of cycles.\n */\nexport function getCurrent(): unknown {\n if (CURRENT === null) {\n throw new Error(\n \"@restatedev/restate-sdk-gen: free-standing API called outside an active fiber. \" +\n \"Call from inside `execute(ctx, gen(function*() { ... }))`.\"\n );\n }\n return CURRENT;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport type { Future } from \"./future.js\";\nimport { getCurrent } from \"./current.js\";\nimport type { RestateOperations } from \"./restate-operations.js\";\n\n/** Synchronous handle for resolving or rejecting a signal on a target invocation */\nexport interface SignalReference<T> {\n resolve(payload?: T): void;\n reject(reason: string | restate.TerminalError): void;\n}\n\n/**\n * A typed reference to a running invocation. Returned by `sendClient()` methods\n * (wrapped in `Future<InvocationReference<O>>`), or created via `invocation(id)`.\n *\n * - `attach()` returns a `Future<O>` with the serde from the original descriptor.\n * - `signal()` sends a named signal to the target invocation.\n * - `cancel()` cancels the target invocation.\n */\nexport interface InvocationReference<O = unknown> {\n readonly id: string;\n attach(serde?: restate.Serde<O>): Future<O>;\n signal<T = unknown>(\n name: string,\n serde?: restate.Serde<T>\n ): SignalReference<T>;\n cancel(): void;\n}\n\nexport class InvocationReferenceImpl<\n O = unknown,\n> implements InvocationReference<O> {\n constructor(\n readonly id: string,\n private readonly _outputSerde?: restate.Serde<O>\n ) {}\n\n attach(serde?: restate.Serde<O>): Future<O> {\n return (getCurrent() as RestateOperations).attach<O>(\n this.id as restate.InvocationId,\n serde ?? this._outputSerde\n );\n }\n\n signal<T = unknown>(\n name: string,\n serde?: restate.Serde<T>\n ): SignalReference<T> {\n return (getCurrent() as RestateOperations).invocationSignal<T>(\n this.id as restate.InvocationId,\n name,\n serde\n );\n }\n\n cancel(): void {\n (getCurrent() as RestateOperations).cancel(this.id as restate.InvocationId);\n }\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */\n\n// Free-standing API\n// =============================================================================\n//\n// Module-level functions that mirror `RestateOperations` methods but\n// read the active operations from the synchronous current-fiber slot\n// (`current.ts`). User code inside a `gen(function*() { ... })` body\n// can call these directly — no `ops` parameter needed.\n//\n// Each function is a one-liner that resolves the slot via `currentOps()`\n// and delegates to the underlying `RestateOperations` method, so this\n// file stays in lockstep with the class without duplicating logic.\n//\n// Usage:\n//\n// import { gen, execute, sleep, run, all } from \"@restatedev/restate-sdk-gen\";\n//\n// const myWorkflow = gen(function*() {\n// const a = run(() => fetchA(), { name: \"a\" });\n// const b = run(() => fetchB(), { name: \"b\" });\n// const [av, bv] = yield* all([a, b]);\n// yield* sleep(100);\n// return av + bv;\n// });\n//\n// // Handler:\n// execute(ctx, myWorkflow);\n//\n// `select` is already a free function in `operation.ts` and requires no\n// slot — it yields a marker the scheduler dispatches. It is re-exported\n// from `index.ts`.\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport type { Future, FutureValues, FutureSettledResult } from \"./future.js\";\nimport type { Channel } from \"./channel.js\";\nimport type { State, SharedState, TypedState, UntypedState } from \"./state.js\";\nimport type { GenDurablePromise } from \"./durable-promise.js\";\nimport type {\n GenContextDate,\n RestateOperations,\n RunAction,\n RunOpts,\n ScopedOperations,\n} from \"./restate-operations.js\";\nimport type { Descriptor, HandlerDescriptor } from \"./define.js\";\nimport type { ClientFuture, GenClient, GenSendClient } from \"./clients.js\";\nimport type { Operation } from \"./operation.js\";\nimport type { Task } from \"./task.js\";\nimport {\n InvocationReferenceImpl,\n type InvocationReference,\n} from \"./invocation-reference.js\";\nimport { getCurrent } from \"./current.js\";\nimport type { HandlerRequest } from \"./restate-operations.js\";\n\n/**\n * Read the active `RestateOperations` from the current-fiber slot.\n * Throws if called outside a fiber's synchronous advance span (e.g.,\n * at module init or inside an `ops.run` async closure that resolved\n * after the fiber returned).\n */\nexport function currentOps(): RestateOperations {\n return getCurrent() as RestateOperations;\n}\n\n// ---- context properties (rand / date / console) ----\n\nexport const rand = (): restate.Rand => currentOps().rand;\n\nexport const date = (): GenContextDate => currentOps().date;\n\nexport const logger = (): Console => currentOps().console;\n\n// ---- context accessor ----\n\n/**\n * Returns the current invocation's request metadata plus the optional\n * virtual-object / workflow key. The `key` field is only present when\n * the handler belongs to an object or workflow.\n */\nexport const handlerRequest = (): HandlerRequest =>\n currentOps().handlerRequest();\n\n// ---- journal-backed Futures ----\n\n/**\n * Run a side-effecting closure as a journal entry. See\n * `RestateOperations.run` for full semantics.\n *\n * `name` is derived from `action.name` (works for named functions and\n * arrow functions assigned to a `const`) or specified explicitly via\n * `opts.name`. If neither resolves, throws.\n */\nexport const run = <T>(action: RunAction<T>, opts?: RunOpts<T>): Future<T> =>\n currentOps().run(action, opts);\n\nexport const sleep = (\n duration: restate.Duration | number,\n name?: string\n): Future<void> => currentOps().sleep(duration, name);\n\nexport const awakeable = <T>(\n serde?: restate.Serde<T>\n): { id: string; promise: Future<T> } => currentOps().awakeable(serde);\n\nexport const resolveAwakeable = <T>(\n id: string,\n payload?: T,\n serde?: restate.Serde<T>\n): void => currentOps().resolveAwakeable(id, payload, serde);\n\nexport const rejectAwakeable = (\n id: string,\n reason: string | restate.TerminalError\n): void => currentOps().rejectAwakeable(id, reason);\n\nexport const signal = <T>(name: string, serde?: restate.Serde<T>): Future<T> =>\n currentOps().signal(name, serde);\n\nexport const attach = <T>(\n invocationId: restate.InvocationId,\n serde?: restate.Serde<T>\n): Future<T> => currentOps().attach(invocationId, serde);\n\n// ---- unified typed clients ----\n\nexport function client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n): GenClient<H>;\nexport function client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n): GenClient<H>;\nexport function client(\n def: Descriptor<\n string,\n Record<string, HandlerDescriptor>,\n \"service\" | \"object\" | \"workflow\"\n >,\n key?: string\n): GenClient<Record<string, HandlerDescriptor>> {\n return currentOps().client(def as Descriptor<string, any, any>, key as any);\n}\n\nexport function sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n): GenSendClient<H>;\nexport function sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n): GenSendClient<H>;\nexport function sendClient(\n def: Descriptor<\n string,\n Record<string, HandlerDescriptor>,\n \"service\" | \"object\" | \"workflow\"\n >,\n key?: string\n): GenSendClient<Record<string, HandlerDescriptor>> {\n return currentOps().sendClient(\n def as Descriptor<string, any, any>,\n key as any\n );\n}\n\n/**\n * Route all outgoing calls/sends through a named scope. Returns a bundle\n * exposing the same `client`/`sendClient` overloads, with every call/send\n * carrying `scopeKey`. See {@link RestateOperations.scope} for full semantics.\n *\n * @example\n * yield* scope(\"tenant-123\").client(Greeter).greet(name);\n * yield* scope(\"tenant-123\").client(Cart, \"cart-42\").add(item);\n * scope(\"tenant-123\").sendClient(Greeter).greet(name);\n */\nexport const scope = (scopeKey: string): ScopedOperations =>\n currentOps().scope(scopeKey);\n\n// ---- generic call/send (renamed from genericCall/genericSend) ----\n\nexport const call = <REQ = Uint8Array, RES = Uint8Array>(\n c: restate.GenericCall<REQ, RES>\n): ClientFuture<RES> => currentOps().call<REQ, RES>(c);\n\nexport const send = <REQ = Uint8Array, RES = unknown>(\n c: restate.GenericSend<REQ>,\n outputSerde?: restate.Serde<RES>\n): Future<InvocationReference<RES>> =>\n currentOps().send<REQ, RES>(c, outputSerde);\n\n// ---- invocation reference ----\n\n/**\n * Create an InvocationReference from a known invocation ID (e.g. retrieved from state).\n * `attach()` and `cancel()` on the result use the current fiber slot like all free functions.\n */\nexport function invocation<O = unknown>(\n id: string,\n opts?: { outputSerde?: restate.Serde<O> }\n): InvocationReference<O> {\n return new InvocationReferenceImpl<O>(id, opts?.outputSerde);\n}\n\n// ---- cancel another invocation ----\n\nexport const cancel = (invocationId: restate.InvocationId): void =>\n currentOps().cancel(invocationId);\n\n// ---- channels & state ----\n\nexport const channel = <T>(): Channel<T> => currentOps().channel<T>();\n\nexport const state = <\n TState extends TypedState = UntypedState,\n>(): State<TState> => currentOps().state<TState>();\n\nexport const sharedState = <\n TState extends TypedState = UntypedState,\n>(): SharedState<TState> => currentOps().sharedState<TState>();\n\n// ---- workflow durable promise ----\n\nexport const workflowPromise = <T>(\n name: string,\n serde?: restate.Serde<T>\n): GenDurablePromise<T> => currentOps().workflowPromise<T>(name, serde);\n\n// ---- combinators ----\n\n/**\n * Wait for every future to settle; return their values in input order.\n * Heterogeneous-tuple typing — `all([fA, fB])` where `fA: Future<A>`\n * and `fB: Future<B>` yields `Future<[A, B]>`. Mirrors `Promise.all`.\n */\nexport const all = <const T extends readonly Future<unknown>[] | []>(\n futures: T\n): Future<FutureValues<T>> => currentOps().all(futures);\n\n/**\n * Return the first future to settle; losers continue running (until\n * the main operation settles — see `OnMainExit`) but their results are\n * discarded. Heterogeneous-tuple typing — `race([fA, fB])` yields\n * `Future<A | B>`. Mirrors `Promise.race`.\n */\nexport const race = <const T extends readonly Future<unknown>[] | []>(\n futures: T\n): Future<FutureValues<T>[number]> => currentOps().race(futures);\n\n/**\n * First-to-succeed wins (non-rejected). Rejects with `AggregateError(errors)`\n * when every input rejects (including the empty input case). Tuple-aware —\n * `any([fA, fB])` yields `Future<A | B>`. Mirrors `Promise.any`.\n */\nexport const any = <const T extends readonly Future<unknown>[] | []>(\n futures: T\n): Future<FutureValues<T>[number]> => currentOps().any(futures);\n\n/**\n * Wait for every future to settle; never rejects. Tuple-aware —\n * `allSettled([fA, fB])` yields\n * `Future<[FutureSettledResult<A>, FutureSettledResult<B>]>`.\n * Mirrors `Promise.allSettled`.\n */\nexport const allSettled = <const T extends readonly Future<unknown>[] | []>(\n futures: T\n): Future<{\n -readonly [P in keyof T]: FutureSettledResult<\n T[P] extends Future<infer U> ? U : never\n >;\n}> => currentOps().allSettled(futures);\n\n/**\n * Register `op` as a fresh routine and return a `Task<T>` for its\n * eventual outcome — a `Future<T>` plus `interrupt(err?)` to throw into\n * the routine at its next yield point. Eager — the child is already in\n * flight by the time `spawn` returns. A spawned routine still running\n * when the main operation settles is abandoned by default (see\n * `OnMainExit`). See `RestateOperations.spawn` for full semantics.\n */\nexport const spawn = <T>(op: Operation<T>): Task<T> => currentOps().spawn(op);\n\n// `select` is already a free function in `operation.ts` (it yields a\n// marker the scheduler dispatches). It is re-exported from `index.ts`\n// directly.\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Operation<T>\n// =============================================================================\n//\n// Operation<T> is a lazy, one-shot description of work that produces a T.\n// Constructed via gen() for user-authored bodies, or by primitives that\n// yield a marker the scheduler dispatches on (Leaf, AwaitRace).\n//\n// The reuse trap from naked-generator designs is closed at the type level:\n// gen() takes a factory `() => Generator<...>`, not a generator object, so\n// `gen(bare())` doesn't typecheck — you have to write `gen(() => bare())`,\n// which produces a fresh body per `[Symbol.iterator]()` call.\n\nimport type { Future } from \"./future.js\";\nimport type { Settled } from \"./scheduler-types.js\";\n\nexport const opTag = Symbol(\"restateOperation\");\n\nexport interface Operation<T> {\n [Symbol.iterator](): Iterator<unknown, T, unknown>;\n}\n\n// =============================================================================\n// Primitive nodes — only the scheduler interprets these.\n// =============================================================================\n\nexport type LeafNode<T> = {\n readonly _tag: \"Leaf\";\n readonly future: Future<T>;\n};\n\nexport type AwaitRaceResult = { index: number; settled: Settled };\n\nexport type AwaitRace = {\n readonly _tag: \"AwaitRace\";\n readonly futures: ReadonlyArray<Future<unknown>>;\n};\n\nexport interface PrimitiveOp<T> extends Operation<T> {\n readonly [opTag]: LeafNode<T> | AwaitRace;\n}\n\nexport function makePrimitive<T>(node: LeafNode<T>): PrimitiveOp<T> {\n const op = {\n [opTag]: node,\n *[Symbol.iterator]() {\n return (yield op) as T;\n },\n };\n return op;\n}\n\n// AwaitAny is module-internal — used by combinator implementations inside\n// this package (race, select). It never appears in the user API.\nexport function awaitRace<T>(\n futures: ReadonlyArray<Future<T>>\n): Operation<AwaitRaceResult> {\n const op = {\n [opTag]: { _tag: \"AwaitRace\", futures } as AwaitRace,\n *[Symbol.iterator]() {\n return (yield op) as AwaitRaceResult;\n },\n };\n return op as unknown as Operation<AwaitRaceResult>;\n}\n\n// =============================================================================\n// gen — the only way to lift a generator function into an Operation.\n// =============================================================================\n\nexport function gen<T>(\n body: () => Generator<unknown, T, unknown>\n): Operation<T> {\n return { [Symbol.iterator]: body };\n}\n\n// =============================================================================\n// select — wait for one branch to settle, return its tag and the future.\n// =============================================================================\n//\n// The user unwraps the future after switching on the tag — `yield* r.future`\n// is effectively sync at that point since it's already settled. select\n// doesn't propagate the value or the error: telling you which branch is\n// ready is its only job.\n\nexport type SelectResult<B extends Record<string, Future<unknown>>> = {\n [K in keyof B]: { tag: K; future: B[K] };\n}[keyof B];\n\nexport function* select<B extends Record<string, Future<unknown>>>(\n branches: B\n): Generator<unknown, SelectResult<B>, unknown> {\n const tags = Object.keys(branches) as Array<keyof B & string>;\n const futures = tags.map((t) => branches[t]) as Future<unknown>[];\n const result = yield* awaitRace(futures);\n const tag = tags[result.index]!;\n return { tag, future: branches[tag] } as SelectResult<B>;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Context-local storage\n// =============================================================================\n//\n// Ambient, invocation-scoped key/value storage — a typed bag carried by\n// the current invocation that generator code running under it (the main\n// body, nested `gen` helpers, and spawned routines) can read and write\n// without threading a parameter through every call.\n//\n// `get`/`set` must run on the fiber's synchronous advance span, i.e.\n// directly from generator code — NOT from inside an `ops.run` action\n// closure or any other async callback, which run off-advance (after the\n// fiber has parked) and throw \"outside an active fiber\". To capture a\n// journaled value into a slot, set it in the body from the run's result:\n// `slot.set(yield* run(() => fetchTenant(), { name: \"tenant\" }))`, not\n// `run(() => { slot.set(...) })`.\n//\n// const tenant = contextLocal<string>(); // define once, anywhere\n//\n// const handler = gen(function* () {\n// tenant.set(yield* run(() => resolveTenant(), { name: \"tenant\" }));\n// yield* doDeeplyNestedWork(); // reads tenant.get() without a param\n// });\n//\n// Scope and lifetime: ONE bag per `execute()` call. Every fiber that\n// runs under that invocation — the main routine, everything it\n// `spawn`s, and the synthetic fibers behind combinator fallbacks —\n// shares the same bag (this is global-per-invocation, not per-fiber:\n// there is no inheritance or per-strand isolation). The bag lives only\n// in memory for the duration of the invocation; it is never journaled\n// or persisted.\n//\n// Determinism: a value re-derived by deterministic workflow code is\n// itself deterministic, so it survives replay/suspension unchanged —\n// the workflow re-runs from the top and re-`set`s the same values, in\n// the same order (fibers advance one at a time, in a replay-stable\n// order). The same rule as a plain local variable applies: do not store\n// a value you obtained non-deterministically (a bare `Date.now()`, a\n// raw network result) unless it came through `run`/the journal first.\n//\n// NOT durable state: `contextLocal` is in-memory scratch for the current\n// invocation. For values that must outlive the invocation (and be\n// readable by later invocations of the same virtual object), use\n// `state()` / `sharedState()`, which the SDK persists.\n//\n// Footgun: because the bag is shared, two concurrently-interleaving\n// fibers that write the *same* key clobber each other — a reader sees\n// whichever fiber advanced last. That is fine for the dominant use\n// (set once near the top, read everywhere); only reach past it if you\n// need per-strand isolation, which this global flavor does not provide.\n\nimport { getCurrent } from \"./current.js\";\n\n/**\n * The slice of the current-fiber slot that backs context-local storage.\n * Both `Scheduler` (the slot in unit tests) and `RestateOperations` (the\n * slot in production) satisfy it structurally — `RestateOperations`\n * delegates to its scheduler, which owns the single per-invocation Map.\n * Kept here, cast from the `unknown` slot, so this module stays free of a\n * scheduler/operations import cycle (mirrors how `free.ts` reaches `ops`).\n */\ninterface ContextStore {\n /** Read `key`'s value, or `fallback` if it has never been set. */\n getLocal(key: symbol, fallback: unknown): unknown;\n /** Write `key`'s value for the rest of the invocation. */\n setLocal(key: symbol, value: unknown): void;\n}\n\n/**\n * A handle to one invocation-scoped slot. Mint it once with\n * {@link contextLocal} (at module scope is fine — minting touches no\n * fiber), then `get`/`set` it from inside the workflow body.\n */\nexport interface ContextLocal<T> {\n /**\n * Read this slot's value for the current invocation. Returns the\n * value previously {@link set} during this invocation, or the default\n * passed to {@link contextLocal} (or `undefined` if none) when it has\n * not been set. Must be called from generator code on the fiber's\n * synchronous span (a `gen` body running under `execute`); calling it\n * from an `ops.run` closure or other async callback throws.\n */\n // Arrow-property fields (not method shorthand) on purpose: method\n // parameters are checked bivariantly, which would let `ContextLocal<Dog>`\n // be treated as `ContextLocal<Animal>` and a widened `set` poison a `get`\n // that still claims `Dog`. As function-typed properties, `set`'s\n // parameter is contravariant, making the handle correctly invariant in T.\n get: () => T;\n /**\n * Set this slot's value for the rest of the current invocation,\n * visible to every fiber under it. Must be called from generator code\n * on the fiber's synchronous span; calling it from an `ops.run`\n * closure or other async callback throws.\n */\n set: (value: T) => void;\n}\n\n/**\n * Create a context-local storage slot.\n *\n * The returned handle's `get`/`set` read and write a bag scoped to the\n * current invocation (`execute` call) and shared by every fiber under\n * it. Each `contextLocal()` call mints an independent slot — two handles\n * never collide, even with the same value type.\n *\n * Minting is pure (it allocates a unique key and captures the default),\n * so a slot can be defined at module scope and reused across\n * invocations; only `get`/`set` touch the current fiber.\n *\n * @example A required value with a default\n * const region = contextLocal(\"us-east-1\"); // ContextLocal<string>\n * // inside a handler:\n * region.set(\"eu-west-1\");\n * const r = region.get(); // string\n *\n * @example An optional value (no default)\n * const traceId = contextLocal<string>(); // ContextLocal<string | undefined>\n * const t = traceId.get(); // string | undefined\n */\nexport function contextLocal<T>(defaultValue: T): ContextLocal<T>;\nexport function contextLocal<T>(): ContextLocal<T | undefined>;\nexport function contextLocal<T>(defaultValue?: T): ContextLocal<T | undefined> {\n // Identity-only key: the bag is keyed by this symbol, never serialized,\n // and lives only in-memory per invocation — so symbol identity (stable\n // within a process, irrelevant across processes) is the right key.\n const key = Symbol(\"restate.contextLocal\");\n return {\n get: () =>\n (getCurrent() as ContextStore).getLocal(key, defaultValue) as\n | T\n | undefined,\n set: (value: T | undefined) =>\n (getCurrent() as ContextStore).setLocal(key, value),\n };\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Task<T>\n// =============================================================================\n//\n// The handle returned by `spawn`. A `Task<T>` is a `Future<T>` (yieldable,\n// composable into all/race/any/allSettled exactly like any other Future)\n// plus a control method: `interrupt(err?)`, which throws `err` into the\n// spawned routine at its next yield point and aborts its in-flight `run`\n// I/O.\n//\n// Only `spawn` produces a Task — combinator results (race/all/…) stay plain\n// Future<T>, since their journal fast path has no fiber to target and their\n// fallback runs SDK-authored loop code with no user-owned try/catch.\n\nimport type { Future } from \"./future.js\";\n\n/**\n * A handle to a spawned routine: its `Future<T>` plus `interrupt`.\n */\nexport interface Task<T> extends Future<T> {\n /**\n * Throw `err` into the spawned routine at its next yield point, and\n * abort its in-flight `run` I/O. `err` is delivered verbatim — the\n * routine's own try/catch may catch and recover (interrupt is\n * swallowable). When `err` is omitted, an {@link InterruptedError} is\n * thrown instead.\n *\n * Interrupt only affects a still-running routine: interrupting one\n * that has already settled is a no-op. Under the default\n * `onMainExit: \"abandon\"`, interrupting a child and then returning\n * from the main operation delivers nothing — the scheduler stops\n * before the child is driven. To run the child's `catch`/`finally`,\n * interrupt then `yield*` the task (interrupt-then-join).\n *\n * Call from within the workflow (an advancing fiber), so the delivery\n * point is deterministic across replay.\n */\n interrupt(err?: unknown): void;\n}\n\n/**\n * The default error thrown by `interrupt()` when no explicit error is\n * given. A plain `Error` (not a `TerminalError`) — interrupt imposes no\n * blast radius of its own; if you want an uncaught interrupt to fail the\n * invocation terminally, pass a `TerminalError` to `interrupt(err)`.\n */\nexport class InterruptedError extends Error {\n constructor(message = \"Task interrupted\") {\n super(message);\n this.name = \"InterruptedError\";\n }\n}\n\n/**\n * Augment a spawned routine's Future with `interrupt`, producing a Task.\n * Takes a plain `(err) => void` callback (the fiber's `interrupt`) rather\n * than the Fiber itself, so this module stays free of scheduler/fiber\n * imports. `Object.assign` mutates and returns the same Future object —\n * its `[Symbol.iterator]` and symbol-keyed backing are untouched, so the\n * Task remains fully yieldable and composable.\n */\nexport function makeTask<T>(\n future: Future<T>,\n interruptFiber: (err: unknown) => void\n): Task<T> {\n const interrupt = (err?: unknown): void =>\n interruptFiber(err === undefined ? new InterruptedError() : err);\n return Object.assign(future as object, { interrupt }) as Task<T>;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Future<T>\n// =============================================================================\n//\n// One user-visible type. Two internal backings, distinguished only inside\n// combinator implementations and the scheduler. The user sees uniform\n// behavior — all Futures yield and compose the same way regardless of\n// backing.\n//\n// Two kinds of backing:\n//\n// - \"journal\" — wraps a remote promise (RestatePromise in production,\n// TestPromise in tests). Resolution is observed by Restate's runtime\n// and journaled. Goes through the scheduler's main-loop `lib.race`.\n//\n// - \"local\" — wraps an in-memory `WaitTarget`. Resolution lives only\n// in the JS heap; never touches the journal, never goes through\n// `lib.race`. Fibers (settled by their iterator finishing) and\n// Channels (settled by `send()`) both implement `WaitTarget`.\n// Future in-memory primitives — semaphores, latches — slot in here\n// too without further changes to the scheduler/fiber.\n\nimport type { Awaitable } from \"./awaitable.js\";\nimport {\n type Operation,\n type PrimitiveOp,\n type LeafNode,\n makePrimitive,\n} from \"./operation.js\";\nimport type { Settled, Waiter } from \"./scheduler-types.js\";\n\n// `futureBacking` is the symbol slot where each Future stashes its backing\n// (journal-backed promise or local WaitTarget). NOT exported from index.ts:\n// the symbol-keyed property is an implementation detail, accessed only by\n// the scheduler/fiber via the internal `getBacking` helper below.\nexport const futureBacking = Symbol(\"restateFutureBacking\");\n\n// Nominal brand that prevents arbitrary iterables (e.g. `Future<T>[]`) from\n// accidentally satisfying `Future<unknown>`. The symbol is NOT exported, so\n// external code cannot construct a value that satisfies the property without\n// a deliberate type assertion.\ndeclare const futureBrand: unique symbol;\n\nexport type JournalBacking<T> = {\n readonly kind: \"journal\";\n readonly promise: Awaitable<T>;\n};\n\n/**\n * In-memory completion source. Anything that gets settled exactly once\n * and notifies waiters can be a `WaitTarget` — fibers, channels, and\n * any future in-memory primitive we add (latch, semaphore, …).\n *\n * Contract mirrors `Fiber`'s lifecycle methods:\n * - `isDone()` and `settledValue()` for a synchronous short-circuit\n * when the target is already settled at park time.\n * - `awaitCompletion(waiter)` registers a one-shot callback;\n * returns the settled value if already done so the caller can\n * short-circuit without queuing.\n */\nexport interface WaitTarget<T> {\n isDone(): boolean;\n settledValue(): Settled;\n awaitCompletion(waiter: Waiter): Settled | null;\n // The generic parameter T is documentation; the concrete settle path\n // already carries the value via `Settled`. Kept on the interface so\n // call-site types match `Fiber<T>` / `ChannelImpl<T>` cleanly.\n readonly _phantom?: T;\n}\n\nexport type LocalBacking<T> = {\n readonly kind: \"local\";\n readonly target: WaitTarget<T>;\n};\n\nexport type Backing<T> = JournalBacking<T> | LocalBacking<T>;\n\n// Public Future is opaque — only the iterable shape is visible. The\n// `[futureBacking]: Backing<T>` storage lives on the internal type, kept\n// off the published API so we don't drag JournalBacking/LocalBacking/\n// WaitTarget/Awaitable/Settled/Waiter into the public surface.\nexport interface Future<T> extends Operation<T> {\n readonly [futureBrand]: unknown;\n}\n\n/**\n * Internal shape — Future plus its symbol-keyed backing slot. Kept off\n * the public `Future<T>` interface so `Backing`/`JournalBacking`/\n * `LocalBacking`/`WaitTarget` (and their transitive deps) don't leak\n * into the published `.d.ts`.\n */\nexport interface FutureWithBacking<T> extends Future<T> {\n readonly [futureBacking]: Backing<T>;\n}\n\n/** Like `FutureWithBacking<T>` but narrowed to a journal backing. */\nexport interface JournalBackedFuture<T> extends Future<T> {\n readonly [futureBacking]: JournalBacking<T>;\n}\n\n/**\n * Internal accessor — read the backing off a Future. Only the scheduler\n * and fiber call this; user code never sees Backing.\n */\nexport function getBacking<T>(f: Future<T>): Backing<T> {\n return (f as FutureWithBacking<T>)[futureBacking];\n}\n\nexport function makeFuture<T>(backing: Backing<T>): Future<T> {\n // Each Future carries a single Leaf op that the scheduler dispatches on.\n // Reused across [Symbol.iterator]() calls since it's stateless — just a\n // back-reference to this future for the scheduler to inspect.\n //\n // The forward-reference inside the iterator closure is safe: the\n // generator body only runs when [Symbol.iterator]() is iterated, which\n // can only happen after this function returns and `leafOp` is bound.\n const future = {\n [futureBacking]: backing,\n *[Symbol.iterator]() {\n return (yield leafOp) as T;\n },\n } as unknown as FutureWithBacking<T>;\n const leafOp: PrimitiveOp<T> = makePrimitive<T>({\n _tag: \"Leaf\",\n future,\n } as LeafNode<T>);\n return future;\n}\n\nexport function isJournalBacked<T>(f: Future<T>): f is JournalBackedFuture<T> {\n return getBacking(f).kind === \"journal\";\n}\n\n// =============================================================================\n// Helper types for heterogeneous combinator inputs.\n// =============================================================================\n//\n// `all([fA, fB, fC])` where each Future has a different value type\n// should yield `[A, B, C]`, not `(A | B | C)[]`. Mirrors the standard\n// lib's `Promise.all` pattern (see `lib.es2015.iterable.d.ts`):\n//\n// all<T extends readonly unknown[] | []>(values: T):\n// Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>\n//\n// Same idea here, but unwrapping `Future<U>` to `U` instead of\n// awaiting a Promise.\n\n/** Extract the value type from a `Future<U>`; `never` for non-Futures. */\nexport type FutureValue<F> = F extends Future<infer U> ? U : never;\n\n/**\n * Map a tuple of Futures to the tuple of their value types.\n * For `[Future<A>, Future<B>]` produces `[A, B]`.\n * For an unbounded `Future<X>[]` produces `X[]`.\n */\nexport type FutureValues<T extends readonly Future<unknown>[] | []> = {\n -readonly [P in keyof T]: T[P] extends Future<infer U> ? U : never;\n};\n\n// =============================================================================\n// FutureSettledResult variants — re-declared here with `reason: unknown`\n// instead of the std-lib's `reason: any`, which leaks `any` into allSettled's\n// return type and every caller that pattern-matches on the result.\n// =============================================================================\n\nexport interface FutureFulfilledResult<T> {\n readonly status: \"fulfilled\";\n readonly value: T;\n}\n\nexport interface FutureRejectedResult {\n readonly status: \"rejected\";\n readonly reason: unknown;\n}\n\nexport type FutureSettledResult<T> =\n | FutureFulfilledResult<T>\n | FutureRejectedResult;\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Linked AbortControllers.\n// =============================================================================\n//\n// A child AbortController whose signal aborts when its parent fires.\n// Used at two levels: the scheduler links its controller to the SDK's\n// attempt signal, and each fiber links its run-closure controller to the\n// scheduler's current signal — so invocation cancellation / attempt-end\n// cascade into in-flight `run` closures, while a targeted `interrupt`\n// can abort just one fiber's controller.\n\n/**\n * Create a controller whose signal is a child of `parent`: pre-aborted\n * if the parent has already fired, otherwise aborted the moment it does.\n *\n * The subscription uses `{ once, signal: c.signal }` so it self-detaches\n * on either exit — when the parent fires (`once`) or when this controller\n * is aborted by some other path (`signal`). A controller that is retired\n * and replaced therefore drops its listener immediately, so at most one\n * listener per child lives on the parent at a time — no accumulation\n * across cancel/recover or interrupt/recover cycles.\n */\nexport function linkAbortController(parent: AbortSignal): AbortController {\n const c = new AbortController();\n if (parent.aborted) {\n c.abort(parent.reason);\n } else {\n parent.addEventListener(\"abort\", () => c.abort(parent.reason), {\n once: true,\n signal: c.signal,\n });\n }\n return c;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Fiber<T>\n// =============================================================================\n//\n// A single strand of cooperative execution. Owns its iterator, its\n// lifecycle state (ready / parked / done), and its waiter list. The\n// scheduler orchestrates many fibers: keeping a ready queue, polling\n// parked fibers' sources, telling fibers to advance.\n//\n// Design boundary:\n//\n// Fiber owns: iterator, state transitions, dispatch of yielded\n// Leaf/AwaitRace ops, waiter notification.\n// Scheduler owns: the set of live fibers, the ready queue, the\n// Awaitable lib (race/all primitives), the main loop,\n// and cancellation broadcast.\n//\n// Communication is narrow:\n//\n// Scheduler → Fiber: new Fiber(op, sched), fiber.advance(),\n// fiber.wake(resume), fiber.parkedSources(),\n// fiber.awaitCompletion(waiter), fiber.isDone(),\n// fiber.settledValue().\n// Fiber → Scheduler: sched.markReady(this), sched.markDone(this).\n//\n// Invariants (the rules that make the rest reason-about-able):\n//\n// I1. A generator step runs ONLY inside `advance`, which the scheduler\n// calls ONLY from `drainReady`. `wake`, source `fire` callbacks,\n// and `finish`'s waiter notifications never run a step — they only\n// set state to `ready` and enqueue. So at most one fiber's body\n// runs at any instant (cooperative, single-threaded).\n// I2. `wake` is the sole transition into `ready`, and it bumps `epoch`\n// — the park-episode id. A waiter registered while parked is valid\n// only for that episode; once the fiber wakes (epoch advances) the\n// waiter is void. `epochGuarded` enforces this.\n// I3. A parked fiber normally leaves `parked` only when one of its own\n// sources fires. `interrupt`/cancellation are the exceptions: they\n// wake it OUT OF BAND, reusing the same resume path. The epoch\n// guard (stale waiters) and the `wokenDuringStep` check in\n// `advance` (self-interrupt) exist solely to keep those out-of-band\n// wakes safe.\n// I4. Journal-source fires need no epoch guard: the scheduler\n// re-collects parked sources fresh every tick, so a journal source\n// fires only in the tick it was collected, before the owner can\n// move on. Local waiters (channels, sibling fibers) are pruned by\n// nothing, so they MUST be epoch-guarded.\n\nimport type { Operation, PrimitiveOp, LeafNode } from \"./operation.js\";\nimport { opTag } from \"./operation.js\";\nimport type { Future, Backing, WaitTarget } from \"./future.js\";\nimport { getBacking } from \"./future.js\";\nimport type { Settled, PromiseSource, Waiter } from \"./scheduler-types.js\";\nimport { setCurrent, clearCurrent } from \"./current.js\";\nimport { linkAbortController } from \"./abort.js\";\n\n/**\n * Narrow interface a Fiber needs from its scheduler. Avoids a wide\n * coupling to Scheduler's full API; Fiber only ever calls these.\n */\nexport interface SchedulerOps {\n markReady(f: Fiber<unknown>): void;\n markDone(f: Fiber<unknown>): void;\n /**\n * The \"current fiber\" slot — the value installed by `execute()` as\n * the active `RestateOperations`. `Fiber.advance` publishes this to\n * the module-level slot so free-standing API functions can read it.\n * Typed `unknown` to avoid cycles with `restate-operations.ts`.\n */\n readonly contextSlot: unknown;\n /**\n * The scheduler's current AbortSignal. A fiber's per-fiber run signal\n * is a child of this, so invocation cancellation / attempt-end cascade\n * into in-flight `run` closures (see `Fiber.runSignal`).\n */\n readonly abortSignal: AbortSignal;\n}\n\ntype FiberState =\n | { kind: \"ready\"; resume: Settled | null }\n | { kind: \"parked\"; promises: PromiseSource[] }\n | { kind: \"done\"; settled: Settled };\n\nexport class Fiber<T = unknown> implements WaitTarget<T> {\n private readonly it: Iterator<unknown, unknown, unknown>;\n private readonly sched: SchedulerOps;\n private state: FiberState = { kind: \"ready\", resume: null };\n private waiters: Waiter[] = [];\n /**\n * Monotonic park-episode id, bumped on every `wake` (invariant I2).\n * Consumed by `epochGuarded` (waiter validity) and `wokenDuringStep`\n * (self-interrupt detection). Generalizes the old per-AwaitRace `won`\n * flag into a persistent, per-fiber guard.\n */\n private epoch = 0;\n /**\n * Whether the generator has been started (`it.next()` called at least\n * once). `it.throw()` on a not-yet-started generator propagates the\n * error out *without* running any body code, bypassing the routine's\n * own try/catch/finally — so an interrupt delivered before the first\n * advance must prime the generator first (see `stepIterator`).\n */\n private started = false;\n /**\n * Lazily-created AbortController for this fiber's `run` closures. Born\n * a child of the scheduler's current signal (so invocation cancellation\n * / attempt-end abort it) and aborted directly by `interrupt`. Recreated\n * when aborted, so cleanup `run`s after a swallowed interrupt see a\n * fresh, unaborted signal. Null until the fiber first needs a run signal.\n */\n private runController: AbortController | null = null;\n /**\n * Spawn-tree links. `parent` is the fiber that was advancing when this\n * one was created; `children` are the fibers it spawned (including the\n * synth fibers behind combinator fallbacks). `interrupt` cascades down\n * `children`. On `finish`, a fiber's still-live children are re-homed\n * onto its `parent` (not dropped) so the subtree stays connected to a\n * live ancestor and a later cascade still reaches them — `parent` is\n * therefore reassignable as ancestors complete.\n */\n private parent: Fiber<unknown> | null;\n private readonly children = new Set<Fiber<unknown>>();\n\n constructor(\n op: Operation<T>,\n sched: SchedulerOps,\n parent: Fiber<unknown> | null = null\n ) {\n this.it = op[Symbol.iterator]() as Iterator<unknown, unknown, unknown>;\n this.sched = sched;\n this.parent = parent;\n parent?.children.add(this as Fiber<unknown>);\n }\n\n // ---- lifecycle queries ----\n\n isDone(): boolean {\n return this.state.kind === \"done\";\n }\n\n /**\n * For a fiber known to be done, return its settled outcome. Throws\n * if called on a non-done fiber — callers must check `isDone()` first\n * (or use `awaitCompletion` for the polymorphic version).\n */\n settledValue(): Settled {\n if (this.state.kind !== \"done\") {\n throw new Error(\"Fiber.settledValue called on non-done fiber\");\n }\n return this.state.settled;\n }\n\n /**\n * Returns the parked sources this fiber is currently racing against.\n * Empty if the fiber is parked only on routine waiters (e.g.,\n * waiting on a sibling fiber to finish), or in any non-parked state.\n * The scheduler reads these to assemble its main-loop race.\n */\n parkedSources(): readonly PromiseSource[] {\n return this.state.kind === \"parked\" ? this.state.promises : [];\n }\n\n /**\n * \"I want to be notified when this fiber is done.\" If the fiber is\n * already done, returns its settled outcome immediately (caller\n * should NOT also expect the waiter to be invoked). Otherwise\n * returns null and queues the waiter for invocation when the fiber\n * eventually finishes.\n */\n awaitCompletion(waiter: Waiter): Settled | null {\n if (this.state.kind === \"done\") return this.state.settled;\n this.waiters.push(waiter);\n return null;\n }\n\n // ---- driving ----\n\n /**\n * Wake this fiber with a resume value. Transitions to ready and\n * notifies the scheduler. May be called from any state except done\n * (waking a done fiber is a programming error and is ignored\n * defensively).\n *\n * Bumps the park epoch so any waiters left registered on the targets\n * of the park we're leaving become stale no-ops (see `epoch`).\n */\n wake(resume: Settled | null): void {\n if (this.state.kind === \"done\") return;\n this.epoch++;\n this.state = { kind: \"ready\", resume };\n this.sched.markReady(this);\n }\n\n /**\n * Wrap a handler as a waiter that fires only while the fiber is still\n * in the park episode that registered it (see `epoch`, invariant I2).\n * A waiter left on a target after the fiber moved on — a re-park after\n * interrupt, or a losing race source — becomes a no-op. This is the\n * single mechanism behind both the AwaitRace \"first source wins\" dedup\n * and the cross-episode stale-waiter guard.\n */\n private epochGuarded(handler: (s: Settled) => void): Waiter {\n const at = this.epoch;\n return (s) => {\n if (this.epoch !== at) return;\n handler(s);\n };\n }\n\n /**\n * Whether a re-entrant `wake` fired during the step that began at\n * `epochBefore` — i.e. the fiber interrupted *itself* while advancing\n * (the only wake that can target the currently-advancing fiber). It\n * leaves a fresh resume in `this.state` to deliver at this yield rather\n * than parking on the op the body just produced.\n */\n private wokenDuringStep(epochBefore: number): boolean {\n return this.epoch !== epochBefore && this.state.kind === \"ready\";\n }\n\n /**\n * The AbortSignal handed to this fiber's `run` closures. Lazily\n * created as a child of the scheduler's current signal, so invocation\n * cancellation and attempt-end abort it like before; additionally,\n * `interrupt` aborts it directly to stop just this fiber's in-flight\n * I/O. Recreated once aborted, so a `run` issued after a swallowed\n * interrupt (or after cancellation recovery) gets a fresh signal.\n */\n runSignal(): AbortSignal {\n if (this.runController === null || this.runController.signal.aborted) {\n this.runController = linkAbortController(this.sched.abortSignal);\n }\n return this.runController.signal;\n }\n\n /**\n * Throw `err` into this fiber at its next yield point, and abort its\n * in-flight `run` I/O.\n *\n * Two effects: (1) abort the per-fiber run signal so an in-flight\n * `run(fetch(url, { signal }))` stops promptly — harmless if the fiber\n * has no live controller; the next `runSignal()` makes a fresh one for\n * post-interrupt cleanup. (2) wake the fiber with a failure resume so\n * `stepIterator` delivers `it.throw(err)` at the next advance — the\n * fiber's own try/catch may catch and recover (interrupt is\n * swallowable / non-sticky). A done fiber is left untouched (`wake`\n * no-ops). Same machinery as the cancellation fan-out, scoped to one\n * fiber.\n *\n * Self-interrupt (a fiber interrupting its own task while advancing)\n * is uniform: the re-entrant `wake` fires during the fiber's own\n * step, and `advance` detects the epoch bump and delivers the throw at\n * the fiber's next yield rather than parking (see `advance`). If the\n * body returns before reaching another yield, the self-interrupt is\n * moot — there is no yield point to throw at.\n */\n interrupt(err: unknown): void {\n this.runController?.abort(err);\n this.wake({ ok: false, e: err });\n // Cascade down the spawn subtree: a task's interrupt also interrupts\n // every routine it spawned (transitively). Synchronous and in-memory,\n // issued from a fiber advance — same determinism as a single\n // interrupt. The walk doesn't mutate `children` (interrupt only\n // wakes; finish/prune happens later in a drain), so iterating is safe.\n // The cascade is a single snapshot: routines a descendant spawns\n // *after* this fires (e.g. in its own interrupt-catch) are not\n // retroactively interrupted — interrupt is one-shot and non-sticky.\n for (const child of this.children) child.interrupt(err);\n }\n\n /**\n * Drive the fiber's iterator until it parks (yields a primitive\n * whose dispatch ends with the fiber waiting on a source) or\n * finishes (returns or throws).\n *\n * No-op if the fiber is not in the ready state — protects against\n * stale entries in the scheduler's ready queue.\n */\n advance(): void {\n if (this.state.kind !== \"ready\") return;\n // Publish the scheduler's RestateOperations slot to the module-level\n // pointer that free-standing API functions (sleep, run, all, …)\n // read. The slot lifetime is exactly the synchronous span of this\n // method; restored in `finally` so concurrent schedulers (different\n // execute() calls) don't clobber each other.\n const prevSlot = setCurrent(this.sched.contextSlot);\n try {\n let resume: Settled | null = this.state.resume;\n while (true) {\n // Snapshot the epoch around the step. A re-entrant `wake` during\n // user code (the fiber interrupting *itself* — the only way a\n // wake can target the fiber that is currently advancing) bumps\n // the epoch and installs a fresh resume in `this.state`. Stale\n // epoch-guarded waiters from a prior park return early without\n // waking, so they never bump it here — an epoch change across\n // the step means, unambiguously, a self-interrupt.\n const epochBefore = this.epoch;\n let next: IteratorResult<unknown, unknown>;\n try {\n next = stepIterator(this.it, resume, this.started);\n } catch (e) {\n this.finish({ ok: false, e });\n return;\n }\n this.started = true;\n if (next.done) {\n // The body returned before reaching another yield, so a\n // self-interrupt has no yield point to land on and is moot.\n this.finish({ ok: true, v: next.value });\n return;\n }\n\n // Self-interrupt during the step: deliver its resume at this\n // yield point instead of parking on the op the body just yielded.\n if (this.wokenDuringStep(epochBefore)) {\n resume = this.state.resume;\n continue;\n }\n\n const op = next.value as PrimitiveOp<unknown>;\n const node = op[opTag];\n // Each branch returns null to mean \"I parked, the fiber is\n // suspended\" or a Settled to mean \"resume the iterator with\n // this value.\" Leaf and AwaitRace may or may not park\n // depending on whether their target is already settled.\n let outcome: Settled | null;\n switch (node._tag) {\n case \"Leaf\":\n outcome = this.parkOnLeaf(node);\n break;\n case \"AwaitRace\":\n outcome = this.parkOnAwaitRace(node.futures);\n break;\n }\n\n if (outcome === null) return;\n resume = outcome;\n }\n } finally {\n clearCurrent(prevSlot);\n }\n }\n\n // ---- yield dispatch ----\n\n /**\n * Park on a single Future, or short-circuit if the Future is already\n * settled. Returns the Settled value to feed back into the iterator\n * if a short-circuit is possible (routine-backed future whose target\n * already finished); returns null if the fiber is parked and the\n * caller should suspend.\n */\n private parkOnLeaf(leaf: LeafNode<unknown>): Settled | null {\n const backing: Backing<unknown> = getBacking(leaf.future);\n if (backing.kind === \"journal\") {\n // Journal fires need no epoch guard (invariant I4): the scheduler\n // re-collects parked sources fresh each tick, so this source only\n // fires in the tick it was collected, before the fiber can move on.\n this.state = {\n kind: \"parked\",\n promises: [{ promise: backing.promise, fire: (s) => this.wake(s) }],\n };\n return null;\n }\n // Local-backed: ask the target (fiber, channel, …) for its settled\n // outcome (sync short-circuit) or register an epoch-guarded waiter —\n // the target never prunes it, so if we're interrupted and re-park it\n // must not wake the moved-on fiber.\n const settled = backing.target.awaitCompletion(\n this.epochGuarded((s) => this.wake(s))\n );\n if (settled !== null) return settled;\n this.state = { kind: \"parked\", promises: [] };\n return null;\n }\n\n /**\n * Park on the first-to-settle of a list of Futures, or short-circuit\n * if any source is already settled. Returns `{index, settled}`\n * (wrapped as Settled) on short-circuit, or null if parked.\n *\n * On the parked path, every source registers a one-shot fire\n * callback that wakes the fiber with `{index, settled}`. The epoch\n * guard ensures only the first source to settle wakes the fiber\n * (`wake` bumps the epoch, so any later same-tick fire sees a stale\n * epoch and no-ops) and that a waiter surviving an interrupt-and-\n * re-park can't fire onto the moved-on fiber. Local sources (fibers,\n * channels) park on the target's waiter list; journal sources race in\n * the main loop's race promise.\n */\n private parkOnAwaitRace(\n futures: ReadonlyArray<Future<unknown>>\n ): Settled | null {\n // Sync-check first: a local source whose target is already done\n // wins immediately. Journal sources can't be sync-checked — they\n // always defer to the race.\n for (let i = 0; i < futures.length; i++) {\n const b = getBacking(futures[i]!);\n if (b.kind === \"local\" && b.target.isDone()) {\n return { ok: true, v: { index: i, settled: b.target.settledValue() } };\n }\n }\n\n const promises: PromiseSource[] = [];\n for (let i = 0; i < futures.length; i++) {\n const idx = i;\n const b = getBacking(futures[i]!);\n // Epoch-guarded so only the first source to settle wakes the fiber\n // (later same-tick fires see the bumped epoch and no-op), and a\n // loser surviving an interrupt-and-re-park can't fire onto it.\n const fireOnce = this.epochGuarded((settled) =>\n this.wake({ ok: true, v: { index: idx, settled } })\n );\n if (b.kind === \"local\") {\n // The target may already be done — but we sync-checked above\n // and short-circuited if so. So awaitCompletion here will queue\n // the waiter (returning null). We ignore its return.\n b.target.awaitCompletion(fireOnce);\n } else {\n promises.push({ promise: b.promise, fire: fireOnce });\n }\n }\n this.state = { kind: \"parked\", promises };\n return null;\n }\n\n // ---- termination ----\n\n /**\n * Iterator finished or threw. Transition to done, fire all waiters\n * with the settled outcome, notify scheduler.\n */\n private finish(settled: Settled): void {\n this.state = { kind: \"done\", settled };\n // Re-home still-live children onto the grandparent before detaching,\n // so an ancestor's interrupt cascade still reaches them. A done fiber\n // is never interrupted again, so leaving children pointing at it would\n // sever the whole subtree from any live ancestor.\n const gp = this.parent;\n for (const child of this.children) {\n child.parent = gp;\n gp?.children.add(child);\n }\n this.children.clear();\n gp?.children.delete(this as Fiber<unknown>);\n const waiters = this.waiters;\n this.waiters = [];\n for (const w of waiters) w(settled);\n this.sched.markDone(this);\n }\n}\n\n/**\n * Drive a generator iterator one step, feeding it whatever value or\n * exception the caller is resuming with. `resume === null` is the\n * very first step; `{ok: true, v}` resumes with a value; `{ok: false,\n * e}` throws into the iterator (or, if the iterator has no `throw`\n * method, rethrows so the fiber fails).\n *\n * `started` is whether the generator has run at least once. Throwing\n * into a *not-yet-started* generator propagates the error straight out\n * without executing any body code (its try/catch/finally never engage).\n * That happens when a spawned routine is interrupted before its first\n * advance. To honor the \"delivered at the next yield point\" /\n * swallowable contract, we prime the generator with one `next()` first,\n * so the throw lands at the body's first yield. If the body returns\n * before reaching a yield, there is no yield point and the throw is moot.\n */\nfunction stepIterator(\n it: Iterator<unknown, unknown, unknown>,\n resume: Settled | null,\n started: boolean\n): IteratorResult<unknown, unknown> {\n if (resume === null) return it.next(undefined);\n if (resume.ok) return it.next(resume.v);\n if (!started) {\n const first = it.next(undefined);\n if (first.done) return first;\n }\n if (it.throw) return it.throw(resume.e);\n throw resume.e;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Channel<T>\n// =============================================================================\n//\n// A single-shot in-memory communication primitive. Cooperative — the\n// receiver chooses when to read, by yielding the channel's `receive`\n// Future. Composes with select, race, and any other Future-shaped\n// primitive.\n//\n// Semantics:\n//\n// send(v) — yieldable. `yield* ch.send(v)` settles the channel\n// with v. The first send wins; subsequent sends are\n// silently dropped (idempotent).\n// receive — a Future<T> that resolves with the sent value once\n// send fires. Always the same Future on every access;\n// settles once, stays settled forever, safe to share\n// across multiple selects/races.\n//\n// `send` returns `Operation<void>` so the only way to fire it is via\n// `yield*` from inside a generator body. This keeps channels\n// intra-workflow by construction — external code (setTimeout,\n// webhooks, cross-handler signals) doesn't have a generator to\n// `yield*` from, and should use `ops.awakeable()` instead, which is\n// durably journaled.\n//\n// Implementation: ChannelImpl is a `WaitTarget` (see future.ts). The\n// receive Future has `LocalBacking` pointing at this impl. When a\n// fiber yields receive, parkOnAwaitAny / parkOnLeaf treats it the\n// same as a routine-backed target — register a waiter, fire on\n// settle. `lib.race` never sees the channel; production's\n// RestatePromise.race is not involved.\n\nimport type { Settled, Waiter } from \"./scheduler-types.js\";\nimport { type Future, makeFuture, type WaitTarget } from \"./future.js\";\nimport { type Operation, gen } from \"./operation.js\";\n\nclass ChannelImpl<T> implements WaitTarget<T> {\n private state: { kind: \"pending\" } | { kind: \"settled\"; value: T } = {\n kind: \"pending\",\n };\n private waiters: Waiter[] = [];\n\n // Synchronous side-effect; only invoked from inside the gen body\n // returned by Channel.send (which itself is only iterable via\n // yield* inside a fiber).\n fire(value: T): void {\n if (this.state.kind === \"settled\") return;\n this.state = { kind: \"settled\", value };\n const ws = this.waiters;\n this.waiters = [];\n const settled: Settled = { ok: true, v: value };\n for (const w of ws) w(settled);\n }\n\n isDone(): boolean {\n return this.state.kind === \"settled\";\n }\n\n settledValue(): Settled {\n if (this.state.kind !== \"settled\") {\n throw new Error(\"ChannelImpl.settledValue called on a pending channel\");\n }\n return { ok: true, v: this.state.value };\n }\n\n awaitCompletion(waiter: Waiter): Settled | null {\n if (this.state.kind === \"settled\") {\n return { ok: true, v: this.state.value };\n }\n this.waiters.push(waiter);\n return null;\n }\n}\n\nexport interface Channel<T> {\n /**\n * Yieldable. Use as `yield* ch.send(value)` from within a gen body.\n * The first call settles the channel; subsequent calls are silently\n * dropped (idempotent).\n *\n * Return value is `Operation<void>` rather than `void` so the only\n * way to fire send is via `yield*` inside a fiber — which enforces\n * the channel-is-intra-workflow contract at the type level.\n */\n send(value: T): Operation<void>;\n readonly receive: Future<T>;\n}\n\nexport function makeChannel<T>(): Channel<T> {\n const impl = new ChannelImpl<T>();\n return {\n send: (v: T): Operation<void> =>\n // The generator body is intentionally yield-less: send's purpose\n // is a synchronous side effect that runs only when iterated via\n // `yield*`. The Operation wrapper exists for the type-level\n // enforcement, not because there's anything to suspend on.\n gen<void>(function* () {\n impl.fire(v);\n }),\n receive: makeFuture<T>({ kind: \"local\", target: impl }),\n };\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Scheduler\n// =============================================================================\n//\n// The runtime that drives Operations. Decoupled from Restate via the\n// Awaitable abstraction — production wires it to RestatePromise, tests\n// wire it to a hand-controlled promise type.\n//\n// The scheduler's job is orchestration:\n//\n// - Maintain the set of live fibers.\n// - Maintain the ready queue (which fibers want to run next).\n// - Run the main loop: assemble the parked sources from every live\n// fiber, race them via the lib, dispatch the winner.\n// - Broadcast invocation cancellation when the race rejects.\n// - Construct journal-backed and routine-backed Futures for users.\n//\n// The fiber's job is execution. The boundary between Scheduler and\n// Fiber is narrow (see `fiber.ts` and `SchedulerOps` interface).\n//\n// Invariants:\n//\n// S1. The ONLY async suspension point is the single `await lib.race`\n// per main-loop iteration. In production `lib.race` is a journaled\n// combinator, so its winner replays identically — this is the\n// determinism boundary. Drains, dispatch, and wakes are all\n// synchronous between two such awaits.\n// S2. Fibers advance ONLY inside `drainReady`. `advancingFiber` names\n// the one currently advancing (so `run` can hand it a per-fiber\n// signal); it is null between advances.\n// S3. Invocation cancellation is observed as the race promise\n// rejecting. It is fanned out to every parked source's `fire`,\n// reusing the normal wake path; the AbortController is aborted\n// then replaced so post-cancel recovery sees a fresh signal.\n\nimport type { Awaitable, AwaitableLib } from \"./awaitable.js\";\nimport {\n type Future,\n type FutureValue,\n type FutureValues,\n type FutureSettledResult,\n futureBacking,\n makeFuture,\n isJournalBacked,\n} from \"./future.js\";\nimport { type Operation, awaitRace, gen } from \"./operation.js\";\nimport type { Settled, PromiseSource } from \"./scheduler-types.js\";\nimport { Fiber, type SchedulerOps } from \"./fiber.js\";\nimport { type Channel, makeChannel } from \"./channel.js\";\nimport { type Task, makeTask } from \"./task.js\";\nimport { linkAbortController } from \"./abort.js\";\n\n/**\n * Policy for what happens to still-running spawned routines when the\n * main operation settles.\n *\n * - `\"abandon\"` (default): `run()` returns as soon as the main\n * operation settles. Still-running spawned routines (including\n * fibers synthesized internally by combinator fallbacks) are\n * abandoned at their current suspension point — they are never\n * resumed again, so no `catch`/`finally` blocks run and the sources\n * they were parked on are dropped. Durable work they already\n * started is journaled as usual; only the in-memory continuation is\n * discarded.\n * - `\"join\"`: `run()` keeps driving until *every* routine has\n * finished. A spawned routine parked on a source that never settles\n * keeps the handler from returning forever — prefer `\"abandon\"`\n * unless the workflow relies on fire-and-forget routines completing.\n */\nexport type OnMainExit = \"abandon\" | \"join\";\n\nexport interface SchedulerOptions {\n /** See {@link OnMainExit}. Defaults to `\"abandon\"`. */\n onMainExit?: OnMainExit;\n}\n\nexport class Scheduler implements SchedulerOps {\n private readonly fibers: Set<Fiber<unknown>> = new Set();\n private readonly ready: Fiber<unknown>[] = [];\n private readonly lib: AwaitableLib;\n private readonly onMainExit: OnMainExit;\n /**\n * The root fiber of the current `run()`. Assigned at the top of each\n * `run` call. Note the scheduler does not support concurrent `run`\n * calls (`fibers`/`ready`/`abortController` are equally shared);\n * production `execute()` always constructs a fresh scheduler.\n */\n private main: Fiber<unknown> | null = null;\n /**\n * The fiber currently being advanced by `drainReady`, or null between\n * advances. `run` reads this (via `currentRunSignal`) to hand a `run`\n * closure the *current fiber's* signal rather than a single global one,\n * so a targeted `interrupt` aborts only that fiber's in-flight I/O.\n */\n private advancingFiber: Fiber<unknown> | null = null;\n // Replaced (not just re-aborted) each time the scheduler observes\n // invocation cancellation. AbortControllers are one-way — once\n // aborted, signal.aborted stays true forever — so the scheduler-\n // level signal must be a fresh controller per cancel event to\n // preserve recoverability. Closures that captured the old signal\n // still see it as aborted (correctly, since their work was caught\n // by the cancellation); closures created after recovery see the new,\n // unaborted signal.\n private abortController: AbortController;\n\n /**\n * Parent AbortSignal supplied at construction (production: the SDK's\n * `attemptCompletedSignal`). Every controller this scheduler creates\n * is a child of it — born aborted if the parent has already fired,\n * aborted the moment it fires otherwise. Unlike cancellation, a\n * parent abort is sticky: an ended attempt never resumes. Defaults\n * to a signal that never fires.\n */\n private readonly parentSignal: AbortSignal;\n\n /**\n * Slot for the operations object bound to this scheduler. Defaults\n * to the scheduler itself so tests (which don't construct a\n * `RestateOperations`) still get a slot exposing `.spawn`. Production\n * `execute()` overrides this with a `RestateOperations` instance\n * after construction (we can't pass it into the ctor because\n * `RestateOperations` needs the scheduler to construct itself).\n * `Fiber.advance` publishes this to the module-level current-fiber\n * slot read by free-standing API functions. Typed `unknown` here to\n * keep this module independent of `restate-operations.ts`.\n */\n contextSlot: unknown;\n\n /**\n * Context-local storage: an ambient key/value bag scoped to this\n * scheduler — i.e. to this one `execute()` call, since production\n * builds a fresh scheduler per invocation (like `fibers` / `ready` /\n * `abortController`, this is per-run state, not shared across runs).\n * Every fiber under this scheduler reaches the same bag (global-per-\n * invocation; see `context.ts`). Keyed by the opaque symbol a\n * `contextLocal()` handle owns. In-memory only — never journaled.\n */\n private readonly localStore = new Map<symbol, unknown>();\n\n constructor(\n lib: AwaitableLib,\n parentSignal?: AbortSignal,\n options?: SchedulerOptions\n ) {\n this.lib = lib;\n this.onMainExit = options?.onMainExit ?? \"abandon\";\n this.contextSlot = this;\n this.parentSignal = parentSignal ?? new AbortController().signal;\n this.abortController = this.newAbortController();\n }\n\n /**\n * The scheduler's current AbortSignal. Aborts when invocation\n * cancellation is observed (the SDK rejects the main race promise\n * with TerminalError), or when the parent signal passed at\n * construction fires (production passes the SDK's\n * `attemptCompletedSignal`). After cancellation has been delivered\n * to fibers and the scheduler has resumed, this getter returns a\n * *fresh* signal — one that is not aborted, even though the previous\n * cancel was just delivered.\n *\n * Pass `signal` to AbortSignal-aware APIs in `ops.run` closures\n * (e.g. `fetch(url, {signal})`) so they cancel promptly when the\n * surrounding work is cancelled. Cleanup closures yielded after a\n * caught CancelledError get a fresh, unaborted signal — so they can\n * do real work and only abort if a *new* cancellation arrives.\n */\n get abortSignal(): AbortSignal {\n return this.abortController.signal;\n }\n\n /**\n * Fresh controller, born linked to the parent signal: pre-aborted if\n * the parent has already fired, otherwise subscribed to it. Births\n * the initial controller and each cancellation-recovery replacement.\n * Recovery closures must not see an unaborted signal once the\n * attempt itself is over — a parent abort is sticky.\n */\n private newAbortController(): AbortController {\n return linkAbortController(this.parentSignal);\n }\n\n /**\n * The AbortSignal for the currently-advancing fiber's `run` closures —\n * scoped per fiber so a targeted `interrupt(task)` aborts only that\n * task's in-flight I/O, while invocation cancellation / attempt-end\n * still cascade in (the fiber signal is a child of `abortSignal`).\n * Falls back to the scheduler signal when no fiber is advancing (a\n * defensive case — `run` is always called from inside a fiber).\n */\n currentRunSignal(): AbortSignal {\n return this.advancingFiber !== null\n ? this.advancingFiber.runSignal()\n : this.abortSignal;\n }\n\n // ---- SchedulerOps: narrow interface for Fiber ----\n\n markReady(f: Fiber<unknown>): void {\n this.ready.push(f);\n }\n\n markDone(f: Fiber<unknown>): void {\n // Remove from the live set so long-running loops that spawn (e.g.,\n // race in a while-true) don't accumulate dead-fiber objects. Safe\n // here because markDone is called from Fiber.advance, which only\n // runs between main-loop awaits — no other code is iterating\n // `fibers` now.\n this.fibers.delete(f);\n }\n\n private createFiber<U>(op: Operation<U>): Fiber<U> {\n // The fiber advancing right now (if any) is the spawning parent — so\n // `interrupt` can cascade down the spawn subtree. The root `main`\n // fiber is created outside any advance, so it has no parent.\n const f = new Fiber<U>(op, this, this.advancingFiber);\n this.fibers.add(f as Fiber<unknown>);\n this.ready.push(f as Fiber<unknown>);\n return f;\n }\n\n // ---- public construction helpers ----\n\n makeJournalFuture<U>(promise: Awaitable<U>): Future<U> {\n return makeFuture<U>({ kind: \"journal\", promise });\n }\n\n /**\n * Register an Operation as a fresh fiber, returning both its\n * local-backed Future and the underlying Fiber. Eager: by the time\n * this returns, the fiber is queued ready and will be advanced on the\n * next drain.\n *\n * Lifetime is bounded by the main fiber under the default\n * `\"abandon\"` policy: a spawned fiber still running when the main\n * fiber settles is abandoned (see {@link OnMainExit}). Under\n * `\"join\"` it keeps the scheduler alive until it finishes.\n *\n * Internal: combinator fallbacks (race, allSettled, …) use this to get\n * a plain Future. The public `spawn` wraps the same pair into a `Task`.\n */\n private spawnRoutine<U>(op: Operation<U>): {\n future: Future<U>;\n fiber: Fiber<U>;\n } {\n const fiber = this.createFiber(op);\n return { future: makeFuture<U>({ kind: \"local\", target: fiber }), fiber };\n }\n\n /** Spawn returning just the Future — for combinator fallbacks, which\n * never expose `interrupt` on their synthesized fibers. */\n private spawnFuture<U>(op: Operation<U>): Future<U> {\n return this.spawnRoutine(op).future;\n }\n\n /**\n * Register an Operation as a fresh fiber and return a `Task<U>` — a\n * `Future<U>` for its eventual value, plus `interrupt(err?)` to throw\n * into it at its next yield point. Eager: by the time this returns the\n * fiber is queued ready. Reached by `RestateOperations.spawn` and the\n * free `spawn` function.\n */\n spawn<U>(op: Operation<U>): Task<U> {\n const { future, fiber } = this.spawnRoutine(op);\n return makeTask(future, (err) => fiber.interrupt(err));\n }\n\n /**\n * Construct a single-shot in-memory channel. Send must be called from\n * a fiber currently advancing under this scheduler. See `channel.ts`\n * for full semantics.\n */\n makeChannel<U>(): Channel<U> {\n return makeChannel<U>();\n }\n\n // ---- context-local storage (see context.ts) ----\n\n /**\n * Read a context-local value, or `fallback` if `key` was never set in\n * this invocation. `has`-checked so an explicit `setLocal(key,\n * undefined)` reads back as `undefined` rather than falling through to\n * the handle's default.\n */\n getLocal(key: symbol, fallback: unknown): unknown {\n return this.localStore.has(key) ? this.localStore.get(key) : fallback;\n }\n\n /** Write a context-local value for the rest of this invocation. */\n setLocal(key: symbol, value: unknown): void {\n this.localStore.set(key, value);\n }\n\n // ---- combinator helpers (used by RestateOperations) ----\n\n /**\n * Combinator over Futures. Fast path when every input is journal-\n * backed: use the lib's all/race for a single combinator entry.\n * Otherwise, fall back to a synthesized fiber that yields each in\n * turn.\n *\n * Tuple-aware typing (mirrors `Promise.all` in the standard lib):\n * `all([fA, fB])` where `fA: Future<A>` and `fB: Future<B>`\n * yields `Future<[A, B]>`, not `Future<(A | B)[]>`. The `const T`\n * lets TS infer a tuple from a literal array.\n */\n all<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>> {\n // Cast to a uniform shape so `every(isJournalBacked)`'s type\n // predicate narrows elements correctly; the input tuple's\n // heterogeneous element types are recovered via the return cast.\n const fs = futures as ReadonlyArray<Future<unknown>>;\n if (fs.every(isJournalBacked)) {\n const promises = fs.map((f) => f[futureBacking].promise);\n return this.makeJournalFuture(this.lib.all(promises)) as Future<\n FutureValues<T>\n >;\n }\n return this.spawnFuture(\n gen<FutureValues<T>>(function* () {\n const out: unknown[] = new Array(fs.length);\n for (let i = 0; i < fs.length; i++) {\n // In case of failure, this throws, respecting the contract that all shortcircuits on failure\n out[i] = yield* fs[i]!;\n }\n return out as FutureValues<T>;\n })\n );\n }\n\n race<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>[number]> {\n type R = FutureValues<T>[number];\n const fs = futures as ReadonlyArray<Future<unknown>>;\n // No need here to try downcasting to RestateFuture's, awaitRace will anyway produce the same UnresolvedFuture tree!\n return this.spawnFuture(\n gen<R>(function* () {\n const result = yield* awaitRace(fs);\n if (result.settled.ok) return result.settled.v as R;\n throw result.settled.e;\n })\n );\n }\n\n /**\n * First-success combinator. Mirrors `Promise.any` /\n * `RestatePromise.any`: settles with the first input that succeeds\n * (non-rejected); rejects with `AggregateError(errors)` when every\n * input rejects (including the empty-array case).\n *\n * Fast path collapses to a single `lib.any` over journal awaitables.\n * Fallback synthesizes a fiber that loops `awaitAnyOf` over the\n * still-pending subset, accumulating rejections in input order until\n * one input fulfills or all have rejected.\n *\n * Tuple-aware: `any([fA, fB])` where `fA: Future<A>` and `fB:\n * Future<B>` yields `Future<A | B>` (the union of slot types), same\n * shape as `Promise.any`.\n */\n any<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>[number]> {\n type R = FutureValues<T>[number];\n const fs = futures as ReadonlyArray<Future<unknown>>;\n if (fs.every(isJournalBacked)) {\n const promises = fs.map((f) => f[futureBacking].promise);\n return this.makeJournalFuture(this.lib.any(promises)) as Future<R>;\n }\n return this.spawnFuture(\n gen<R>(function* () {\n const errors: unknown[] = new Array(fs.length);\n const remaining = new Set<number>();\n for (let i = 0; i < fs.length; i++) remaining.add(i);\n while (remaining.size > 0) {\n const liveIdx = Array.from(remaining);\n const live = liveIdx.map((i) => fs[i]!);\n const result = yield* awaitRace(live);\n const original = liveIdx[result.index]!;\n if (result.settled.ok) return result.settled.v as R;\n errors[original] = result.settled.e;\n remaining.delete(original);\n }\n throw new AggregateError(errors, \"All promises were rejected\");\n })\n );\n }\n\n /**\n * Settle-all combinator. Mirrors `Promise.allSettled` /\n * `RestatePromise.allSettled`: resolves with an array of\n * `FutureSettledResult` in input order, never rejects.\n *\n * Fast path collapses to a single `lib.allSettled`. Fallback yields\n * each Future in turn — safe because Futures are eager (already in\n * flight); sequential harvesting just reads them as they complete\n * without blocking concurrency.\n *\n * Tuple-aware: `allSettled([fA, fB])` yields\n * `Future<[FutureSettledResult<A>, FutureSettledResult<B>]>`.\n */\n allSettled<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<{\n -readonly [P in keyof T]: FutureSettledResult<FutureValue<T[P]>>;\n }> {\n type R = {\n -readonly [P in keyof T]: FutureSettledResult<FutureValue<T[P]>>;\n };\n const fs = futures as ReadonlyArray<Future<unknown>>;\n if (fs.every(isJournalBacked)) {\n const promises = fs.map((f) => f[futureBacking].promise);\n return this.makeJournalFuture(this.lib.allSettled(promises)) as Future<R>;\n }\n return this.spawnFuture(\n gen<R>(function* () {\n const out = new Array<FutureSettledResult<unknown>>(fs.length);\n for (let i = 0; i < fs.length; i++) {\n try {\n const value = yield* fs[i]!;\n out[i] = { status: \"fulfilled\", value };\n } catch (reason) {\n out[i] = { status: \"rejected\", reason };\n }\n }\n return out as R;\n })\n );\n }\n\n // ---- driving ----\n\n /**\n * True once the main fiber has settled under the `\"abandon\"` policy —\n * the signal to stop driving everything else. Checked by the main\n * loop *and* by `drainReady`, so the drain stops promptly mid-queue:\n * nothing observable (journal writes, channel sends, side effects)\n * happens after the main fiber's outcome is decided. Always false\n * under `\"join\"`.\n */\n private mainExited(): boolean {\n return (\n this.onMainExit === \"abandon\" && this.main !== null && this.main.isDone()\n );\n }\n\n private drainReady(): void {\n while (this.ready.length > 0 && !this.mainExited()) {\n const f = this.ready.shift()!;\n // Track the advancing fiber so `run` (called synchronously from\n // inside `f.advance()`) can read this fiber's run signal. Saved/\n // restored to tolerate any nesting, though advances don't nest.\n const prev = this.advancingFiber;\n this.advancingFiber = f;\n try {\n f.advance();\n } finally {\n this.advancingFiber = prev;\n }\n }\n }\n\n /**\n * Run an operation to completion. Drain the ready queue, then loop:\n * collect every PromiseSource from every parked fiber, race them,\n * dispatch the winner via its fire callback, drain.\n *\n * When to stop is governed by `onMainExit`: under `\"abandon\"` (the\n * default) the loop ends as soon as the main fiber settles and any\n * still-running spawned fibers are abandoned; under `\"join\"` it ends\n * only when no fiber is alive.\n */\n async run<T>(op: Operation<T>): Promise<T> {\n const main = this.createFiber(op);\n this.main = main as Fiber<unknown>;\n this.drainReady();\n\n // Under \"join\", mainExited() is always false and the loop runs\n // until every fiber is done. Under \"abandon\", main ∈ fibers while\n // it is alive, so the conjunction reduces to !main.isDone().\n while (!this.mainExited() && this.fibers.size > 0) {\n const items: PromiseSource[] = [];\n for (const f of this.fibers) {\n for (const src of f.parkedSources()) items.push(src);\n }\n if (items.length === 0) {\n // Live fibers exist but no journal promises are pending — a\n // wait-cycle deadlock, or fibers parked only on routine waiters\n // whose targets can't progress.\n throw new Error(\n \"scheduler stuck: live fibers but nothing pending on a journal promise\"\n );\n }\n\n const tagged = items.map(({ promise }, i) =>\n promise.map((v, e): { i: number } & Settled =>\n e !== undefined ? { i, ok: false, e } : { i, ok: true, v }\n )\n );\n\n // The race promise itself can be settled with a rejection by\n // the SDK when invocation cancellation arrives. Per-source\n // promises are unaffected — the rejection lives on this\n // aggregate race promise. We fan the rejection out to every\n // parked fiber: each was, in effect, contributing a source to\n // this race, so each gets the TerminalError delivered at its\n // current yield point. Fibers may catch and continue normally;\n // subsequent iterations build fresh race promises that are not\n // infected by this rejection.\n //\n // Before fanning out, abort the current AbortController so\n // in-flight syscalls inside ops.run closures (those listening\n // on the captured signal) start cancelling immediately. Then\n // replace the controller with a fresh one so that closures\n // created during recovery (cleanup yields, etc.) see an\n // unaborted signal — cancellation is not a sticky state.\n let raceWinner: { i: number } & Settled;\n try {\n raceWinner = (await this.lib.race(tagged)) as { i: number } & Settled;\n } catch (e) {\n if (this.lib.isCancellation(e)) {\n this.abortController.abort(e);\n this.abortController = this.newAbortController();\n }\n const errSettled: Settled = { ok: false, e };\n for (const it of items) it.fire(errSettled);\n this.drainReady();\n continue;\n }\n\n const { i, ...settledFields } = raceWinner;\n const settled: Settled = settledFields.ok\n ? { ok: true, v: settledFields.v }\n : { ok: false, e: settledFields.e };\n items[i]!.fire(settled);\n this.drainReady();\n }\n\n if (!main.isDone()) {\n throw new Error(\"scheduler exited but main fiber never completed\");\n }\n const final = main.settledValue();\n if (final.ok) return final.v as T;\n throw final.e;\n }\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// State<TState>\n// =============================================================================\n//\n// Wrapper around Restate's KeyValueStore — the per-key state attached\n// to a virtual object or workflow invocation. Available via\n// `ops.state()` (read-write) or `ops.sharedState()` (read-only) from\n// within `execute()`.\n//\n// Read-only vs read-write is a real distinction:\n// - ObjectContext / WorkflowContext expose the full KeyValueStore\n// (get + keys + set + clear + clearAll).\n// - ObjectSharedContext / WorkflowSharedContext expose only the\n// reads. Calling `set` etc. on the underlying context throws at\n// runtime; we surface that at the type level by giving shared\n// handlers a narrower interface.\n//\n// Both interfaces are generic over `TState extends TypedState`:\n// - Default `UntypedState` keeps the loose `(name: string)` shape\n// and a per-call value type — same as the SDK's untyped mode.\n// - Pass an explicit shape to get keyof-checked names and per-key\n// value types: `ops.state<{count: number; user: User}>()` then\n// `state.get(\"count\")` infers `Future<number | null>`.\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport type { Awaitable } from \"./awaitable.js\";\nimport type { Future } from \"./future.js\";\nimport type { Scheduler } from \"./scheduler.js\";\n\n/**\n * Marker types matching the SDK's typed-state convention. Pass a\n * concrete shape (e.g. `{count: number; name: string}`) to enable\n * keyof-checked names; leave the default to keep names as `string`\n * with a per-call value generic.\n */\nexport type TypedState = Record<string, unknown>;\nexport type UntypedState = { _: never };\n\n/**\n * Read-only state, for handlers running under an\n * ObjectSharedContext or WorkflowSharedContext.\n */\nexport interface SharedState<TState extends TypedState = UntypedState> {\n /** Read a state value. Returns null if the key isn't set. */\n get<TValue, TKey extends keyof TState = string>(\n name: TState extends UntypedState ? string : TKey,\n serde?: restate.Serde<TState extends UntypedState ? TValue : TState[TKey]>\n ): Future<(TState extends UntypedState ? TValue : TState[TKey]) | null>;\n\n /** List all currently-known state keys. */\n keys(): Future<string[]>;\n}\n\n/**\n * Read-write state, for handlers running under an ObjectContext or\n * WorkflowContext. Extends SharedState with mutation methods.\n *\n * Writes are synchronous in the SDK — the journal entry is recorded\n * immediately, no yield required — so `set` / `clear` / `clearAll`\n * return `void` rather than `Operation<void>`.\n */\nexport interface State<\n TState extends TypedState = UntypedState,\n> extends SharedState<TState> {\n /** Write a state value. Sync; journal entry recorded immediately. */\n set<TValue, TKey extends keyof TState = string>(\n name: TState extends UntypedState ? string : TKey,\n value: TState extends UntypedState ? TValue : TState[TKey],\n serde?: restate.Serde<TState extends UntypedState ? TValue : TState[TKey]>\n ): void;\n\n /** Clear a single key. */\n clear<TKey extends keyof TState>(\n name: TState extends UntypedState ? string : TKey\n ): void;\n\n /** Clear all state for this invocation. */\n clearAll(): void;\n}\n\n// Loose type covering every Restate context flavor that exposes any\n// state methods. We only call KeyValueStore methods on this; the rest\n// of Context is unused here.\ntype StateContext =\n | restate.ObjectContext\n | restate.ObjectSharedContext\n | restate.WorkflowContext\n | restate.WorkflowSharedContext;\n\n/**\n * Build a `State<TState>` over the given context. The runtime delegates\n * straight to `ctx.get` / `ctx.set` / etc.; the TState generic is purely\n * a TS-level convenience and gets erased at runtime.\n *\n * For shared (read-only) contexts, the returned State has the same\n * runtime shape but the caller should use the `SharedState<TState>`\n * type to drop the write methods. The convenience method\n * `RestateOperations.sharedState()` does this cast.\n */\nexport function makeState<TState extends TypedState = UntypedState>(\n ctx: StateContext,\n sched: Scheduler,\n adapt: <T>(p: restate.RestatePromise<T>) => Awaitable<T>\n): State<TState> {\n // Cast for write methods: the typed shared variants don't have them\n // on the type, but the runtime object does carry them in writable\n // contexts. Calling write() from a shared handler throws naturally.\n const writeCtx = ctx as restate.ObjectContext;\n\n // Internally we use the loose UntypedState signatures and cast the\n // resulting object to the narrower State<TState>. Runtime is identical;\n // the conditional types only matter at the call site.\n const impl: State<UntypedState> = {\n get<T>(name: string, serde?: restate.Serde<T>): Future<T | null> {\n return sched.makeJournalFuture(\n adapt(\n ctx.get<T>(name, serde) as unknown as restate.RestatePromise<T | null>\n )\n );\n },\n keys(): Future<string[]> {\n return sched.makeJournalFuture(\n adapt(ctx.stateKeys() as unknown as restate.RestatePromise<string[]>)\n );\n },\n set<T>(name: string, value: T, serde?: restate.Serde<T>): void {\n writeCtx.set(name, value, serde);\n },\n clear(name: string): void {\n writeCtx.clear(name);\n },\n clearAll(): void {\n writeCtx.clearAll();\n },\n };\n return impl as unknown as State<TState>;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport * as restate from \"@restatedev/restate-sdk\";\nimport type { Future } from \"./future.js\";\nimport type { InvocationReference } from \"./invocation-reference.js\";\nimport type { HandlerDescriptor, Descriptor } from \"./define.js\";\nimport {\n ClientCallOptions,\n ClientSendOptions,\n Opts,\n SendOpts,\n} from \"@restatedev/restate-sdk\";\n\n/**\n * A Future<O> that also carries an `invocation` field — a Future<InvocationReference<O>>\n * for accessing the invocationId, attach, cancel, and signal of the underlying call.\n */\nexport type ClientFuture<O> = Future<O> & {\n invocation: Future<InvocationReference<O>>;\n};\n\n/** Client type returned by client() — each method returns ClientFuture<O> */\nexport type GenClient<H extends Record<string, HandlerDescriptor>> = {\n readonly [K in keyof H]: H[K] extends HandlerDescriptor<infer I, infer O>\n ? [I] extends [void]\n ? (opts?: Opts<I, O>) => ClientFuture<O>\n : (input: I, opts?: Opts<I, O>) => ClientFuture<O>\n : never;\n};\n\n/** Client type returned by sendClient() — each method returns Future<InvocationReference<O>> */\nexport type GenSendClient<H extends Record<string, HandlerDescriptor>> = {\n readonly [K in keyof H]: H[K] extends HandlerDescriptor<infer I, infer O>\n ? [I] extends [void]\n ? (opts?: SendOpts<I>) => Future<InvocationReference<O>>\n : (input: I, opts?: SendOpts<I>) => Future<InvocationReference<O>>\n : never;\n};\n\n// =============================================================================\n// makeClient / makeSendClient — proxy factories used by RestateOperations\n// =============================================================================\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport function makeClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, any>,\n key: string | undefined,\n call: (opts: restate.GenericCall<unknown, unknown>) => ClientFuture<unknown>,\n scope?: string\n): GenClient<H> {\n return new Proxy({} as any, {\n get(_target, methodName: string) {\n return (...args: unknown[]) => {\n const { parameter, opts } = optsFromArgs(args);\n const callOpts = opts as ClientCallOptions<unknown, unknown>;\n const desc = def._handlers[methodName];\n const outputSerde = callOpts?.output ?? desc?._outputSerde;\n return call({\n service: def.name,\n key,\n method: String(methodName),\n parameter,\n inputSerde: (callOpts?.input ??\n desc?._inputSerde ??\n restate.serde.json) as restate.Serde<unknown>,\n outputSerde: (outputSerde ??\n restate.serde.json) as restate.Serde<unknown>,\n idempotencyKey: callOpts?.idempotencyKey,\n limitKey: callOpts?.limitKey,\n scope,\n headers: callOpts?.headers,\n name: callOpts?.name,\n });\n };\n },\n }) as GenClient<H>;\n}\n\nexport function makeSendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, any>,\n key: string | undefined,\n send: (\n opts: restate.GenericSend<unknown>,\n outputSerde?: restate.Serde<unknown>\n ) => Future<InvocationReference<unknown>>,\n scope?: string\n): GenSendClient<H> {\n return new Proxy({} as any, {\n get(_target, methodName: string) {\n return (...args: unknown[]) => {\n const { parameter, opts } = optsFromArgs(args);\n const sendOpts = opts as ClientSendOptions<unknown>;\n const desc = def._handlers[methodName];\n return send(\n {\n service: def.name,\n key,\n method: String(methodName),\n parameter,\n inputSerde: (sendOpts?.input ??\n desc?._inputSerde ??\n restate.serde.json) as restate.Serde<unknown>,\n delay: sendOpts?.delay,\n idempotencyKey: sendOpts?.idempotencyKey,\n limitKey: sendOpts?.limitKey,\n scope,\n headers: sendOpts?.headers,\n name: sendOpts?.name,\n },\n desc?._outputSerde as restate.Serde<unknown> | undefined\n );\n };\n },\n }) as GenSendClient<H>;\n}\n\nfunction optsFromArgs(args: unknown[]): {\n parameter?: unknown;\n opts?:\n | ClientCallOptions<unknown, unknown>\n | ClientSendOptions<unknown>\n | undefined;\n} {\n let parameter: unknown;\n let opts:\n | ClientCallOptions<unknown, unknown>\n | ClientSendOptions<unknown>\n | undefined;\n switch (args.length) {\n case 0: {\n break;\n }\n case 1: {\n if (args[0] instanceof Opts) {\n opts = args[0].getOpts();\n } else if (args[0] instanceof SendOpts) {\n opts = args[0].getOpts();\n } else {\n parameter = args[0];\n }\n break;\n }\n case 2: {\n parameter = args[0];\n if (args[1] instanceof Opts) {\n opts = args[1].getOpts();\n } else if (args[1] instanceof SendOpts) {\n opts = args[1].getOpts();\n } else {\n throw new TypeError(\n \"The second argument must be either Opts or SendOpts\"\n );\n }\n break;\n }\n default: {\n throw new TypeError(\"unexpected number of arguments\");\n }\n }\n return {\n parameter,\n opts,\n };\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport type { Future } from \"./future.js\";\n\n/** Same shape as the SDK's DurablePromise<T> but each method returns Future<...>. */\nexport type GenDurablePromise<T> = {\n peek(): Future<T | undefined>;\n resolve(value?: T): Future<void>;\n reject(errorMsg: string): Future<void>;\n get(): Future<T>;\n};\n\nexport function wrapDurablePromise<T>(\n dp: restate.DurablePromise<T>,\n toFuture: <U>(p: restate.RestatePromise<U> | Promise<U>) => Future<U>\n): GenDurablePromise<T> {\n return {\n peek: () =>\n toFuture(dp.peek() as unknown as restate.RestatePromise<T | undefined>),\n resolve: (value?: T) =>\n toFuture(dp.resolve(value) as unknown as restate.RestatePromise<void>),\n reject: (errorMsg: string) =>\n // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n toFuture(dp.reject(errorMsg) as unknown as restate.RestatePromise<void>),\n get: () => toFuture(dp.get()),\n };\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Production wiring: an AwaitableLib backed by restate.RestatePromise.\n//\n// RestatePromise is structurally compatible with Awaitable<T> already — it\n// has `.map((v, e) => U)` and is thenable. The adapter is a simple cast\n// at the boundary; the four combinators forward to RestatePromise's\n// static methods, preserving the tuple-aware result types declared on\n// AwaitableLib.\n\nimport * as restate from \"@restatedev/restate-sdk\";\nimport type { Awaitable, AwaitableLib } from \"./awaitable.js\";\nimport type { FutureSettledResult } from \"./future.js\";\n\nexport const defaultLib: AwaitableLib = {\n all<const T extends readonly Awaitable<unknown>[]>(\n items: T\n ): Awaitable<{ -readonly [P in keyof T]: Awaited<T[P]> }> {\n return restate.RestatePromise.all(\n items as unknown as readonly restate.RestatePromise<unknown>[]\n ) as unknown as Awaitable<{ -readonly [P in keyof T]: Awaited<T[P]> }>;\n },\n race<const T extends readonly Awaitable<unknown>[]>(\n items: T\n ): Awaitable<Awaited<T[number]>> {\n return restate.RestatePromise.race(\n items as unknown as readonly restate.RestatePromise<unknown>[]\n ) as unknown as Awaitable<Awaited<T[number]>>;\n },\n any<const T extends readonly Awaitable<unknown>[]>(\n items: T\n ): Awaitable<Awaited<T[number]>> {\n return restate.RestatePromise.any(\n items as unknown as readonly restate.RestatePromise<unknown>[]\n ) as unknown as Awaitable<Awaited<T[number]>>;\n },\n allSettled<const T extends readonly Awaitable<unknown>[]>(\n items: T\n ): Awaitable<{\n -readonly [P in keyof T]: FutureSettledResult<Awaited<T[P]>>;\n }> {\n return restate.RestatePromise.allSettled(\n items as unknown as readonly restate.RestatePromise<unknown>[]\n ) as unknown as Awaitable<{\n -readonly [P in keyof T]: FutureSettledResult<Awaited<T[P]>>;\n }>;\n },\n // Invocation cancellation arrives at the aggregate race promise as a\n // CancelledError (the SDK's terminal-error subclass with code 409).\n isCancellation(e: unknown): boolean {\n return e instanceof restate.CancelledError;\n },\n};\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unnecessary-type-assertion */\n\n// RestateOperations\n// =============================================================================\n//\n// Production-side wrapper around restate.Context. Produces journal-backed\n// Futures by delegating to the Restate SDK; defers to the scheduler for\n// spawn/all/race/select.\n//\n// Tests don't need this class — they construct Futures via\n// `Scheduler.makeJournalFuture(testPromise)` directly, build operations via\n// `gen()`, and run them via `Scheduler.run()`. This module's only job is\n// gluing the Restate SDK to the scheduler for production use.\n\nimport * as restate from \"@restatedev/restate-sdk\";\nimport type { Awaitable } from \"./awaitable.js\";\nimport type { Future, FutureSettledResult, FutureValues } from \"./future.js\";\nimport type { Task } from \"./task.js\";\nimport type { Channel } from \"./channel.js\";\nimport {\n gen,\n type Operation,\n select as selectOp,\n type SelectResult,\n} from \"./operation.js\";\nimport type { Scheduler, SchedulerOptions } from \"./scheduler.js\";\nimport { Scheduler as SchedulerClass } from \"./scheduler.js\";\nimport {\n makeState,\n type SharedState,\n type State,\n type TypedState,\n type UntypedState,\n} from \"./state.js\";\nimport {\n type ClientFuture,\n type GenClient,\n type GenSendClient,\n makeClient,\n makeSendClient,\n} from \"./clients.js\";\nimport {\n type GenDurablePromise,\n wrapDurablePromise,\n} from \"./durable-promise.js\";\nimport type { Descriptor, HandlerDescriptor } from \"./define.js\";\nimport {\n type InvocationReference,\n InvocationReferenceImpl,\n type SignalReference,\n} from \"./invocation-reference.js\";\nimport { defaultLib } from \"./default-lib.js\";\nimport { RestatePromise } from \"@restatedev/restate-sdk\";\n\n// Adapt a real RestatePromise to our Awaitable interface. RestatePromise\n// already has `.map((v, e) => U)` and is thenable, so the adapter is a\n// structural pass-through.\nfunction adapt<T>(p: restate.RestatePromise<T>): Awaitable<T> {\n return p as unknown as Awaitable<T>;\n}\n\nexport type HandlerRequest = Omit<restate.Request, \"attemptCompletedSignal\"> & {\n /**\n * Object key or Workflow key\n */\n readonly key?: string;\n};\n\n/**\n * Retry policy for `run`. Mirrors the SDK's `RunOptions` retry knobs\n * but namespaced (no `Retry` prefix on each field) and grouped under\n * `RunOpts.retry` for readability.\n */\nexport type RetryOptions = {\n /**\n * Max attempts (including the initial). When reached, `run` throws\n * a `TerminalError` wrapping the original error message.\n */\n maxAttempts?: number;\n /**\n * Max total duration of retries before giving up. Number is ms.\n */\n maxDuration?: restate.Duration | number;\n /**\n * First retry delay. Subsequent delays grow by `exponentiationFactor`.\n * Number is ms. Defaults to 50 ms.\n */\n initialInterval?: restate.Duration | number;\n /**\n * Cap on retry delay. Number is ms. Defaults to 10 s.\n */\n maxInterval?: restate.Duration | number;\n /**\n * Exponentiation factor applied to the previous delay. Defaults to 2.\n */\n exponentiationFactor?: number;\n /**\n * @deprecated Renamed to {@link exponentiationFactor}.\n */\n intervalFactor?: number;\n};\n\n/**\n * Options for `run`. Both fields are optional; if `name` is omitted,\n * the action's `Function.name` is used (works for named functions and\n * for arrow functions assigned to a `const` since JS infers names from\n * the binding site). If neither resolves, `run` throws.\n */\nexport type RunOpts<T> = {\n /** Journal entry name. Falls back to `action.name` if absent. */\n name?: string;\n /** Retry policy. Defaults to the SDK's defaults if absent. */\n retry?: RetryOptions;\n /** Custom serde for the journaled value. */\n serde?: restate.Serde<T>;\n};\n\n/**\n * Options object passed to the closure of `run(...)`. Carries an\n * AbortSignal that fires when invocation cancellation arrives.\n *\n * Using an object (rather than positional args) leaves room to extend\n * the closure's API surface — additional fields may be added later\n * without breaking existing closures.\n */\nexport type RunActionOpts = {\n readonly signal: AbortSignal;\n};\n\n/**\n * The closure that `run` invokes. Receives `{ signal }` — pass the\n * signal into AbortSignal-aware APIs (e.g. `fetch(url, { signal })`)\n * to cancel in-flight syscalls promptly.\n */\nexport type RunAction<T> = (opts: RunActionOpts) => Promise<T>;\n\n/**\n * Wrap a user-supplied `run` closure to surface the abort reason\n * (typically a TerminalError(CANCELLED)) on throw paths if the signal\n * aborted during execution. This converts AbortError (and any other\n * abort-caused failure) into the canonical cancellation TerminalError\n * for journal recording.\n *\n * Defensive coercion: if `signal.reason` is itself not a TerminalError\n * (which shouldn't happen in production but might during testing or\n * with non-cancellation race rejections), we wrap it in one. The\n * journal must record a *terminal* outcome to avoid retries against\n * a cancelled invocation.\n *\n * Exposed for testing — the wrapper's behavior is the part that has\n * semantic bite, separate from the ctx.run plumbing.\n */\nexport function wrapActionForCancellation<T>(\n signal: AbortSignal,\n action: RunAction<T>\n): () => Promise<T> {\n return async () => {\n try {\n return await action({ signal });\n } catch (e) {\n if (signal.aborted) {\n throw asTerminalError(signal.reason);\n }\n throw e;\n }\n };\n}\n\n/**\n * Resolve the journal-entry name; throw `TerminalError` if neither\n * source provides one.\n *\n * `TerminalError` (not a plain `Error`) because a missing name is a\n * programming bug — retrying the invocation will hit the same code\n * path and fail the same way. The SDK treats terminal errors as\n * non-retryable; the invocation fails fast instead of looping.\n */\nfunction resolveRunName<T>(action: RunAction<T>, opts?: RunOpts<T>): string {\n const fromOpts = opts?.name?.trim();\n if (fromOpts) return fromOpts;\n const fromFn = action.name;\n if (fromFn) return fromFn;\n throw new restate.TerminalError(\n \"@restatedev/restate-sdk-gen: run() requires a journal-entry name. \" +\n \"Either pass a named function (`run(myFn)`) or supply \" +\n \"`{ name: '...' }` in the second argument.\"\n );\n}\n\n/** Translate our `RetryOptions` into the SDK's flat `RunOptions` shape. */\nfunction toSdkRunOptions<T>(opts?: RunOpts<T>): restate.RunOptions<T> {\n const out: restate.RunOptions<T> = {};\n if (opts?.serde !== undefined) out.serde = opts.serde;\n const r = opts?.retry;\n if (r) {\n if (r.maxAttempts !== undefined) out.maxRetryAttempts = r.maxAttempts;\n if (r.maxDuration !== undefined) out.maxRetryDuration = r.maxDuration;\n if (r.initialInterval !== undefined)\n out.initialRetryInterval = r.initialInterval;\n if (r.maxInterval !== undefined) out.maxRetryInterval = r.maxInterval;\n // `exponentiationFactor` is the aligned name; `intervalFactor` is the\n // deprecated alias, honored only as a fallback.\n const exponentiationFactor = r.exponentiationFactor ?? r.intervalFactor;\n if (exponentiationFactor !== undefined)\n out.retryIntervalFactor = exponentiationFactor;\n }\n return out;\n}\n\nfunction asTerminalError(reason: unknown): restate.TerminalError {\n if (reason instanceof restate.TerminalError) return reason;\n // Non-Terminal reason: wrap as CancelledError. The SDK's CancelledError\n // is the canonical type for \"invocation was cancelled\" — TerminalError\n // subclass with the proper error code (409). The original reason is\n // discarded; defensible since this branch should never fire in\n // production (cancellation rejections from the SDK are always Terminal).\n return new restate.CancelledError();\n}\n\n/**\n * Deterministic date methods that return journal-backed Futures.\n * Wraps the SDK's `ContextDate` (which returns Promises via internal\n * `ctx.run()` calls) so that gen-SDK user code can `yield*` them.\n */\nexport interface GenContextDate {\n now(): Future<number>;\n toJSON(): Future<string>;\n}\n\n/**\n * Client bundle bound to a specific scope, returned by\n * {@link RestateOperations.scope} (and the free-standing `scope`).\n *\n * Exposes the same `client`/`sendClient` overloads as the unscoped\n * variants — for services, no key; for objects/workflows, the key —\n * but every call/send routes within the bound scope.\n */\nexport interface ScopedOperations {\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): GenClient<H>;\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): GenClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): GenSendClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): GenSendClient<H>;\n}\n\nexport class RestateOperations {\n private readonly ctx: restate.internal.ContextInternal;\n private readonly sched: Scheduler;\n\n constructor(context: restate.Context, sched: Scheduler) {\n this.ctx = context as restate.internal.ContextInternal;\n this.sched = sched;\n }\n\n // Internal: wrap an SDK RestatePromise as a journal-backed Future.\n // Not part of the public surface — every primitive that needs it\n // (run/sleep/awakeable/typed clients/genericCall/workflowPromise)\n // funnels through here so the adapt + makeJournalFuture wiring\n // stays in one place.\n toFuture<T>(p: restate.RestatePromise<T>): Future<T> {\n return this.sched.makeJournalFuture(adapt(p));\n }\n\n // ---- context properties (rand / date / console) ----\n\n get rand(): restate.Rand {\n return this.ctx.rand;\n }\n\n get date(): GenContextDate {\n return {\n now: () => this.toFuture(this.ctx.date.now() as RestatePromise<number>),\n toJSON: () =>\n this.toFuture(this.ctx.date.toJSON() as RestatePromise<string>),\n };\n }\n\n get console(): Console {\n return this.ctx.console;\n }\n\n isProcessing(): boolean {\n return this.ctx.isProcessing();\n }\n\n // ---- context-local storage ----\n // Delegate to the scheduler, which owns the single per-invocation bag.\n // Present here because `RestateOperations` is the current-fiber slot in\n // production; `contextLocal()` handles cast the slot to this shape.\n\n getLocal(key: symbol, fallback: unknown): unknown {\n return this.sched.getLocal(key, fallback);\n }\n\n setLocal(key: symbol, value: unknown): void {\n this.sched.setLocal(key, value);\n }\n\n // ---- journal-backed Futures ----\n\n /**\n * Run a side-effecting closure as a journal entry.\n *\n * The closure receives `{ signal }` — an AbortSignal that fires when\n * invocation cancellation arrives. Pass it into AbortSignal-aware\n * APIs (e.g. `fetch(url, { signal })`) to abort in-flight syscalls.\n *\n * `name` is the journal entry's stable identifier (must be\n * deterministic across replay). It can come from either:\n *\n * - `opts.name` — explicit override\n * - `action.name` — the function's own name (works for `function`\n * declarations and arrow functions assigned to a `const`,\n * since JS infers names from the binding site)\n *\n * If neither resolves, `run` throws.\n *\n * @example Named function — name derived\n * async function fetchUser({ signal }: RunActionOpts): Promise<User> {\n * const r = await fetch(`/users/${id}`, { signal });\n * return r.json();\n * }\n * yield* run(fetchUser);\n *\n * @example Named arrow — name derived from binding\n * const fetchUser = async ({ signal }: RunActionOpts) => { ... };\n * yield* run(fetchUser);\n *\n * @example Inline arrow — name explicit\n * yield* run(async ({ signal }) => fetch(url, { signal }), { name: \"fetch\" });\n *\n * @example With retry policy\n * yield* run(fetchUser, { retry: { maxAttempts: 3 } });\n *\n * Cancellation hygiene: if the closure throws while the signal is\n * aborted, we rethrow `signal.reason` (the original TerminalError)\n * instead of whatever the closure threw. This ensures the journal\n * entry records `TerminalError(CANCELLED)` rather than `AbortError`.\n */\n run<T>(action: RunAction<T>, opts?: RunOpts<T>): Future<T> {\n const name = resolveRunName(action, opts);\n // Per-fiber signal: a targeted `interrupt(task)` aborts only this\n // fiber's in-flight run; invocation cancellation / attempt-end still\n // cascade in (the fiber signal is a child of the scheduler signal).\n const wrapped = wrapActionForCancellation(\n this.sched.currentRunSignal(),\n action\n );\n return this.sched.makeJournalFuture(\n adapt(this.ctx.run(name, wrapped, toSdkRunOptions(opts)))\n );\n }\n\n sleep(duration: restate.Duration | number, name?: string): Future<void> {\n return this.sched.makeJournalFuture(adapt(this.ctx.sleep(duration, name)));\n }\n\n awakeable<T>(serde?: restate.Serde<T>): { id: string; promise: Future<T> } {\n const { id, promise } = this.ctx.awakeable(serde);\n return { id, promise: this.sched.makeJournalFuture(adapt(promise)) };\n }\n\n resolveAwakeable<T>(id: string, payload?: T, serde?: restate.Serde<T>) {\n this.ctx.resolveAwakeable(id, payload, serde);\n }\n\n rejectAwakeable(id: string, reason: string | restate.TerminalError) {\n this.ctx.rejectAwakeable(id, reason);\n }\n\n signal<T>(name: string, serde?: restate.Serde<T>): Future<T> {\n return this.sched.makeJournalFuture(adapt(this.ctx.signal(name, serde)));\n }\n\n attach<T>(\n invocationId: restate.InvocationId,\n serde?: restate.Serde<T>\n ): Future<T> {\n return this.sched.makeJournalFuture(\n adapt(this.ctx.attach(invocationId, serde))\n );\n }\n\n // ---- context accessor ----\n\n /**\n * Returns the current invocation's request metadata plus the optional\n * virtual-object / workflow key. The `key` field is only present when\n * the handler belongs to an object or workflow.\n */\n handlerRequest(): HandlerRequest {\n const req = this.ctx.request();\n const ctx = this.ctx;\n return {\n attemptHeaders: req.attemptHeaders,\n body: req.body,\n extraArgs: req.extraArgs,\n headers: req.headers,\n id: req.id,\n target: req.target,\n get key(): string | undefined {\n return (ctx as unknown as { key: string }).key;\n },\n scope: req.scope,\n idempotencyKey: req.idempotencyKey,\n limitKey: req.limitKey,\n };\n }\n\n // ---- typed clients (call + send) backed by call()/send() ----\n\n /**\n * Unified client for any Descriptor (service, object, or workflow).\n * Each method yields a Future<O> backed by call().\n * For services, key is not needed. For objects/workflows, pass the key.\n */\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): GenClient<H>;\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): GenClient<H>;\n client(def: Descriptor<string, any, any>, key?: string): GenClient<any> {\n return makeClient(def, key, (o) => this.call(o as any)) as any;\n }\n\n /**\n * Fire-and-forget send client for any Descriptor.\n * Each method returns an InvocationHandle synchronously.\n */\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): GenSendClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): GenSendClient<H>;\n sendClient(\n def: Descriptor<string, any, any>,\n key?: string\n ): GenSendClient<any> {\n return makeSendClient(def, key, (o, serde) =>\n this.send(o as any, serde)\n ) as any;\n }\n\n /**\n * Route all outgoing calls/sends through a named scope.\n *\n * Returns a bundle with the same `client`/`sendClient` overloads as the\n * unscoped variants; every call or send built from it carries the given\n * `scopeKey`. A scope is a sub-grouping of resources within the cluster\n * and becomes part of the target identity (it contributes to the\n * partition key, co-locating resources in the same scope).\n *\n * `scopeKey` must match `[a-zA-Z0-9_.-]`, 1..36 chars. Per-call\n * `limitKey` (via `Opts`/`SendOpts`) can only be used within a scope.\n *\n * @example\n * yield* scope(\"tenant-123\").client(Greeter).greet(name);\n * yield* scope(\"tenant-123\").client(Cart, \"cart-42\").add(item);\n * scope(\"tenant-123\").sendClient(Greeter).greet(name);\n */\n scope(scopeKey: string): ScopedOperations {\n return {\n client: (def: Descriptor<string, any, any>, key?: string) =>\n makeClient(def, key, (o) => this.call(o as any), scopeKey),\n sendClient: (def: Descriptor<string, any, any>, key?: string) =>\n makeSendClient(\n def,\n key,\n (o, serde) => this.send(o as any, serde),\n scopeKey\n ),\n } as ScopedOperations;\n }\n\n // ---- generic call/send (renamed from genericCall/genericSend) ----\n\n call<REQ = Uint8Array, RES = Uint8Array>(\n opts: restate.GenericCall<REQ, RES>\n ): ClientFuture<RES> {\n const restatePromise = this.ctx.genericCall<REQ, RES>(opts);\n const resultFuture = this.toFuture(restatePromise);\n const invocation = this.invocationReferenceFromHandle(\n restatePromise as unknown as restate.InvocationHandle,\n opts.outputSerde\n ) as Future<InvocationReference<RES>>;\n return Object.assign(resultFuture, { invocation }) as ClientFuture<RES>;\n }\n\n send<REQ = Uint8Array, RES = unknown>(\n opts: restate.GenericSend<REQ>,\n outputSerde?: restate.Serde<RES>\n ): Future<InvocationReference<RES>> {\n const handle = this.ctx.genericSend<REQ>(opts);\n return this.invocationReferenceFromHandle(handle, outputSerde) as Future<\n InvocationReference<RES>\n >;\n }\n\n // ---- invocation reference helpers ----\n\n invocationReferenceFromHandle<O>(\n handle: restate.InvocationHandle,\n outputSerde: restate.Serde<O> | undefined\n ): Future<InvocationReference<O>> {\n // handle.invocationId is Promise<InvocationId> typed, but under the hood\n // it is a RestatePromise — adapt it to a journal-backed Future.\n const idFuture = this.toFuture(\n handle.invocationId as unknown as restate.RestatePromise<restate.InvocationId>\n );\n return this.sched.spawn(\n gen(function* (): Generator<unknown, InvocationReference<O>, unknown> {\n const id = (yield* idFuture) as string;\n return new InvocationReferenceImpl<O>(id, outputSerde);\n })\n );\n }\n\n invocationSignal<T>(\n invocationId: restate.InvocationId,\n name: string,\n serde?: restate.Serde<T>\n ): SignalReference<T> {\n const internalCtx = this.ctx as unknown as restate.internal.ContextInternal;\n const ref = internalCtx.invocation(invocationId);\n return ref.signal<T>(name, serde) as SignalReference<T>;\n }\n\n // ---- cancel another invocation ----\n\n /**\n * Cancel another invocation by its id. To observe cancellation\n * arriving at *this* invocation, catch the `TerminalError` thrown by\n * the next `yield*` boundary or use the `signal` exposed inside\n * `ops.run` closures.\n */\n cancel(invocationId: restate.InvocationId): void {\n this.ctx.cancel(invocationId);\n }\n\n // ---- workflow durable promise ----\n\n /**\n * Workflow-bound durable promise. Use only inside a workflow handler\n * (the underlying context must be `WorkflowContext` or\n * `WorkflowSharedContext`). Returns a wrapper whose `peek`/`get`/\n * `resolve`/`reject` methods return Futures.\n */\n workflowPromise<T>(\n name: string,\n serde?: restate.Serde<T>\n ): GenDurablePromise<T> {\n const wfCtx = this.ctx as unknown as restate.WorkflowSharedContext;\n return wrapDurablePromise(wfCtx.promise<T>(name, serde), <U>(p: unknown) =>\n this.toFuture(p as restate.RestatePromise<U>)\n );\n }\n\n // ---- spawn ----\n\n /**\n * Register `op` as a fresh routine and return a `Future<T>` for its\n * eventual outcome. Eager: by the time `spawn` returns, the child is\n * already queued and will advance on the next scheduler tick — same\n * model as `run`/`sleep`/`awakeable`. The returned Future can be\n * yielded on, handed to combinators, or stored.\n *\n * A spawned routine still running when the main operation settles is\n * abandoned by default (its handler returns without it); pass\n * `{ onMainExit: \"join\" }` to `execute` to wait for it instead.\n *\n * Returns a `Task<T>` — a `Future<T>` plus `interrupt(err?)` to throw\n * into the routine at its next yield point.\n */\n spawn<T>(op: Operation<T>): Task<T> {\n return this.sched.spawn(op);\n }\n\n // ---- channels ----\n\n /**\n * Create a single-shot in-memory channel. Returns a Channel<T> with\n * `send(v)` (fire-and-forget, idempotent — first call settles, rest\n * are dropped) and `receive: Future<T>` (a stable settle-once Future,\n * the same handle on every access).\n *\n * Canonical use: cooperative cancellation. Spawn a routine that\n * selects over its work and `stop.receive`; the canceller calls\n * `stop.send()` to request termination. The receiver decides what\n * to do — return a partial result, do cleanup yields, ignore.\n *\n * Because `receive` is a stable, settle-once Future, multiple readers\n * all observe the same value (one-time broadcast) and the worker can\n * use it in every iteration of a select-loop without leaking orphan\n * receivers.\n *\n * Multi-event streams (producer-consumer, progress events) are NOT\n * supported — Channel is intentionally single-shot. A separate\n * primitive for that use case is yet to be designed.\n */\n channel<T>(): Channel<T> {\n return this.sched.makeChannel<T>();\n }\n\n // ---- state ----\n\n /**\n * Per-invocation read-write key-value store. Use from a handler whose\n * underlying context is ObjectContext or WorkflowContext.\n *\n * The optional `TState` generic gives keyof-checked names and per-key\n * value types:\n *\n * ops.state<{count: number; user: User}>()\n * // state.get(\"count\") → Future<number | null>\n *\n * Without it, names are `string` and values are inferred per call:\n *\n * ops.state()\n * // state.get<number>(\"count\") → Future<number | null>\n *\n * Calling write methods from a shared (read-only) context throws at\n * runtime — for shared handlers, use `sharedState()` below to get a\n * narrower type that drops the write methods.\n */\n state<TState extends TypedState = UntypedState>(): State<TState> {\n return makeState<TState>(\n this.ctx as unknown as restate.ObjectContext,\n this.sched,\n adapt\n );\n }\n\n /**\n * Per-invocation read-only key-value store. Use from a handler whose\n * underlying context is ObjectSharedContext or WorkflowSharedContext.\n *\n * Same `TState` generic as `state()`. Returns the read-only subset\n * (`get`, `keys`); attempting to call writes is a type error.\n */\n sharedState<TState extends TypedState = UntypedState>(): SharedState<TState> {\n return makeState<TState>(\n this.ctx as unknown as restate.ObjectSharedContext,\n this.sched,\n adapt\n );\n }\n\n // ---- combinators ----\n\n /**\n * Wait for every future to settle; return their values in input\n * order. Heterogeneous-tuple typing — `all([fA, fB])` where\n * `fA: Future<A>` and `fB: Future<B>` yields `Future<[A, B]>`.\n * Mirrors `Promise.all` from the standard lib.\n */\n all<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>> {\n return this.sched.all(futures);\n }\n\n /**\n * Return the first future to settle; losers continue running (until\n * the main operation settles — see `OnMainExit`) but their results\n * are discarded. Heterogeneous-tuple typing — `race([fA, fB])`\n * yields `Future<A | B>`. Mirrors `Promise.race`.\n */\n race<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>[number]> {\n return this.sched.race(futures);\n }\n\n /**\n * First-success combinator. Resolves with the first input that\n * succeeds (non-rejected); rejects with `AggregateError(errors)` when\n * every input rejects (including an empty input array). See `Promise.any`.\n *\n * Tuple-aware typing — `any([fA, fB])` where `fA: Future<A>` and\n * `fB: Future<B>` yields `Future<A | B>`.\n */\n any<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<FutureValues<T>[number]> {\n return this.sched.any(futures);\n }\n\n /**\n * Settle-all combinator. Resolves with an array of\n * `FutureSettledResult` in input order; never rejects. See\n * `Promise.allSettled`.\n *\n * Tuple-aware typing — `allSettled([fA, fB])` yields\n * `Future<[FutureSettledResult<A>, FutureSettledResult<B>]>`.\n */\n allSettled<const T extends readonly Future<unknown>[] | []>(\n futures: T\n ): Future<{\n -readonly [P in keyof T]: FutureSettledResult<\n T[P] extends Future<infer U> ? U : never\n >;\n }> {\n return this.sched.allSettled(futures);\n }\n\n // Wait for one branch to settle, return its tag and the future itself.\n // The user unwraps the future after switching on the tag — `yield* r.future`\n // is effectively sync at that point since it's already settled.\n *select<B extends Record<string, Future<unknown>>>(\n branches: B\n ): Generator<unknown, SelectResult<B>, unknown> {\n return yield* selectOp(branches);\n }\n}\n\n// =============================================================================\n// Production execute() entry point.\n// =============================================================================\n\n/**\n * Options for {@link execute}.\n */\nexport type ExecuteOptions = SchedulerOptions;\n\n/**\n * Run a generator-based workflow against a Restate context.\n *\n * `op` is an `Operation<T>` — typically the result of\n * `gen(function*() { ... })`. Inside the generator body, reach for the\n * free-standing API (`run`, `sleep`, `all`, `state`, …) imported\n * from `@restatedev/restate-sdk-gen`. They read the active scheduler from a\n * synchronous current-fiber slot installed by `Fiber.advance`.\n *\n * `gen()` already takes a factory, so the same `Operation` is re-\n * iterable across multiple `execute()` calls — no need for a builder\n * lambda at this boundary.\n *\n * By default `execute` resolves as soon as the main operation settles;\n * spawned fibers (and race losers) still running at that point are\n * abandoned. Pass `{ onMainExit: \"join\" }` to instead keep driving\n * until every spawned fiber has finished.\n *\n * @example\n * execute(ctx, gen(function* () {\n * const greeting = yield* run(async () => \"hi\", { name: \"compose\" });\n * return greeting;\n * }));\n */\nexport async function execute<T>(\n context: restate.Context,\n op: Operation<T>,\n options?: ExecuteOptions\n): Promise<T> {\n // The attempt's lifecycle signal is the parent of the scheduler's\n // AbortSignal: when the current attempt completes (suspension,\n // stream close, success or failure), in-flight `run` closures\n // listening on the signal stop promptly instead of running on\n // detached.\n const sched = new SchedulerClass(\n defaultLib,\n context.request().attemptCompletedSignal,\n options\n );\n // Publish a private `RestateOperations` on the scheduler so\n // `Fiber.advance` can install it on the module-level current-fiber\n // slot read by the free-standing API.\n sched.contextSlot = new RestateOperations(context, sched);\n return sched.run(op);\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unnecessary-type-assertion */\n\nimport * as restate from \"@restatedev/restate-sdk\";\nimport type { StandardSchemaV1 } from \"@restatedev/restate-sdk-core\";\nimport {\n type HandlerDescriptor,\n type Descriptor,\n type ServiceDescriptor,\n type ObjectDescriptor,\n type WorkflowDescriptor,\n type ImplementedServiceDefinition,\n type ImplementedObjectDefinition,\n type ImplementedWorkflowDefinition,\n type ImplementedDefinition,\n makeHandlerDescriptor,\n serde,\n} from \"@restatedev/restate-sdk-core\";\nimport { execute } from \"./restate-operations.js\";\nimport { type Operation } from \"./operation.js\";\nimport { ServiceHandlerOpts } from \"@restatedev/restate-sdk\";\n\n// =============================================================================\n// Shared interface/descriptor layer — moved to @restatedev/restate-sdk-core and\n// re-exported here so this package's public API is unchanged.\n// =============================================================================\nexport type {\n HandlerDescriptor,\n Descriptor,\n ServiceDescriptor,\n ObjectDescriptor,\n WorkflowDescriptor,\n ImplementedServiceDefinition,\n ImplementedObjectDefinition,\n ImplementedWorkflowDefinition,\n ImplementedDefinition,\n};\n\n// =============================================================================\n// HandlerDef — result of serdes()\n// =============================================================================\n\n/** @internal\n * @internal - Wraps a generator function with optional serde. Produced by typed().\n * Discriminated by _genFn for runtime detection (distinct from bare gen fns,\n * which are plain functions rather than objects).\n */\nexport type HandlerDef<I = any, O = any> = {\n readonly _genFn: (input: I) => Operation<O>;\n} & HandlerDescriptor<I, O>;\n\n/** @internal */\nexport type EntryToDescriptor<E> =\n E extends HandlerDef<infer I, infer O>\n ? HandlerDescriptor<I, O>\n : E extends () => Operation<infer O>\n ? HandlerDescriptor<void, O> // no-arg generator → void input\n : E extends (input: infer I) => Operation<infer O>\n ? HandlerDescriptor<I, O>\n : HandlerDescriptor;\n\n/** Map a full handler map type to the corresponding descriptor map type */\nexport type HandlerDescriptors<\n H extends Record<string, HandlerOrHandlerDescriptor>,\n> = {\n [K in keyof H]: EntryToDescriptor<H[K]>;\n};\n\n// =============================================================================\n// Per-handler options\n// =============================================================================\n\n/** Options valid for all handler types. To set input and output serde, check {@link serdes()} */\nexport type GenHandlerOpts = Omit<\n ServiceHandlerOpts<unknown, unknown>,\n \"input\" | \"output\"\n>;\n\n/** Handler options for virtual object handlers */\nexport type GenObjectHandlerOpts = GenHandlerOpts & {\n /**\n * When true, the handler will be marked as shared.\n * Shared object handlers can only read state, not write it.\n */\n shared?: boolean;\n\n /**\n * When set to `true`, lazy state will be enabled for all invocations to this handler.\n *\n * *NOTE:* You can set this field only if you register this endpoint against restate-server >= 1.4,\n * otherwise the service discovery will fail.\n */\n enableLazyState?: boolean;\n};\n\n/** Handler options for workflow handlers (shared is implicit from name) */\nexport type GenWorkflowHandlerOpts = {\n /**\n * When set to `true`, lazy state will be enabled for all invocations to this handler.\n *\n * *NOTE:* You can set this field only if you register this endpoint against restate-server >= 1.4,\n * otherwise the service discovery will fail.\n */\n enableLazyState?: boolean;\n};\n\n// =============================================================================\n// Handler entry types\n// =============================================================================\n\n/** @internal */\nexport type AnyGenFn = (input: any) => Operation<any>;\n\n/** A handler entry: either a bare generator fn or the result of {@link serdes()} */\nexport type HandlerOrHandlerDescriptor = AnyGenFn | HandlerDef<any, any>;\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/** HandlerDef has _genFn as an object property; bare gen fns are plain functions */\nfunction isHandlerDef(\n entry: HandlerOrHandlerDescriptor\n): entry is HandlerDef<any, any> {\n return (\n typeof entry === \"object\" &&\n entry !== null &&\n typeof (entry as any)._genFn === \"function\"\n );\n}\n\nfunction extractEntry(entry: HandlerOrHandlerDescriptor): {\n genFn: AnyGenFn;\n inputSerde: restate.Serde<any> | undefined;\n outputSerde: restate.Serde<any> | undefined;\n} {\n if (isHandlerDef(entry)) {\n return {\n genFn: entry._genFn as AnyGenFn,\n inputSerde: entry._inputSerde,\n outputSerde: entry._outputSerde,\n };\n }\n return {\n genFn: entry as AnyGenFn,\n inputSerde: undefined,\n outputSerde: undefined,\n };\n}\n\n// =============================================================================\n// Handler definition helpers — produce HandlerDef for use in service/object/workflow\n// =============================================================================\n\n/** serdes(opts, fn) — explicit Serde per field */\nexport function serdes<I, O>(\n opts: { input: restate.Serde<I>; output: restate.Serde<O> },\n fn: (input: I) => Operation<O>\n): HandlerDef<I, O> {\n return {\n _genFn: fn as AnyGenFn,\n _inputSerde: opts.input,\n _outputSerde: opts.output,\n };\n}\n\n/** schemas(opts, fn) — Standard Schema (Zod, TypeBox, Valibot, …) per field */\nexport function schemas<\n SI extends StandardSchemaV1<any>,\n SO extends StandardSchemaV1<any>,\n>(\n opts: { input: SI; output: SO },\n fn: (\n input: StandardSchemaV1.InferOutput<SI>\n ) => Operation<StandardSchemaV1.InferOutput<SO>>\n): HandlerDef<\n StandardSchemaV1.InferOutput<SI>,\n StandardSchemaV1.InferOutput<SO>\n> {\n return {\n _genFn: fn as AnyGenFn,\n _inputSerde: serde.schema(opts.input),\n _outputSerde: serde.schema(opts.output),\n };\n}\n\n// =============================================================================\n// service() factory\n// =============================================================================\n\nexport function service<\n P extends string,\n H extends Record<string, HandlerOrHandlerDescriptor>,\n>(config: {\n name: P;\n description?: string;\n metadata?: Record<string, string>;\n handlers: H;\n options?: restate.ServiceOptions & {\n handlers?: Partial<Record<keyof H, GenHandlerOpts>>;\n };\n}): ImplementedServiceDefinition<P, HandlerDescriptors<H>> {\n const { name, description, metadata, handlers, options } = config;\n const { handlers: perHandlerOpts, ...serviceOpts } = options ?? {};\n\n const coreHandlers: Record<string, any> = {};\n const descriptors: Record<string, HandlerDescriptor> = {};\n\n for (const [handlerName, entry] of Object.entries(handlers)) {\n const { genFn, inputSerde, outputSerde } = extractEntry(entry);\n const handlerOpts =\n ((perHandlerOpts as any)?.[handlerName] as GenHandlerOpts) ?? {};\n\n coreHandlers[handlerName] = restate.handlers.handler(\n { input: inputSerde, output: outputSerde, ...handlerOpts } as any,\n async (ctx: restate.Context, input: any) => execute(ctx, genFn(input))\n );\n\n descriptors[handlerName] = makeHandlerDescriptor(inputSerde, outputSerde);\n }\n\n const coreDef = restate.service({\n name,\n handlers: coreHandlers as any,\n description,\n metadata,\n options: serviceOpts,\n });\n\n return Object.assign(coreDef, {\n _kind: \"service\" as const,\n _handlers: descriptors,\n }) as unknown as ImplementedServiceDefinition<P, HandlerDescriptors<H>>;\n}\n\n// =============================================================================\n// object() factory\n// =============================================================================\n\nexport function object<\n P extends string,\n H extends Record<string, HandlerOrHandlerDescriptor>,\n>(config: {\n name: P;\n description?: string;\n metadata?: Record<string, string>;\n handlers: H;\n options?: restate.ObjectOptions & {\n handlers?: Partial<Record<keyof H, GenObjectHandlerOpts>>;\n };\n}): ImplementedObjectDefinition<P, HandlerDescriptors<H>> {\n const { name, description, metadata, handlers, options } = config;\n const { handlers: perHandlerOpts, ...objectOpts } = options ?? {};\n\n const coreHandlers: Record<string, any> = {};\n const descriptors: Record<string, HandlerDescriptor> = {};\n\n for (const [handlerName, entry] of Object.entries(handlers)) {\n const { genFn, inputSerde, outputSerde } = extractEntry(entry);\n const handlerOpts: GenObjectHandlerOpts =\n ((perHandlerOpts as any)?.[handlerName] as GenObjectHandlerOpts) ?? {};\n const { shared, ...restOpts } = handlerOpts;\n\n const sdkOpts = {\n input: inputSerde,\n output: outputSerde,\n ...restOpts,\n } as any;\n const fn = async (\n ctx: restate.ObjectContext | restate.ObjectSharedContext,\n input: any\n ) => execute(ctx as restate.Context, genFn(input));\n\n coreHandlers[handlerName] = shared\n ? restate.handlers.object.shared(sdkOpts, fn as any)\n : restate.handlers.object.exclusive(sdkOpts, fn as any);\n\n descriptors[handlerName] = makeHandlerDescriptor(inputSerde, outputSerde);\n }\n\n const coreDef = restate.object({\n name,\n handlers: coreHandlers as any,\n description,\n metadata,\n options: objectOpts,\n });\n\n return Object.assign(coreDef, {\n _kind: \"object\" as const,\n _handlers: descriptors,\n }) as unknown as ImplementedObjectDefinition<P, HandlerDescriptors<H>>;\n}\n\n// =============================================================================\n// workflow() factory\n// =============================================================================\n\nexport function workflow<\n P extends string,\n H extends Record<string, HandlerOrHandlerDescriptor>,\n>(config: {\n name: P;\n description?: string;\n metadata?: Record<string, string>;\n handlers: H;\n options?: restate.WorkflowOptions & {\n handlers?: Partial<Record<keyof H, GenWorkflowHandlerOpts>>;\n };\n}): ImplementedWorkflowDefinition<P, HandlerDescriptors<H>> {\n const { name, description, metadata, handlers, options } = config;\n const { handlers: perHandlerOpts, ...workflowOpts } = options ?? {};\n\n const coreHandlers: Record<string, any> = {};\n const descriptors: Record<string, HandlerDescriptor> = {};\n\n for (const [handlerName, entry] of Object.entries(handlers)) {\n const { genFn, inputSerde, outputSerde } = extractEntry(entry);\n const handlerOpts =\n ((perHandlerOpts as any)?.[handlerName] as GenWorkflowHandlerOpts) ?? {};\n\n const sdkOpts = {\n input: inputSerde,\n output: outputSerde,\n ...handlerOpts,\n } as any;\n const fn = async (\n ctx: restate.WorkflowContext | restate.WorkflowSharedContext,\n input: any\n ) => execute(ctx as restate.Context, genFn(input));\n\n coreHandlers[handlerName] =\n handlerName === \"run\"\n ? restate.handlers.workflow.workflow(sdkOpts, fn as any)\n : restate.handlers.workflow.shared(sdkOpts, fn as any);\n\n descriptors[handlerName] = makeHandlerDescriptor(inputSerde, outputSerde);\n }\n\n const coreDef = restate.workflow({\n name,\n handlers: coreHandlers as any,\n description,\n metadata,\n options: workflowOpts,\n });\n\n return Object.assign(coreDef, {\n _kind: \"workflow\" as const,\n _handlers: descriptors,\n }) as unknown as ImplementedWorkflowDefinition<P, HandlerDescriptors<H>>;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-assignment */\n\nimport type * as restate from \"@restatedev/restate-sdk\";\nimport {\n type HandlerDescriptor,\n type Descriptor,\n type ServiceDescriptor,\n type ObjectDescriptor,\n type WorkflowDescriptor,\n type ImplementedServiceDefinition,\n type ImplementedObjectDefinition,\n type ImplementedWorkflowDefinition,\n type ImplementedDefinition,\n type InferInput,\n type InferOutput,\n} from \"@restatedev/restate-sdk-core\";\nimport type { Operation } from \"./operation.js\";\nimport {\n type GenHandlerOpts,\n type GenObjectHandlerOpts,\n type GenWorkflowHandlerOpts,\n service as _defineService,\n object as _defineObject,\n workflow as _defineWorkflow,\n} from \"./define.js\";\n\n// The pure interface declarators (`json`/`serdes`/`schemas`) and the\n// `iface.service/object/workflow` factories now live in\n// @restatedev/restate-sdk-core and are re-exported through this package's\n// `iface` namespace (see index.ts). InferInput/InferOutput are re-exported for\n// API Extractor traceability.\nexport type { InferInput, InferOutput };\n\n// =============================================================================\n// implement() — bind generator handlers to a service interface (contract)\n// =============================================================================\n\n/** @internal */\nexport type ImplementHandlers<H extends Record<string, HandlerDescriptor>> = {\n [K in keyof H]: (input: InferInput<H[K]>) => Operation<InferOutput<H[K]>>;\n};\n\nexport function implement<\n P extends string,\n H extends Record<string, HandlerDescriptor>,\n>(\n iface: ServiceDescriptor<P, H>,\n config: {\n handlers: ImplementHandlers<H>;\n options?: restate.ServiceOptions & {\n handlers?: Partial<Record<keyof H, GenHandlerOpts>>;\n };\n }\n): ImplementedServiceDefinition<P, H>;\n\nexport function implement<\n P extends string,\n H extends Record<string, HandlerDescriptor>,\n>(\n iface: ObjectDescriptor<P, H>,\n config: {\n handlers: ImplementHandlers<H>;\n options?: restate.ObjectOptions & {\n handlers?: Partial<Record<keyof H, GenObjectHandlerOpts>>;\n };\n }\n): ImplementedObjectDefinition<P, H>;\n\nexport function implement<\n P extends string,\n H extends Record<string, HandlerDescriptor>,\n>(\n iface: WorkflowDescriptor<P, H>,\n config: {\n handlers: ImplementHandlers<H>;\n options?: restate.WorkflowOptions & {\n handlers?: Partial<Record<keyof H, GenWorkflowHandlerOpts>>;\n };\n }\n): ImplementedWorkflowDefinition<P, H>;\n\nexport function implement(\n iface: Descriptor<any, any, any>,\n config: {\n handlers: Record<string, any>;\n options?: any;\n }\n): ImplementedDefinition<any, any, any> {\n // Build HandlerDef entries from interface descriptors + implementation fns.\n // Contract-declared per-handler docs/metadata (defaults) are merged with any\n // per-handler opts passed to implement() (which override), and threaded\n // through `options.handlers` — define.ts spreads those onto the SDK handler.\n const handlerEntries: Record<string, any> = {};\n const contractHandlerOpts: Record<string, Record<string, unknown>> = {};\n for (const [name, desc] of Object.entries(\n iface._handlers as Record<string, HandlerDescriptor>\n )) {\n const genFn = config.handlers[name];\n if (!genFn) throw new Error(`implement(): missing handler \"${name}\"`);\n // Object with _genFn triggers isHandlerDef() check in define.ts factories\n handlerEntries[name] = {\n _genFn: genFn,\n _inputSerde: desc._inputSerde,\n _outputSerde: desc._outputSerde,\n };\n if (desc._description !== undefined || desc._metadata !== undefined) {\n contractHandlerOpts[name] = {\n description: desc._description,\n metadata: desc._metadata,\n };\n }\n }\n\n const { handlers: userHandlerOpts, ...restOptions } = (config.options ??\n {}) as {\n handlers?: Record<string, Record<string, unknown>>;\n [key: string]: unknown;\n };\n const mergedHandlerOpts: Record<string, Record<string, unknown>> = {};\n for (const name of Object.keys(iface._handlers as Record<string, unknown>)) {\n const merged: Record<string, unknown> = {\n ...contractHandlerOpts[name],\n ...userHandlerOpts?.[name],\n };\n if (Object.keys(merged).length > 0) {\n mergedHandlerOpts[name] = merged;\n }\n }\n\n const common = {\n name: iface.name,\n handlers: handlerEntries,\n // Service-level docs come from the contract; per-handler docs are merged\n // into options.handlers below (contract defaults, implement() overrides).\n description: iface._description,\n metadata: iface._metadata,\n options: { ...restOptions, handlers: mergedHandlerOpts },\n };\n\n if (iface._kind === \"service\") {\n return _defineService(common) as any;\n } else if (iface._kind === \"object\") {\n return _defineObject(common) as any;\n } else {\n return _defineWorkflow(common) as any;\n }\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument */\n\n/**\n * @deprecated The `clients` ingress adapter is superseded by\n * `@restatedev/restate-sdk-clients`. The service interface / `Descriptor`\n * values produced by this package (`service`/`object`/`workflow`/`iface` /\n * `implement`) are now first-class inputs to that package's ingress client,\n * which reuses their declared serdes automatically:\n *\n * ```ts\n * import { connect } from \"@restatedev/restate-sdk-clients\";\n * const ingress = connect({ url });\n * await ingress.client(greeter).greet(req); // service\n * await ingress.client(counter, \"k\").add(1); // virtual object / workflow (with key)\n * ```\n *\n * Every export here now delegates to that client and will be removed in a\n * future release.\n */\n\nimport {\n Opts,\n SendOpts,\n type Send,\n type Ingress,\n type IngressClient,\n type IngressWorkflowClient,\n type IngressSendClient,\n type ConnectionOpts,\n type RetryPolicy,\n type RetryFailure,\n connect as clientsConnect,\n defaultShouldRetry,\n HttpCallError,\n} from \"@restatedev/restate-sdk-clients\";\nimport type { HandlerDescriptor, Descriptor } from \"./define.js\";\n\n// Re-export connect, Ingress, SendOpts so consumers can use clients.connect / clients.Ingress\nexport {\n Opts,\n SendOpts,\n defaultShouldRetry,\n HttpCallError,\n type ConnectionOpts,\n type RetryPolicy,\n type RetryFailure,\n type Ingress,\n type Send,\n type IngressClient,\n type IngressWorkflowClient,\n type IngressSendClient,\n};\n\n/**\n * @deprecated Use `connect` from `@restatedev/restate-sdk-clients` and its typed\n * client methods, e.g. `connect({ url }).serviceClient(def)`\n */\nexport function connect(opts: ConnectionOpts): GenIngress {\n return clientsConnect(opts);\n}\n\n/**\n * @deprecated Use `connect` from `@restatedev/restate-sdk-clients` and its typed\n * client methods, e.g. `connect({ url }).serviceClient(def)`\n */\nexport type GenIngress = Ingress;\n\n// =============================================================================\n// Typed ingress client types\n// =============================================================================\n\ntype InferInput<D> = D extends HandlerDescriptor<infer I, any> ? I : unknown;\ntype InferOutput<D> = D extends HandlerDescriptor<any, infer O> ? O : unknown;\n\n/**\n * Typed ingress call client — each method returns Promise<O>.\n *\n * @deprecated Use the client returned by `ingress.serviceClient(def)` /\n * `ingress.objectClient(def, key)` from `@restatedev/restate-sdk-clients`.\n */\nexport type IngressHandlerClient<H extends Record<string, HandlerDescriptor>> =\n {\n readonly [K in keyof H]: (\n input: InferInput<H[K]>,\n opts?: Opts<InferInput<H[K]>, InferOutput<H[K]>>\n ) => Promise<InferOutput<H[K]>>;\n };\n\n/**\n * Typed ingress send client — each method returns Promise<Send>.\n *\n * @deprecated Use the client returned by `ingress.serviceSendClient(def)` /\n * `ingress.objectSendClient(def, key)` from `@restatedev/restate-sdk-clients`.\n */\nexport type IngressSendHandlerClient<\n H extends Record<string, HandlerDescriptor>,\n> = {\n readonly [K in keyof H]: [InferInput<H[K]>] extends [void]\n ? (opts?: SendOpts<void>) => Promise<Send>\n : (\n input: InferInput<H[K]>,\n opts?: SendOpts<InferInput<H[K]>>\n ) => Promise<Send>;\n};\n\n// =============================================================================\n// client / sendClient — thin wrappers over the regular ingress client.\n// =============================================================================\n\n/**\n * @deprecated Call the regular ingress client directly: `ingress.client(def)`\n * for a service, or `ingress.client(def, key)` for a virtual object / workflow.\n */\nexport function client<H extends Record<string, HandlerDescriptor>>(\n ingress: GenIngress,\n def: Descriptor<string, H, \"service\">\n): IngressHandlerClient<H>;\nexport function client<H extends Record<string, HandlerDescriptor>>(\n ingress: GenIngress,\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n): IngressHandlerClient<H>;\nexport function client(\n ingress: GenIngress,\n def: Descriptor<string, any, any>,\n key?: string\n): IngressHandlerClient<any> {\n return (key === undefined\n ? ingress.client(def as any)\n : ingress.client(def as any, key)) as unknown as IngressHandlerClient<any>;\n}\n\n/**\n * @deprecated Call the regular ingress client directly: `ingress.sendClient(def)`\n * for a service, or `ingress.sendClient(def, key)` for a virtual object / workflow.\n */\nexport function sendClient<H extends Record<string, HandlerDescriptor>>(\n ingress: GenIngress,\n def: Descriptor<string, H, \"service\">\n): IngressSendHandlerClient<H>;\nexport function sendClient<H extends Record<string, HandlerDescriptor>>(\n ingress: GenIngress,\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n): IngressSendHandlerClient<H>;\nexport function sendClient(\n ingress: GenIngress,\n def: Descriptor<string, any, any>,\n key?: string\n): IngressSendHandlerClient<any> {\n return (key === undefined\n ? ingress.sendClient(def as any)\n : ingress.sendClient(\n def as any,\n key\n )) as unknown as IngressSendHandlerClient<any>;\n}\n\n/**\n * @deprecated Use `ingress.scope(scopeKey)` from\n * `@restatedev/restate-sdk-clients` and its `client`/`sendClient` methods.\n */\nexport interface ScopedGenIngress {\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): IngressHandlerClient<H>;\n client<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): IngressHandlerClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"service\">\n ): IngressSendHandlerClient<H>;\n sendClient<H extends Record<string, HandlerDescriptor>>(\n def: Descriptor<string, H, \"object\" | \"workflow\">,\n key: string\n ): IngressSendHandlerClient<H>;\n}\n\n/**\n * @deprecated Use `ingress.scope(scopeKey)` from\n * `@restatedev/restate-sdk-clients`, then `.client(def)` / `.sendClient(def)`\n * on the returned scoped ingress.\n */\nexport function scope(ingress: GenIngress, scopeKey: string): ScopedGenIngress {\n const scoped = ingress.scope(scopeKey);\n return {\n client: (def: Descriptor<string, any, any>, key?: string) =>\n (key === undefined\n ? scoped.client(def as any)\n : scoped.client(def as any, key)) as unknown,\n sendClient: (def: Descriptor<string, any, any>, key?: string) =>\n (key === undefined\n ? scoped.sendClient(def as any)\n : scoped.sendClient(def as any, key)) as unknown,\n } as ScopedGenIngress;\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Internal operations\n// =============================================================================\n//\n// Free-standing functions that are deliberately NOT part of the main\n// API surface (`free.ts` / top-level `index.ts` exports). They expose\n// sharp tools whose misuse leads straight to non-determinism errors,\n// so they live behind the `internal` namespace as an \"I know what I'm\n// doing\" gate:\n//\n// import { internal } from \"@restatedev/restate-sdk-gen\";\n// if (internal.isProcessing()) { ... }\n\nimport { isRestatePromise, type RestatePromise } from \"@restatedev/restate-sdk\";\nimport { peekCurrent } from \"./current.js\";\nimport { currentOps } from \"./free.js\";\nimport type { Future } from \"./future.js\";\nimport { RestateOperations } from \"./restate-operations.js\";\n\n/**\n * Whether the current invocation is in the processing phase (as opposed\n * to replaying its journal). Aligns with the core SDK's\n * `ContextInternal.isProcessing()`.\n *\n * Returns `true`/`false` when called inside an active fiber backed by a\n * real Restate context, and `undefined` when there is no such context\n * (outside `execute()`, or in scheduler-only tests with no SDK context).\n *\n * **WARNING**: this is the same mechanism `ctx.console` uses to decide\n * whether to log during replay. Do **not** use it to influence control\n * flow — doing so will **surely** lead to non-determinism errors. It is\n * intended for observability concerns only (logging, metrics).\n *\n * @experimental\n */\nexport function isProcessing(): boolean | undefined {\n const current = peekCurrent();\n return current instanceof RestateOperations\n ? current.isProcessing()\n : undefined;\n}\n\n/**\n * Wrap an existing SDK promise as a journal-backed Future without\n * starting another operation or adding a journal entry.\n *\n * Call inside a generator running under `execute(ctx, ...)`, using a\n * RestatePromise from that same invocation. Pass the SDK promise directly:\n * `async` wrappers and `.then()` return native promises and are rejected.\n *\n * An InvocationPromise becomes a plain Future; invocation handles and\n * child-invocation cancellation are not added by this bridge.\n *\n * @example\n * yield* internal.adopt(ctx.serviceClient(greeter).greet(\"Ada\"));\n *\n * @experimental\n */\nexport function adopt<T>(promise: RestatePromise<T>): Future<T> {\n if (!isRestatePromise(promise)) {\n throw new TypeError(\n \"adopt requires a RestatePromise. Pass the SDK promise directly, without async or .then().\"\n );\n }\n return currentOps().toFuture(promise);\n}\n","/*\n * Copyright (c) 2023-2026 - Restate Software, Inc., Restate GmbH\n *\n * This file is part of the Restate SDK for Node.js/TypeScript,\n * which is released under the MIT license.\n *\n * You can find a copy of the license in file LICENSE in the root\n * directory of this repository or package, or at\n * https://github.com/restatedev/sdk-typescript/blob/main/LICENSE\n */\n\n// Public API.\n\nexport type { Channel } from \"./channel.js\";\nexport type { GenClient, GenSendClient, ClientFuture } from \"./clients.js\";\nexport type { GenDurablePromise } from \"./durable-promise.js\";\nexport type {\n InvocationReference,\n SignalReference,\n} from \"./invocation-reference.js\";\nexport {\n all,\n allSettled,\n any,\n attach,\n awakeable,\n call,\n cancel,\n channel,\n client,\n date,\n handlerRequest,\n invocation,\n logger,\n race,\n rand,\n rejectAwakeable,\n resolveAwakeable,\n run,\n scope,\n send,\n sendClient,\n sharedState,\n signal,\n sleep,\n spawn,\n state,\n workflowPromise,\n} from \"./free.js\";\n\nexport type {\n Future,\n FutureFulfilledResult,\n FutureRejectedResult,\n FutureSettledResult,\n FutureValue,\n FutureValues,\n} from \"./future.js\";\nexport { gen, type Operation, select, type SelectResult } from \"./operation.js\";\nexport { contextLocal, type ContextLocal } from \"./context.js\";\nexport { type Task, InterruptedError } from \"./task.js\";\nexport {\n execute,\n type ExecuteOptions,\n type GenContextDate,\n type RetryOptions,\n type RunAction,\n type RunActionOpts,\n type RunOpts,\n type ScopedOperations,\n wrapActionForCancellation,\n type HandlerRequest,\n} from \"./restate-operations.js\";\nexport type { OnMainExit, SchedulerOptions } from \"./scheduler.js\";\nexport type { SharedState, State, TypedState, UntypedState } from \"./state.js\";\n\n// Service/object/workflow definition API\nexport {\n serdes,\n schemas,\n service,\n object,\n workflow,\n type Descriptor,\n type HandlerDescriptor,\n type HandlerOrHandlerDescriptor,\n type HandlerDescriptors,\n type ServiceDescriptor,\n type ObjectDescriptor,\n type WorkflowDescriptor,\n type ImplementedServiceDefinition,\n type ImplementedObjectDefinition,\n type ImplementedWorkflowDefinition,\n type ImplementedDefinition,\n type GenHandlerOpts,\n type GenObjectHandlerOpts,\n type GenWorkflowHandlerOpts,\n} from \"./define.js\";\n\n// Interface / implement pattern.\n// The declarators/factories (`service`/`object`/`workflow`/`json`/`serdes`/\n// `schemas`/`shared`) live in @restatedev/restate-sdk-core; `implement` is\n// generator-specific and lives here. Merge them under one `iface` namespace.\nexport { implement } from \"./interface.js\";\nimport { iface as _coreIface } from \"@restatedev/restate-sdk-core\";\nimport { implement as _implement } from \"./interface.js\";\nexport const iface = { ..._coreIface, implement: _implement };\n\n// Ingress adapters, exported as `clients` namespace\nimport * as _ingress from \"./ingress.js\";\nexport { _ingress as clients };\n\n// Internal functions\nexport * as internal from \"./internal-operations.js\";\n\n// External types that appear in our public API surface — re-exported for consumers\nexport { serde } from \"@restatedev/restate-sdk-core\";\nexport type {\n StandardSchemaV1,\n Serde,\n VirtualObjectDefinitionFrom,\n VirtualObject,\n Service,\n ServiceDefinition,\n ServiceDefinitionFrom,\n Workflow,\n WorkflowDefinition,\n WorkflowDefinitionFrom,\n VirtualObjectDefinition,\n Duration,\n StandardTypedV1,\n ServiceInterface,\n DescriptorOpts,\n SerdeType,\n} from \"@restatedev/restate-sdk-core\";\n\nexport type { ContextDate, Rand } from \"@restatedev/restate-sdk\";\n\n// Internal types exposed only for API Extractor traceability — not part of the public API\n/** @internal */\nexport type { EntryToDescriptor, AnyGenFn, HandlerDef } from \"./define.js\";\n/** @internal */\nexport type {\n ImplementHandlers,\n InferInput,\n InferOutput,\n} from \"./interface.js\";\n"],"mappings":"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"}
|