@lunora/workflow 1.0.0-alpha.67 → 1.0.0-alpha.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -192,7 +192,9 @@ export const checkout = mutation.input({ orderId: v.string() }).mutation(async (
192
192
  });
193
193
  ```
194
194
 
195
- A handle exposes `create({ id?, params?, retention? })`, `createBatch([...])`, `get(id)`, and `sendEvent(instanceId, event, payload)` — the typed delivery of a declared event (see above). `create`/`get` return the native Cloudflare instance, which exposes its own lifecycle: `status()`, `pause()`, `resume()`, `restart()`, `terminate()`, and the untyped `sendEvent({ type, payload })`.
195
+ A handle exposes `create({ id?, params?, retention? })`, `createBatch([...])`, `deleteBatch([...ids])` (up to 100), `get(id)`, and `sendEvent(instanceId, event, payload)` — the typed delivery of a declared event (see above). `create`/`get` return the native Cloudflare instance, which exposes its own lifecycle: `status()`, `pause()`, `resume()`, `restart()`, `terminate()`, `delete()`, `subscribe({ cursor?, filter? })` (streams the instance's event history, then new events), and the untyped `sendEvent({ type, payload })`.
196
+
197
+ `defineWorkflow` also takes deploy settings, which codegen writes into the workflow's `wrangler.jsonc` entry: `schedules` (cron expressions that each start an instance), `limits: { steps }`, and `defaultRetention: { successRetention, errorRetention }`. Scheduled workflows are refused on the Node and celld targets.
196
198
 
197
199
  ### Runtime requirements
198
200
 
@@ -204,7 +206,7 @@ A handle exposes `create({ id?, params?, retention? })`, `createBatch([...])`, `
204
206
  ### Manual wiring (without codegen)
205
207
 
206
208
  1. Author `lunora/workflows.ts` as above.
207
- 2. Re-export the generated class from your worker entry — wrangler requires every `workflows[].class_name` to be exported:
209
+ 2. Re-export the generated class from your worker entry — wrangler requires every workflow export to be a class the worker exports:
208
210
 
209
211
  ```ts
210
212
  import LunoraWorkflow from "@lunora/workflow/do";
@@ -217,17 +219,17 @@ A handle exposes `create({ id?, params?, retention? })`, `createBatch([...])`, `
217
219
  }
218
220
  ```
219
221
 
220
- 3. Add the binding to `wrangler.jsonc`:
222
+ 3. Declare it in `wrangler.jsonc`'s `exports` (Wrangler 4.142.0+):
221
223
 
222
224
  ```jsonc
223
225
  {
224
- "workflows": [{ "name": "order-pipeline", "binding": "WORKFLOW_ORDER_PIPELINE", "class_name": "OrderPipelineWorkflow" }],
226
+ "exports": { "OrderPipelineWorkflow": { "type": "workflow", "name": "order-pipeline" } },
225
227
  }
226
228
  ```
227
229
 
228
- 4. Build `ctx.workflows` from the binding: `createWorkflows({ bindings: { orderPipeline: env.WORKFLOW_ORDER_PIPELINE } })`.
230
+ 4. Build `ctx.workflows` from the invoking context's exports: `createWorkflows({ bindings: { orderPipeline: ctx.exports.OrderPipelineWorkflow } })`.
229
231
 
230
- The `workflowClassName` / `workflowBindingName` / `workflowDefaultName` helpers produce exactly these names so codegen and config never disagree.
232
+ The `workflowClassName` / `workflowDefaultName` helpers produce exactly these names so codegen and config never disagree.
231
233
 
232
234
  ### Observing instances (REST client)
233
235
 
@@ -1,5 +1,5 @@
1
1
  import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
2
- import { W as WorkflowDefinition } from "../packem_shared/types.d-DKvSidAr.mjs";
2
+ import { W as WorkflowDefinition } from "../packem_shared/types.d-5O82Xdxt.mjs";
3
3
  import '@lunora/values';
4
4
  /**
5
5
  * Base class for the generated `WorkflowEntrypoint` classes. Applies a
@@ -1,5 +1,5 @@
1
1
  import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
2
- import { W as WorkflowDefinition } from "../packem_shared/types.d-DKvSidAr.js";
2
+ import { W as WorkflowDefinition } from "../packem_shared/types.d-5O82Xdxt.js";
3
3
  import '@lunora/values';
4
4
  /**
5
5
  * Base class for the generated `WorkflowEntrypoint` classes. Applies a
package/dist/do/index.mjs CHANGED
@@ -1 +1 @@
1
- import{WorkflowEntrypoint as p}from"cloudflare:workers";import{NonRetryableError as i}from"cloudflare:workflows";import{convertNonRetryableError as m}from"../packem_shared/NonRetryableError-BPu01mU8.mjs";import{extractBranchMarker as f,stripBranchMarker as h,signalBranchParentSafe as l,errorOutcome as u,okOutcome as y}from"../packem_shared/MAX_BRANCHES-j59ZUUSu.mjs";import{createWorkflowRunContext as d}from"../packem_shared/createWorkflowRunContext-DTYKQowc.mjs";class N extends p{#r;#t;constructor(t,e,o,r){super(t,e),this.#t=o,this.#r=r??"workflow"}async run(t,e){const o=e,r=f(t.payload),c=r?{...t,payload:h(t.payload)}:t,a=d({env:this.env,event:c,exportName:this.#r,nonRetryableErrorClass:i,step:o});let n;try{n=await this.#t.handler(a)}catch(s){return r&&await l({env:this.env,log:a.log,step:o},r,u(s)),m(s,i)}return r&&await l({env:this.env,log:a.log,step:o},r,y(n)),n}}export{N as default};
1
+ import{WorkflowEntrypoint as l}from"cloudflare:workers";import{NonRetryableError as i}from"cloudflare:workflows";import{convertNonRetryableError as h}from"../packem_shared/NonRetryableError-BPu01mU8.mjs";import{extractBranchMarker as m,stripBranchMarker as x,signalBranchParentSafe as p,errorOutcome as f,okOutcome as u}from"../packem_shared/MAX_BRANCHES-Bcw3dss9.mjs";import{createWorkflowRunContext as y}from"../packem_shared/createWorkflowRunContext-CMweH87g.mjs";class N extends l{#r;#t;constructor(t,e,o,r){super(t,e),this.#t=o,this.#r=r??"workflow"}async run(t,e){const o=e,r=m(t.payload),c=r?{...t,payload:x(t.payload)}:t,a=y({env:this.env,exports:this.ctx.exports,event:c,exportName:this.#r,nonRetryableErrorClass:i,step:o});let n;try{n=await this.#t.handler(a)}catch(s){return r&&await p({env:this.env,exports:this.ctx.exports,log:a.log,step:o},r,f(s)),h(s,i)}return r&&await p({env:this.env,exports:this.ctx.exports,log:a.log,step:o},r,u(n)),n}}export{N as default};
package/dist/index.d.mts CHANGED
@@ -1,22 +1,23 @@
1
- import { a as Workflows, L as LunoraWorkflowsOptions, b as WorkflowEventDefinition, S as StepArgsValidator, c as StepConfig, d as StepDefinition, e as WorkflowConfig, W as WorkflowDefinition, f as WorkflowBranch, g as WorkflowInstanceStatus, h as WorkflowEventLike, i as WorkflowStepLike, j as WorkflowRunContext, k as WorkflowLogger, l as WorkflowRunFunction, m as WorkflowRunStepFunction, n as WorkflowWaitForEventFunction } from "./packem_shared/types.d-DKvSidAr.mjs";
2
- export type { A as ArgsOf, B as BranchCompensationParams, F as FunctionKind, o as FunctionReference, I as InferStepArgs, R as RunFunctionOptions, p as RunStepOptions, q as StepHandler, r as StepRollbackContext, s as StepRollbackHandler, t as StepRunContext, u as WaitForEventOptions, v as WorkflowBindingLike, w as WorkflowBranchOutputs, x as WorkflowCreateOptions, y as WorkflowHandle, z as WorkflowHandler, C as WorkflowInstanceLike, D as WorkflowParallelFunction, E as WorkflowRollbackContextLike, G as WorkflowRollbackHandlerLike, H as WorkflowSpawnFunction, J as WorkflowSpawnOptions, K as WorkflowStatusResult, M as WorkflowStepConfigLike, N as WorkflowStepContextLike, O as WorkflowStepRollbackOptionsLike } from "./packem_shared/types.d-DKvSidAr.mjs";
1
+ import { a as Workflows, L as LunoraWorkflowsOptions, b as WorkflowEventDefinition, S as StepArgsValidator, c as StepConfig, d as StepDefinition, e as WorkflowConfig, W as WorkflowDefinition, f as WorkflowBranch, g as WorkflowInstanceStatus, h as WorkflowEventLike, i as WorkflowStepLike, j as WorkflowRunContext, k as WorkflowLogger, l as WorkflowRunFunction, m as WorkflowRunStepFunction, n as WorkflowWaitForEventFunction } from "./packem_shared/types.d-5O82Xdxt.mjs";
2
+ export type { A as ArgsOf, B as BranchCompensationParams, F as FunctionKind, o as FunctionReference, I as InferStepArgs, R as RunFunctionOptions, p as RunStepOptions, q as StepHandler, r as StepRollbackContext, s as StepRollbackHandler, t as StepRunContext, u as WaitForEventOptions, v as WorkflowBatchDeleteResult, w as WorkflowBindingLike, x as WorkflowBranchOutputs, y as WorkflowCreateOptions, z as WorkflowDelayFunctionLike, C as WorkflowHandle, D as WorkflowHandler, E as WorkflowInstanceEventLike, G as WorkflowInstanceLike, H as WorkflowInstanceSubscribeOptionsLike, J as WorkflowInstanceSubscriptionLike, K as WorkflowParallelFunction, M as WorkflowRetention, N as WorkflowRollbackContextLike, O as WorkflowRollbackHandlerLike, P as WorkflowSpawnFunction, Q as WorkflowSpawnOptions, T as WorkflowStatusResult, U as WorkflowStepConfigLike, V as WorkflowStepContextLike, X as WorkflowStepRollbackOptionsLike } from "./packem_shared/types.d-5O82Xdxt.mjs";
3
3
  import { Validator } from '@lunora/values';
4
4
  import { LunoraError } from '@lunora/errors';
5
5
  /** Wiring info for one declared workflow, emitted by codegen into the generated shard. */
6
6
  interface WorkflowBindingSpec {
7
- /** The Cloudflare `Workflow` binding name, e.g. `WORKFLOW_ORDER_PIPELINE`. */
8
- binding: string;
7
+ /** The workflow's export key — its generated class name, e.g. `OrderPipelineWorkflow`. */
8
+ className: string;
9
9
  /** The `lunora/workflows.ts` export name, e.g. `orderPipeline`. */
10
10
  exportName: string;
11
11
  }
12
12
  /**
13
- * Build the `ctx.workflows` handle for a request: resolve every spec's
14
- * `env[binding]` into the `exportName → Workflow binding` map and wrap it in
15
- * {@link createWorkflows}. A spec whose binding is absent from `env` is skipped
13
+ * Build the `ctx.workflows` handle for a request: resolve every spec's key off
14
+ * the invoking context's `exports` (Cloudflare) or `env` (other hosts) into the
15
+ * `exportName → Workflow binding` map and wrap it in {@link createWorkflows}. A
16
+ * spec whose workflow is absent from both is skipped
16
17
  * here — the helpful "no workflow named …" error is raised lazily by
17
18
  * `workflows.get(name)` when the missing workflow is actually used.
18
19
  */
19
- declare const createWorkflowContext: (env: Record<string, unknown>, specs: ReadonlyArray<WorkflowBindingSpec>) => Workflows;
20
+ declare const createWorkflowContext: (env: Record<string, unknown>, specs: ReadonlyArray<WorkflowBindingSpec>, exports?: unknown) => Workflows;
20
21
  /**
21
22
  * Build the `ctx.workflows` handle from a map of `lunora/workflows.ts` export
22
23
  * name → Cloudflare `Workflow` binding. `get(name)` resolves the typed handle;
@@ -86,20 +87,15 @@ declare const defineStep: <A extends StepArgsValidator, Result>(name: string, co
86
87
  declare const isStepDefinition: (value: unknown) => value is StepDefinition;
87
88
  /**
88
89
  * The generated `WorkflowEntrypoint` class name for a `lunora/workflows.ts`
89
- * export: `orderPipeline` → `OrderPipelineWorkflow`. wrangler's
90
- * `workflows[].class_name` references it, so codegen and the config layer MUST
91
- * derive it identically — always via this helper.
90
+ * export: `orderPipeline` → `OrderPipelineWorkflow`. It is also the workflow's
91
+ * key everywhere at runtime: wrangler's `exports.<Class>` declares it, the
92
+ * invoking context's `ctx.exports.<Class>` reaches it (see
93
+ * `shared/workflow-binding.ts`), so codegen, config and the runtime MUST derive
94
+ * it identically — always via this helper.
92
95
  */
93
96
  declare const workflowClassName: (exportName: string) => string;
94
97
  /**
95
- * The wrangler binding name for a workflow export: `orderPipeline` →
96
- * `WORKFLOW_ORDER_PIPELINE`, `etl` → `WORKFLOW_ETL`. The `WORKFLOW_` prefix
97
- * namespaces these away from `SHARD`/`SESSION`/`SCHEDULER`/`CONTAINER_*` so a
98
- * workflow export can never collide with the built-in bindings.
99
- */
100
- declare const workflowBindingName: (exportName: string) => string;
101
- /**
102
- * The stable workflow name wrangler registers (`workflows[].name`):
98
+ * The stable workflow name wrangler registers (`exports.<Class>.name`):
103
99
  * `orderPipeline` → `order-pipeline`. Used as the deployed workflow's
104
100
  * identifier when no explicit `name` override is given.
105
101
  */
@@ -108,8 +104,8 @@ declare const workflowDefaultName: (exportName: string) => string;
108
104
  * Declare a durable workflow deployed alongside the app. Pure validation +
109
105
  * branding: codegen discovers the export, emits the `WorkflowEntrypoint`
110
106
  * subclass (`_generated/workflows.ts`), and wires the typed `ctx.workflows`
111
- * handle; the config layer reconciles the wrangler `workflows[]` entry from the
112
- * same definition.
107
+ * handle; the config layer reconciles the wrangler `exports.<Class>` entry from
108
+ * the same definition.
113
109
  *
114
110
  * ```ts
115
111
  * // lunora/workflows.ts
@@ -127,6 +123,10 @@ declare const workflowDefaultName: (exportName: string) => string;
127
123
  * );
128
124
  * return order;
129
125
  * },
126
+ * // Deploy settings, written into the wrangler `exports.<Class>` entry.
127
+ * schedules: ["0 * * * *"],
128
+ * limits: { steps: 25_000 },
129
+ * defaultRetention: { successRetention: "3 days", errorRetention: "30 days" },
130
130
  * });
131
131
  * ```
132
132
  */
@@ -277,6 +277,8 @@ interface RunContextOptions<Params> {
277
277
  env: Record<string, unknown>;
278
278
  event: WorkflowEventLike<Params>;
279
279
  exportName: string;
280
+ /** The invoking context's `ctx.exports`, where Cloudflare exposes the workflows declared in wrangler `exports`. */
281
+ exports?: unknown;
280
282
  fetchImpl?: typeof fetch;
281
283
  /** Native `cloudflare:workflows` `NonRetryableError` — injected by `src/do`; absent in Node tests. */
282
284
  nonRetryableErrorClass?: NativeNonRetryableErrorConstructor;
@@ -337,4 +339,4 @@ interface WaitForEventDeps {
337
339
  * fast.
338
340
  */
339
341
  declare const createWaitForEvent: (deps: WaitForEventDeps) => WorkflowWaitForEventFunction;
340
- export { type LunoraWorkflowsOptions, MAX_BRANCHES, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowBranch, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type WorkflowWaitForEventFunction, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, branch, convertNonRetryableError, createRunStep, createWaitForEvent, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, defineWorkflowEvent, isDuplicateInstanceError, isNonRetryableError, isStepDefinition, isWorkflowDefinition, isWorkflowEventDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
342
+ export { type LunoraWorkflowsOptions, MAX_BRANCHES, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowBranch, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type WorkflowWaitForEventFunction, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, branch, convertNonRetryableError, createRunStep, createWaitForEvent, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, defineWorkflowEvent, isDuplicateInstanceError, isNonRetryableError, isStepDefinition, isWorkflowDefinition, isWorkflowEventDefinition, toNativeNonRetryableError, validateStepArgs, workflowClassName, workflowDefaultName };
package/dist/index.d.ts CHANGED
@@ -1,22 +1,23 @@
1
- import { a as Workflows, L as LunoraWorkflowsOptions, b as WorkflowEventDefinition, S as StepArgsValidator, c as StepConfig, d as StepDefinition, e as WorkflowConfig, W as WorkflowDefinition, f as WorkflowBranch, g as WorkflowInstanceStatus, h as WorkflowEventLike, i as WorkflowStepLike, j as WorkflowRunContext, k as WorkflowLogger, l as WorkflowRunFunction, m as WorkflowRunStepFunction, n as WorkflowWaitForEventFunction } from "./packem_shared/types.d-DKvSidAr.js";
2
- export type { A as ArgsOf, B as BranchCompensationParams, F as FunctionKind, o as FunctionReference, I as InferStepArgs, R as RunFunctionOptions, p as RunStepOptions, q as StepHandler, r as StepRollbackContext, s as StepRollbackHandler, t as StepRunContext, u as WaitForEventOptions, v as WorkflowBindingLike, w as WorkflowBranchOutputs, x as WorkflowCreateOptions, y as WorkflowHandle, z as WorkflowHandler, C as WorkflowInstanceLike, D as WorkflowParallelFunction, E as WorkflowRollbackContextLike, G as WorkflowRollbackHandlerLike, H as WorkflowSpawnFunction, J as WorkflowSpawnOptions, K as WorkflowStatusResult, M as WorkflowStepConfigLike, N as WorkflowStepContextLike, O as WorkflowStepRollbackOptionsLike } from "./packem_shared/types.d-DKvSidAr.js";
1
+ import { a as Workflows, L as LunoraWorkflowsOptions, b as WorkflowEventDefinition, S as StepArgsValidator, c as StepConfig, d as StepDefinition, e as WorkflowConfig, W as WorkflowDefinition, f as WorkflowBranch, g as WorkflowInstanceStatus, h as WorkflowEventLike, i as WorkflowStepLike, j as WorkflowRunContext, k as WorkflowLogger, l as WorkflowRunFunction, m as WorkflowRunStepFunction, n as WorkflowWaitForEventFunction } from "./packem_shared/types.d-5O82Xdxt.js";
2
+ export type { A as ArgsOf, B as BranchCompensationParams, F as FunctionKind, o as FunctionReference, I as InferStepArgs, R as RunFunctionOptions, p as RunStepOptions, q as StepHandler, r as StepRollbackContext, s as StepRollbackHandler, t as StepRunContext, u as WaitForEventOptions, v as WorkflowBatchDeleteResult, w as WorkflowBindingLike, x as WorkflowBranchOutputs, y as WorkflowCreateOptions, z as WorkflowDelayFunctionLike, C as WorkflowHandle, D as WorkflowHandler, E as WorkflowInstanceEventLike, G as WorkflowInstanceLike, H as WorkflowInstanceSubscribeOptionsLike, J as WorkflowInstanceSubscriptionLike, K as WorkflowParallelFunction, M as WorkflowRetention, N as WorkflowRollbackContextLike, O as WorkflowRollbackHandlerLike, P as WorkflowSpawnFunction, Q as WorkflowSpawnOptions, T as WorkflowStatusResult, U as WorkflowStepConfigLike, V as WorkflowStepContextLike, X as WorkflowStepRollbackOptionsLike } from "./packem_shared/types.d-5O82Xdxt.js";
3
3
  import { Validator } from '@lunora/values';
4
4
  import { LunoraError } from '@lunora/errors';
5
5
  /** Wiring info for one declared workflow, emitted by codegen into the generated shard. */
6
6
  interface WorkflowBindingSpec {
7
- /** The Cloudflare `Workflow` binding name, e.g. `WORKFLOW_ORDER_PIPELINE`. */
8
- binding: string;
7
+ /** The workflow's export key — its generated class name, e.g. `OrderPipelineWorkflow`. */
8
+ className: string;
9
9
  /** The `lunora/workflows.ts` export name, e.g. `orderPipeline`. */
10
10
  exportName: string;
11
11
  }
12
12
  /**
13
- * Build the `ctx.workflows` handle for a request: resolve every spec's
14
- * `env[binding]` into the `exportName → Workflow binding` map and wrap it in
15
- * {@link createWorkflows}. A spec whose binding is absent from `env` is skipped
13
+ * Build the `ctx.workflows` handle for a request: resolve every spec's key off
14
+ * the invoking context's `exports` (Cloudflare) or `env` (other hosts) into the
15
+ * `exportName → Workflow binding` map and wrap it in {@link createWorkflows}. A
16
+ * spec whose workflow is absent from both is skipped
16
17
  * here — the helpful "no workflow named …" error is raised lazily by
17
18
  * `workflows.get(name)` when the missing workflow is actually used.
18
19
  */
19
- declare const createWorkflowContext: (env: Record<string, unknown>, specs: ReadonlyArray<WorkflowBindingSpec>) => Workflows;
20
+ declare const createWorkflowContext: (env: Record<string, unknown>, specs: ReadonlyArray<WorkflowBindingSpec>, exports?: unknown) => Workflows;
20
21
  /**
21
22
  * Build the `ctx.workflows` handle from a map of `lunora/workflows.ts` export
22
23
  * name → Cloudflare `Workflow` binding. `get(name)` resolves the typed handle;
@@ -86,20 +87,15 @@ declare const defineStep: <A extends StepArgsValidator, Result>(name: string, co
86
87
  declare const isStepDefinition: (value: unknown) => value is StepDefinition;
87
88
  /**
88
89
  * The generated `WorkflowEntrypoint` class name for a `lunora/workflows.ts`
89
- * export: `orderPipeline` → `OrderPipelineWorkflow`. wrangler's
90
- * `workflows[].class_name` references it, so codegen and the config layer MUST
91
- * derive it identically — always via this helper.
90
+ * export: `orderPipeline` → `OrderPipelineWorkflow`. It is also the workflow's
91
+ * key everywhere at runtime: wrangler's `exports.<Class>` declares it, the
92
+ * invoking context's `ctx.exports.<Class>` reaches it (see
93
+ * `shared/workflow-binding.ts`), so codegen, config and the runtime MUST derive
94
+ * it identically — always via this helper.
92
95
  */
93
96
  declare const workflowClassName: (exportName: string) => string;
94
97
  /**
95
- * The wrangler binding name for a workflow export: `orderPipeline` →
96
- * `WORKFLOW_ORDER_PIPELINE`, `etl` → `WORKFLOW_ETL`. The `WORKFLOW_` prefix
97
- * namespaces these away from `SHARD`/`SESSION`/`SCHEDULER`/`CONTAINER_*` so a
98
- * workflow export can never collide with the built-in bindings.
99
- */
100
- declare const workflowBindingName: (exportName: string) => string;
101
- /**
102
- * The stable workflow name wrangler registers (`workflows[].name`):
98
+ * The stable workflow name wrangler registers (`exports.<Class>.name`):
103
99
  * `orderPipeline` → `order-pipeline`. Used as the deployed workflow's
104
100
  * identifier when no explicit `name` override is given.
105
101
  */
@@ -108,8 +104,8 @@ declare const workflowDefaultName: (exportName: string) => string;
108
104
  * Declare a durable workflow deployed alongside the app. Pure validation +
109
105
  * branding: codegen discovers the export, emits the `WorkflowEntrypoint`
110
106
  * subclass (`_generated/workflows.ts`), and wires the typed `ctx.workflows`
111
- * handle; the config layer reconciles the wrangler `workflows[]` entry from the
112
- * same definition.
107
+ * handle; the config layer reconciles the wrangler `exports.<Class>` entry from
108
+ * the same definition.
113
109
  *
114
110
  * ```ts
115
111
  * // lunora/workflows.ts
@@ -127,6 +123,10 @@ declare const workflowDefaultName: (exportName: string) => string;
127
123
  * );
128
124
  * return order;
129
125
  * },
126
+ * // Deploy settings, written into the wrangler `exports.<Class>` entry.
127
+ * schedules: ["0 * * * *"],
128
+ * limits: { steps: 25_000 },
129
+ * defaultRetention: { successRetention: "3 days", errorRetention: "30 days" },
130
130
  * });
131
131
  * ```
132
132
  */
@@ -277,6 +277,8 @@ interface RunContextOptions<Params> {
277
277
  env: Record<string, unknown>;
278
278
  event: WorkflowEventLike<Params>;
279
279
  exportName: string;
280
+ /** The invoking context's `ctx.exports`, where Cloudflare exposes the workflows declared in wrangler `exports`. */
281
+ exports?: unknown;
280
282
  fetchImpl?: typeof fetch;
281
283
  /** Native `cloudflare:workflows` `NonRetryableError` — injected by `src/do`; absent in Node tests. */
282
284
  nonRetryableErrorClass?: NativeNonRetryableErrorConstructor;
@@ -337,4 +339,4 @@ interface WaitForEventDeps {
337
339
  * fast.
338
340
  */
339
341
  declare const createWaitForEvent: (deps: WaitForEventDeps) => WorkflowWaitForEventFunction;
340
- export { type LunoraWorkflowsOptions, MAX_BRANCHES, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowBranch, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type WorkflowWaitForEventFunction, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, branch, convertNonRetryableError, createRunStep, createWaitForEvent, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, defineWorkflowEvent, isDuplicateInstanceError, isNonRetryableError, isStepDefinition, isWorkflowDefinition, isWorkflowEventDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
342
+ export { type LunoraWorkflowsOptions, MAX_BRANCHES, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowBranch, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type WorkflowWaitForEventFunction, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, branch, convertNonRetryableError, createRunStep, createWaitForEvent, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, defineWorkflowEvent, isDuplicateInstanceError, isNonRetryableError, isStepDefinition, isWorkflowDefinition, isWorkflowEventDefinition, toNativeNonRetryableError, validateStepArgs, workflowClassName, workflowDefaultName };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{createWorkflowContext as e}from"./packem_shared/createWorkflowContext-zQR_9N-v.mjs";import{default as f}from"./packem_shared/createWorkflows-LvAyUyKq.mjs";import{defineWorkflowEvent as a,isWorkflowEventDefinition as i}from"./packem_shared/defineWorkflowEvent-suERPEEV.mjs";import{defineStep as p,isStepDefinition as s}from"./packem_shared/defineStep-D1-9eOnA.mjs";import{defineWorkflow as w,isWorkflowDefinition as x,workflowBindingName as k,workflowClassName as c,workflowDefaultName as E}from"./packem_shared/defineWorkflow-tKaIifbZ.mjs";import{NonRetryableError as N,convertNonRetryableError as R,isNonRetryableError as v,toNativeNonRetryableError as d}from"./packem_shared/NonRetryableError-BPu01mU8.mjs";import{MAX_BRANCHES as u,branch as C}from"./packem_shared/MAX_BRANCHES-j59ZUUSu.mjs";import{WorkflowsRestError as S,createWorkflowsRestClient as y}from"./packem_shared/WorkflowsRestError-Ccq1FUR1.mjs";import{createWorkflowRunContext as g}from"./packem_shared/createWorkflowRunContext-DTYKQowc.mjs";import{c as h,v as F}from"./packem_shared/run-step-CMkT6BI4.mjs";import{createWaitForEvent as I}from"./packem_shared/createWaitForEvent-D5Ohn2Pz.mjs";import{isDuplicateInstanceError as X}from"./packem_shared/isDuplicateInstanceError-CecnqNAa.mjs";export{u as MAX_BRANCHES,N as NonRetryableError,S as WorkflowsRestError,C as branch,R as convertNonRetryableError,h as createRunStep,I as createWaitForEvent,e as createWorkflowContext,g as createWorkflowRunContext,f as createWorkflows,y as createWorkflowsRestClient,p as defineStep,w as defineWorkflow,a as defineWorkflowEvent,X as isDuplicateInstanceError,v as isNonRetryableError,s as isStepDefinition,x as isWorkflowDefinition,i as isWorkflowEventDefinition,d as toNativeNonRetryableError,F as validateStepArgs,k as workflowBindingName,c as workflowClassName,E as workflowDefaultName};
1
+ import{createWorkflowContext as e}from"./packem_shared/createWorkflowContext-CiNtEzpn.mjs";import{default as f}from"./packem_shared/createWorkflows-BTny3jXV.mjs";import{defineWorkflowEvent as n,isWorkflowEventDefinition as i}from"./packem_shared/defineWorkflowEvent-suERPEEV.mjs";import{defineStep as p,isStepDefinition as s}from"./packem_shared/defineStep-D1-9eOnA.mjs";import{defineWorkflow as x,isWorkflowDefinition as w,workflowClassName as c,workflowDefaultName as k}from"./packem_shared/defineWorkflow-DynRL6LP.mjs";import{NonRetryableError as W,convertNonRetryableError as R,isNonRetryableError as N,toNativeNonRetryableError as v}from"./packem_shared/NonRetryableError-BPu01mU8.mjs";import{MAX_BRANCHES as d,branch as u}from"./packem_shared/MAX_BRANCHES-Bcw3dss9.mjs";import{WorkflowsRestError as D,createWorkflowsRestClient as S}from"./packem_shared/WorkflowsRestError-CxLJskBZ.mjs";import{createWorkflowRunContext as A}from"./packem_shared/createWorkflowRunContext-CMweH87g.mjs";import{c as h,v as B}from"./packem_shared/run-step-CMkT6BI4.mjs";import{createWaitForEvent as H}from"./packem_shared/createWaitForEvent-D5Ohn2Pz.mjs";import{isDuplicateInstanceError as M}from"./packem_shared/isDuplicateInstanceError-CecnqNAa.mjs";export{d as MAX_BRANCHES,W as NonRetryableError,D as WorkflowsRestError,u as branch,R as convertNonRetryableError,h as createRunStep,H as createWaitForEvent,e as createWorkflowContext,A as createWorkflowRunContext,f as createWorkflows,S as createWorkflowsRestClient,p as defineStep,x as defineWorkflow,n as defineWorkflowEvent,M as isDuplicateInstanceError,N as isNonRetryableError,s as isStepDefinition,w as isWorkflowDefinition,i as isWorkflowEventDefinition,v as toNativeNonRetryableError,B as validateStepArgs,c as workflowClassName,k as workflowDefaultName};
@@ -0,0 +1 @@
1
+ import{LunoraError as x}from"@lunora/errors";import{h as N,B as A,a as g}from"./branch-marker-CCpWfS5k.mjs";import{r as P}from"./workflow-binding-Dm9hBzx_.mjs";import{RESERVED_EVENT_TYPE_PREFIX as B}from"./defineWorkflowEvent-suERPEEV.mjs";import{NonRetryableError as m}from"./NonRetryableError-BPu01mU8.mjs";import{isDuplicateInstanceError as C}from"./isDuplicateInstanceError-CecnqNAa.mjs";const p=e=>e.toString(16).padStart(4,"0"),k=e=>{let t=8997,n=33826,a=40164,o=52210;for(let s=0;s<e.length;s+=1){t^=e.charCodeAt(s);const l=t*435,d=n*435,h=a*435+t*256,r=o*435+n*256,c=d+(l>>>16),i=h+(c>>>16),u=r+(i>>>16);t=l&65535,n=c&65535,a=i&65535,o=u&65535}return p(o)+p(a)+p(n)+p(t)},v=100,I=100,b="lunora:spawn:",O="lunora:await:",W="lunora:signal:",F="lunora:compensate:",X=17,w=(e,t="")=>e.length+t.length<=I?`${e}${t}`:`${e.slice(0,I-t.length-X)}-${k(e)}${t}`,S=`${B}branch:`,M=/^[A-Z_$][\w$]*Workflow$/u,Q=(e,t,n)=>({compensateWith:n?.compensateWith,id:n?.id,params:t,timeout:n?.timeout,workflow:e}),T=e=>e instanceof Error?{message:e.message,name:e.name}:{message:String(e),name:"Error"},H=e=>({status:"ok",value:e}),Z=e=>({error:T(e),status:"error"}),$=1048576,j=e=>{try{return String(e instanceof Error?e.message:e).slice(0,200)}catch{return"the failure itself could not be described"}},_=e=>{let t;try{t=new TextEncoder().encode(JSON.stringify(e)).length}catch(n){return{error:{message:`branch outcome cannot be serialised to JSON (${j(n)}) — the parent can never receive it. Return a plain JSON value (no cycles, no BigInt, no class instance that fails to serialise) or a reference the parent can dereference (an R2 key, a row id)`,name:"BranchOutputUnserializable"},status:"error"}}return t<=$?e:{error:{message:`branch outcome serialises to ${String(t)} bytes, over Cloudflare's ${String($)}-byte event payload limit — the parent can never receive it. Return a reference the parent can dereference (an R2 key, a row id) instead of the payload itself`,name:"BranchOutputTooLarge"},status:"error"}},E=async(e,t)=>{try{return{attached:!1,instance:await e.create(t)}}catch(n){if(!C(n))throw n;return{attached:!0,instance:await e.get(t.id)}}},D=async e=>{const{error:t,output:n,status:a}=await e.status();if(a==="complete")return H(n);if(a==="errored"||a==="terminated")return{error:t??{message:`branch instance ${a}`,name:"Error"},status:"error"}},L=e=>{if(typeof e!="object"||e===null)return;const{status:t}=e;return t==="error"||t==="ok"?e:void 0};class f extends Error{branchError;kind;plan;constructor(t,n,a){super(n.message),this.branchError=n,this.kind=a,this.plan=t}}const J=async(e,t,n)=>{for(let a=t.length-1;a>=0;a-=1){const o=t[a],s=o?.plan.item.compensateWith;if(!(o===void 0||s===void 0))try{const l=e.resolveBinding(s);await e.step.do(`${F}${o.plan.childId}`,async()=>{const d=w(o.plan.childId,"-compensate"),h={branch:o.plan.item.workflow,error:n,index:o.plan.index,output:o.output};return await E(l,{id:d,params:h}),d})}catch(l){e.log?.error(`ctx.parallel: group-saga compensation "${s}" for branch "${o.plan.item.workflow}" (#${String(o.plan.index)}) failed`,l)}}},ee=e=>async n=>{if(n.length===0)return[];if(n.length>v)throw new m(`ctx.parallel: ${String(n.length)} branches exceeds the cap of ${String(v)} — split the fan-out or raise the work into fewer child workflows`);const a=n.map((r,c)=>{const i=w(e.nextChildId(r.id));return{childId:i,eventType:`${S}${i}`,index:c,item:r}}),o=new Set;for(const r of a){if(o.has(r.childId))throw new m(`ctx.parallel: duplicate branch id "${r.childId}" — each branch in a group must resolve to a unique child instance id (check explicit \`id\` options)`);o.add(r.childId)}const s=await Promise.all(a.map(r=>e.step.do(`${b}${r.childId}`,async()=>{const c=e.resolveBinding(r.item.workflow),i={eventType:r.eventType,index:r.index,parentClassName:e.parentClassName,parentId:e.instanceId},{attached:u,instance:R}=await E(c,{id:r.childId,params:{...r.item.params,[g]:i}});if(!u)return;const y=await D(R);return y===void 0?void 0:_(y)}))),l=Array.from({length:a.length}),d=Array.from({length:a.length}),h=async(r,c)=>{let i;if(c===void 0)try{i=(await e.step.waitForEvent(`${O}${r.childId}`,{timeout:r.item.timeout,type:r.eventType})).payload}catch(u){throw new f(r,T(u),"join failed")}else i=c;if(i.status==="error")throw new f(r,i.error,"failed");d[r.index]={output:i.value,plan:r},l[r.index]=i.value};try{await Promise.all(a.map((r,c)=>h(r,L(s[c]))))}catch(r){throw r instanceof f?(await J(e,d.filter(c=>c!==void 0),r.branchError),new m(`ctx.parallel: branch "${r.plan.item.workflow}" (#${String(r.plan.index)}) ${r.kind}: ${r.branchError.message}`)):r}return l},te=e=>async(t,n,a)=>{if(N(n))throw new x("BAD_REQUEST",`@lunora/workflow: params ${A}`);const o=w(e.nextChildId(a?.id));return await e.step.do(`${b}${o}`,async()=>{const s=e.resolveBinding(t);return await E(s,{id:o,params:n}),o}),e.resolveBinding(t).get(o)},ne=e=>{if(typeof e!="object"||e===null)return;const t=e[g];if(typeof t!="object"||t===null)return;const n=t;if(!(typeof n.eventType!="string"||typeof n.parentClassName!="string"||typeof n.parentId!="string"||typeof n.index!="number")&&!(!M.test(n.parentClassName)||!n.eventType.startsWith(S)))return{eventType:n.eventType,index:n.index,parentClassName:n.parentClassName,parentId:n.parentId}},re=e=>{if(typeof e!="object"||e===null)return e;const t={...e};return Reflect.deleteProperty(t,g),t},K=async(e,t,n)=>{const a=P(e.env,e.exports,t.parentClassName,["get"]);if(a===void 0)return;const o=a.get.bind(a),s=_(n);await e.step.do(`${W}${String(t.index)}`,async()=>(await(await o(t.parentId)).sendEvent({payload:s,type:t.eventType}),t.eventType))},ae=async(e,t,n)=>{try{await K(e,t,n)}catch(a){e.log?.error(`@lunora/workflow: failed to signal branch parent "${t.parentId}" (event "${t.eventType}")`,a)}};export{v as MAX_BRANCHES,Q as branch,ee as createParallel,te as createSpawn,Z as errorOutcome,ne as extractBranchMarker,H as okOutcome,K as signalBranchParent,ae as signalBranchParentSafe,re as stripBranchMarker};
@@ -0,0 +1 @@
1
+ import{LunoraError as g}from"@lunora/errors";const l=256,S=t=>t.length>l?`${t.slice(0,l)}… (truncated)`:t,h="https://api.cloudflare.com/client/v4/accounts",_=async({accountId:t,apiToken:a,fetch:e,init:n,path:r})=>{const s=await(e??globalThis.fetch.bind(globalThis))(`${h}/${encodeURIComponent(t)}${r}`,{...n,headers:{Authorization:`Bearer ${a}`,"Content-Type":"application/json"}}),o=await s.text();let c;try{c=JSON.parse(o)}catch{return{ok:!1,status:s.status,text:o}}return!s.ok||typeof c!="object"||c===null||c.success===!1?{ok:!1,status:s.status,text:o}:{body:c,ok:!0}},A={complete:!0,errored:!0,paused:!0,queued:!0,running:!0,terminated:!0,unknown:!0,waiting:!0,waitingForPause:!0},y=t=>typeof t=="string"&&Object.hasOwn(A,t)?t:"unknown",i=t=>typeof t=="string"&&t!==""?t:void 0,m=(t,a)=>typeof t=="string"?t:a,O=t=>typeof t=="boolean"?t:void 0,b=t=>Array.isArray(t)?t.length:typeof t=="number"?t:void 0,f=t=>({createdOn:i(t.created_on),endedOn:i(t.ended_on),id:m(t.id,""),startedOn:i(t.started_on),status:y(t.status)}),C=t=>({attempts:b(t.attempts),end:i(t.end),error:t.error,name:m(t.name,""),output:t.output,start:i(t.start),success:O(t.success),type:i(t.type)});class $ extends g{constructor(a,e){super("WORKFLOWS_REST_ERROR",`Cloudflare Workflows REST API returned ${String(a)}: ${S(e)}`,{cause:e,name:"WorkflowsRestError",status:a})}}const I=t=>{const a=async(e,n)=>{const r=await _({accountId:t.accountId,apiToken:t.apiToken,...t.fetch===void 0?{}:{fetch:t.fetch},...n===void 0?{}:{init:n},path:`/workflows${e}`});if(!r.ok)throw new $(r.status,r.text);return r.body};return{getInstance:async({instanceId:e,workflowName:n})=>{const s=(await a(`/${encodeURIComponent(n)}/instances/${encodeURIComponent(e)}`)).result??{},o=Array.isArray(s.steps)?s.steps:[];return{...f(s),error:s.error,output:s.output,params:s.params,steps:o.map(c=>C(c))}},listInstances:async({page:e,perPage:n,status:r,workflowName:s})=>{const o=new URLSearchParams;r!==void 0&&o.set("status",r),e!==void 0&&o.set("page",String(e)),n!==void 0&&o.set("per_page",String(n));const c=o.toString()===""?"":`?${o.toString()}`,p=await a(`/${encodeURIComponent(s)}/instances${c}`),d=Array.isArray(p.result)?p.result:[],u=p.result_info??{};return{instances:d.map(R=>f(R)),page:typeof u.page=="number"?u.page:e??1,perPage:typeof u.per_page=="number"?u.per_page:n??d.length,totalCount:typeof u.total_count=="number"?u.total_count:void 0}},setInstanceStatus:async({action:e,instanceId:n,workflowName:r})=>{const o=(await a(`/${encodeURIComponent(r)}/instances/${encodeURIComponent(n)}/status`,{body:JSON.stringify({status:e}),method:"PATCH"})).result??{};return{status:y(o.status)}}}};export{$ as WorkflowsRestError,I as createWorkflowsRestClient};
@@ -0,0 +1 @@
1
+ import{r as s}from"./workflow-binding-Dm9hBzx_.mjs";import a from"./createWorkflows-BTny3jXV.mjs";const l=(t,c,n)=>{const o={};for(const e of c){const r=s(t,n,e.className,["create","createBatch","get"]);r!==void 0&&(o[e.exportName]=r)}return a({bindings:o})};export{l as createWorkflowContext};
@@ -0,0 +1 @@
1
+ import{l as I,d as R,c as x,p as k,w as N}from"./run-step-CMkT6BI4.mjs";import{LunoraError as C}from"@lunora/errors";import{r as T}from"./workflow-binding-Dm9hBzx_.mjs";import{workflowClassName as y}from"./defineWorkflow-DynRL6LP.mjs";import{raiseNonRetryable as v}from"./NonRetryableError-BPu01mU8.mjs";import{createSpawn as O,createParallel as $}from"./MAX_BRANCHES-Bcw3dss9.mjs";import{createWaitForEvent as S}from"./createWaitForEvent-D5Ohn2Pz.mjs";const _=r=>({debug:(t,...n)=>{console.debug(r,t,...n)},error:(t,...n)=>{console.error(r,t,...n)},info:(t,...n)=>{console.info(r,t,...n)},warn:(t,...n)=>{console.warn(r,t,...n)}}),j=r=>{let t="";for(let a=0;a<r.length;a+=32768)t+=String.fromCharCode(...r.subarray(a,a+32768));return btoa(t)},P=r=>{const t=atob(r),n=new Uint8Array(t.length);for(let a=0;a<t.length;a+=1)n[a]=t.codePointAt(a)??0;return n},U="$lunora.wire$",b=64,p=1024,g="__proto__",E={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},h={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},s=(r,t=0)=>{if(t>b)throw new RangeError(`wire-codec: value nesting exceeds the ${b}-level limit`);if(r===null||typeof r!="object")return r;if(Array.isArray(r)){if(r[0]===U)switch(r[1]){case"-inf":return-1/0;case"arr":return r[2].map(e=>s(e,t+1));case"bigint":{const e=r[2];if(typeof e!="string"||e.length>p||!/^-?\d+$/.test(e))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${p} digits)`);return BigInt(e)}case"date":{const e=s(r[2],t+1);if(typeof e!="number")throw new TypeError("wire-codec: malformed date — epoch must be a number");return new Date(e)}case"map":{const e=r[2];return new Map(e.map(o=>{if(!Array.isArray(o)||o.length!==2)throw new TypeError("wire-codec: malformed map entry — expected a [key, value] pair");return[s(o[0],t+1),s(o[1],t+1)]}))}case"set":return new Set(r[2].map(e=>s(e,t+1)));case"url":{const e=r[2];if(typeof e!="string")throw new TypeError("wire-codec: malformed url — href must be a string");return new URL(e)}case"error":{const e=r[2],o=r[3];if(typeof e!="string"||typeof o!="string")throw new TypeError("wire-codec: malformed error — name and message must be strings");const m=(Object.hasOwn(h,e)?h[e]:void 0)??Error,c=new m(o);c.name!==e&&Object.defineProperty(c,"name",{configurable:!0,value:e,writable:!0});const f=s(r[4],t+1);if(f===null||typeof f!="object"||Array.isArray(f))throw new TypeError("wire-codec: malformed error — props must be an object");for(const d of Object.keys(f))d===g?Object.defineProperty(c,d,{configurable:!0,enumerable:!0,value:f[d],writable:!0}):c[d]=f[d];return r.length>5&&Object.defineProperty(c,"cause",{configurable:!0,value:s(r[5],t+1),writable:!0}),c}case"bytes":{const e=r[2];if(typeof e!="string")throw new TypeError("wire-codec: malformed bytes — payload must be a base64 string");const o=P(e);if(j(o)!==e)throw new TypeError("wire-codec: malformed bytes — payload must be canonical padded base64");const m=r[3]??"Uint8Array";if(m==="ArrayBuffer")return o.buffer.byteLength===o.byteLength?o.buffer:o.slice().buffer;const c=Object.hasOwn(E,m)?E[m]:void 0;return c?new c(o.slice().buffer):o}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return r.map(e=>s(e,t+1))}return r.map(i=>s(i,t+1))}const n=r,a={};for(const i of Object.keys(n)){const e=s(n[i],t+1);i===g?Object.defineProperty(a,i,{configurable:!0,enumerable:!0,value:e,writable:!0}):a[i]=e}return a},H=r=>{const t=_(`[workflow:${r.exportName}]`),n=I({env:r.env,fetchImpl:r.fetchImpl,label:"@lunora/workflow"}),a=N(n),i=R(r.exportName,r.event.instanceId),e=k(a,`${i}#body`),o=l=>{const u=y(l),w=T(r.env,r.exports,u,["create","get"]);if(w===void 0)throw new C("INTERNAL",`@lunora/workflow: cannot spawn child workflow "${l}" — no "${u}" on ctx.exports or env (is it declared in lunora/workflows.ts?)`);return w},m=r.exportName.replaceAll(/\W/gu,"_");let c=0;const f=l=>{if(l!==void 0)return l;const u=`${r.event.instanceId}-${m}-c${String(c)}`;return c+=1,u},d={env:r.env,exports:r.exports,instanceId:r.event.instanceId,log:t,nextChildId:f,parentClassName:y(r.exportName),resolveBinding:o,step:r.step},A=(()=>{try{return s(r.event.payload)}catch(l){return v(`@lunora/workflow: workflow "${r.exportName}" params could not be decoded — ${l instanceof Error?l.message:String(l)}`,l,r.nonRetryableErrorClass)}})();return{env:r.env,exports:r.exports,event:r.event,...r.fetchImpl===void 0?{}:{fetchImpl:r.fetchImpl},log:t,parallel:$(d),params:A,run:e,runStep:x({dedupNamespace:i,env:r.env,log:t,nonRetryableErrorClass:r.nonRetryableErrorClass,run:n,step:r.step}),spawn:O(d),step:r.step,waitForEvent:S({nonRetryableErrorClass:r.nonRetryableErrorClass,step:r.step})}};export{H as createWorkflowRunContext};
@@ -0,0 +1 @@
1
+ import{LunoraError as a}from"@lunora/errors";import{h as w,B as l}from"./branch-marker-CCpWfS5k.mjs";import{eventDefinitionProblem as f}from"./defineWorkflowEvent-suERPEEV.mjs";const c=o=>{if(w(o?.params))throw new a("BAD_REQUEST",`@lunora/workflow: params ${l}`)},i=o=>({create:async e=>(c(e),o.create(e)),createBatch:async e=>{for(const r of e)c(r);return o.createBatch(e)},deleteBatch:async e=>o.deleteBatch(e),get:async e=>o.get(e),sendEvent:async(e,r,n)=>{const t=f(r);if(t!==void 0)throw new a("BAD_REQUEST",`@lunora/workflow: sendEvent ${t}`);await(await o.get(e)).sendEvent({payload:r.payload.parse(n),type:r.type})}}),h=o=>{const e=o.bindings??{};return{get:r=>{const n=e[r];if(n===void 0){const t=Object.keys(e),s=t.length===0?"no workflows are declared":`known workflows: ${t.join(", ")}`;throw new a("INTERNAL",`@lunora/workflow: no workflow named "${r}" (${s})`)}return i(n)}}};export{h as default};
@@ -0,0 +1 @@
1
+ const d=e=>`${e.charAt(0).toUpperCase()}${e.slice(1)}Workflow`,w=e=>e.replaceAll(/(?<=[a-z0-9])(?=[A-Z])/g,"-").toLowerCase(),f=e=>typeof e=="string"&&e.trim().length>0,a=e=>{const{defaultRetention:o,limits:r,schedules:n}=e,s=t=>typeof t=="object"&&t!==null;if(n!==void 0&&!(Array.isArray(n)&&n.length>0&&n.every(t=>f(t))))return"`schedules` must be a non-empty array of cron expression strings";const i=s(r)?r.steps:void 0;if(r!==void 0&&(!s(r)||i!==void 0&&!(Number.isInteger(i)&&i>0)))return"`limits` must be an object whose `steps` is a positive integer";const l=s(o)?[o.errorRetention,o.successRetention]:[];if(o!==void 0&&(!s(o)||l.some(t=>t!==void 0&&!f(t))))return'`defaultRetention` must be an object of duration strings (e.g. "7 days")'},u=e=>{if(typeof e.handler!="function")throw new TypeError("defineWorkflow: `handler` must be a function (the workflow body)");if(e.name!==void 0&&(typeof e.name!="string"||e.name.length===0))throw new TypeError("defineWorkflow: `name` must be a non-empty string when provided");const o=a(e);if(o!==void 0)throw new TypeError(`defineWorkflow: ${o}`);return{...e,isLunoraWorkflow:!0}},c=e=>typeof e=="object"&&e!==null&&e.isLunoraWorkflow===!0;export{u as defineWorkflow,c as isWorkflowDefinition,d as workflowClassName,w as workflowDefaultName};
@@ -58,14 +58,59 @@ interface WorkflowCreateOptions<Params = Record<string, unknown>> {
58
58
  id?: string;
59
59
  /** The event payload the instance is triggered with — surfaced as `event.payload`. */
60
60
  params?: Params;
61
- /** Instance retention policy (defaults to the account maximum). */
62
- retention?: {
63
- errorRetention?: string;
64
- successRetention?: string;
65
- };
61
+ /** Instance retention policy (defaults to the workflow's `defaultRetention`, else the plan default). */
62
+ retention?: WorkflowRetention;
63
+ }
64
+ /** Result of `Workflow.deleteBatch`. Mirrors Cloudflare's `WorkflowBatchDeleteResult`: one entry per input position. */
65
+ interface WorkflowBatchDeleteResult {
66
+ deleted: {
67
+ id: string;
68
+ }[];
69
+ errors: {
70
+ code: number;
71
+ id: string;
72
+ message: string;
73
+ }[];
74
+ }
75
+ /**
76
+ * One event a workflow instance emitted, as `WorkflowInstance.subscribe()`
77
+ * streams it. Mirrors Cloudflare's `WorkflowInstanceEvent` loosely: the three
78
+ * fields every event carries are typed, and the per-`type` payload (`stepName`,
79
+ * `attempt`, `output`, `error`, `durationMs`, …) is left open, because the
80
+ * upstream union has thirty members and grows with the engine — a closed copy
81
+ * here would reject the next event kind Cloudflare ships.
82
+ */
83
+ interface WorkflowInstanceEventLike {
84
+ [field: string]: unknown;
85
+ /** Monotonic per-instance id; pass one as `cursor` to resume after it. */
86
+ eventId: number;
87
+ instanceId: string;
88
+ timestamp: number;
89
+ /** `workflow_started`, `step_completed`, `attempt_errored`, `rollback_started`, … */
90
+ type: string;
91
+ }
92
+ /** Options for `WorkflowInstance.subscribe()`, mirroring Cloudflare's subscribe options type. */
93
+ interface WorkflowInstanceSubscribeOptionsLike {
94
+ /** Start after this `eventId` instead of replaying the whole history. */
95
+ cursor?: number;
96
+ /** Only stream events of these types. */
97
+ filter?: string[];
98
+ }
99
+ /**
100
+ * A live subscription to one instance's events, mirroring Cloudflare's
101
+ * subscription type: `next()` replays the history first, then
102
+ * waits for new events, and reports `done` once the instance completes, errors
103
+ * or is terminated. Cloudflare's subscription is also `Disposable`; that half is
104
+ * not mirrored because the ES2024 lib this package compiles against has no
105
+ * `Symbol.dispose`, and the native object keeps it either way.
106
+ */
107
+ interface WorkflowInstanceSubscriptionLike {
108
+ next: () => Promise<IteratorResult<WorkflowInstanceEventLike, void>>;
66
109
  }
67
110
  /** A live handle to a single workflow instance. Mirrors `WorkflowInstance`. */
68
111
  interface WorkflowInstanceLike {
112
+ /** Delete the instance and its stored state, stopping it if it is running. */
113
+ delete: () => Promise<void>;
69
114
  readonly id: string;
70
115
  pause: () => Promise<void>;
71
116
  restart: () => Promise<void>;
@@ -75,6 +120,8 @@ interface WorkflowInstanceLike {
75
120
  type: string;
76
121
  }) => Promise<void>;
77
122
  status: () => Promise<WorkflowStatusResult>;
123
+ /** Stream the instance's events — its full history first, then new ones as it runs. */
124
+ subscribe: (options?: WorkflowInstanceSubscribeOptionsLike) => Promise<WorkflowInstanceSubscriptionLike>;
78
125
  terminate: () => Promise<void>;
79
126
  }
80
127
  /**
@@ -86,6 +133,7 @@ interface WorkflowInstanceLike {
86
133
  interface WorkflowBindingLike<Params = Record<string, unknown>> {
87
134
  create: (options?: WorkflowCreateOptions<Params>) => Promise<WorkflowInstanceLike>;
88
135
  createBatch: (batch: ReadonlyArray<WorkflowCreateOptions<Params>>) => Promise<WorkflowInstanceLike[]>;
136
+ deleteBatch: (instanceIds: ReadonlyArray<string>) => Promise<WorkflowBatchDeleteResult>;
89
137
  get: (id: string) => Promise<WorkflowInstanceLike>;
90
138
  }
91
139
  /** The `event` argument a workflow `run` receives. Mirrors `WorkflowEvent<T>`. */
@@ -95,11 +143,21 @@ interface WorkflowEventLike<Params = Record<string, unknown>> {
95
143
  readonly timestamp: Date;
96
144
  readonly workflowName: string;
97
145
  }
146
+ /**
147
+ * A retry delay computed from the failed attempt. Mirrors `WorkflowDelayFunction`:
148
+ * it receives the failed attempt's step context and error, and returns the wait
149
+ * before the next attempt as a duration.
150
+ */
151
+ type WorkflowDelayFunctionLike = (input: {
152
+ ctx: WorkflowStepContextLike;
153
+ error: Error;
154
+ }) => number | string | Promise<number | string>;
98
155
  /** Per-step durability config. Mirrors the `WorkflowStepConfig.retries` shape. */
99
156
  interface WorkflowStepConfigLike {
100
157
  retries?: {
101
158
  backoff?: "constant" | "exponential" | "linear";
102
- delay?: number | string;
159
+ /** A fixed base delay (scaled by `backoff`), or a function that computes each wait from the failure. */
160
+ delay?: number | string | WorkflowDelayFunctionLike;
103
161
  limit: number;
104
162
  };
105
163
  timeout?: number | string;
@@ -460,6 +518,13 @@ interface WorkflowRunContext<Params = Record<string, unknown>> {
460
518
  readonly env: Record<string, unknown>;
461
519
  /** The triggering event (id, payload, timestamp, workflow name). */
462
520
  readonly event: WorkflowEventLike<Params>;
521
+ /**
522
+ * The invoking context's `ctx.exports` — where Cloudflare exposes the
523
+ * workflows (and agents) declared in wrangler `exports`, keyed by class name.
524
+ * Absent on a host that binds them on `env` instead. A body that resolves a
525
+ * sibling workflow itself (as `@lunora/agent` does) reads both.
526
+ */
527
+ readonly exports?: unknown;
463
528
  /**
464
529
  * The `fetch` the host injected for this run, if it injected one — absent on
465
530
  * a host that relies on the runtime's global.
@@ -492,16 +557,47 @@ interface WorkflowRunContext<Params = Record<string, unknown>> {
492
557
  type WorkflowHandler<Params = Record<string, unknown>, Output = unknown> = (context: WorkflowRunContext<Params>) => Output | Promise<Output>;
493
558
  /** Author-supplied config for `defineWorkflow`. */
494
559
  interface WorkflowConfig<Params = Record<string, unknown>, Output = unknown> {
560
+ /**
561
+ * How long finished instances keep their state and logs unless `create({
562
+ * retention })` says otherwise — written to `exports.<Class>.default_retention`.
563
+ * Durations are Cloudflare's (`"3 days"`, `"12 hours"`); the plan's maximum
564
+ * applies (30 days on Workers Paid, 3 on Free).
565
+ */
566
+ defaultRetention?: WorkflowRetention;
495
567
  /** The workflow body — the multi-step durable program. */
496
568
  handler: WorkflowHandler<Params, Output>;
497
569
  /**
498
- * Optional override for the deployed workflow name — the `workflows[].name`
570
+ * Per-instance limits, written to `exports.<Class>.limits`. `steps` raises (or
571
+ * lowers) the cap on steps one instance may execute — 10,000 by default,
572
+ * up to 25,000.
573
+ */
574
+ limits?: {
575
+ steps?: number;
576
+ };
577
+ /**
578
+ * Optional override for the deployed workflow name — the `exports.<Class>.name`
499
579
  * written to `wrangler.jsonc`. Defaults to a kebab-cased form of the
500
580
  * `lunora/workflows.ts` export name (`orderPipeline` → `order-pipeline`).
501
- * This does NOT change the binding name, which is always derived from the
502
- * export name (`orderPipeline` → `WORKFLOW_ORDER_PIPELINE`).
581
+ * This does NOT change the export key, which is always the generated class
582
+ * name derived from the export name (`orderPipeline` → `OrderPipelineWorkflow`).
503
583
  */
504
584
  name?: string;
585
+ /**
586
+ * Cron expressions that each start a new instance with no params — written
587
+ * to `exports.<Class>.schedules`, so no separate `scheduled()` handler is
588
+ * needed. Five-field Cloudflare cron syntax (`"0 * * * *"`).
589
+ *
590
+ * Deploy configuration: codegen reads these statically, so each entry must
591
+ * be a string literal.
592
+ */
593
+ schedules?: ReadonlyArray<string>;
594
+ }
595
+ /** Instance retention durations. Mirrors `default_retention` / `create({ retention })`. */
596
+ interface WorkflowRetention {
597
+ /** Kept this long after the instance errors. */
598
+ errorRetention?: string;
599
+ /** Kept this long after the instance completes or is terminated. */
600
+ successRetention?: string;
505
601
  }
506
602
  /**
507
603
  * A `defineWorkflow` result — the config plus the runtime brand codegen and the
@@ -526,6 +622,8 @@ interface WorkflowHandle<Params = Record<string, unknown>> {
526
622
  create: (options?: WorkflowCreateOptions<Params>) => Promise<WorkflowInstanceLike>;
527
623
  /** Start many instances in one batched RPC. */
528
624
  createBatch: (batch: ReadonlyArray<WorkflowCreateOptions<Params>>) => Promise<WorkflowInstanceLike[]>;
625
+ /** Delete up to 100 instances and their stored state; ids that do not exist come back as per-instance errors. */
626
+ deleteBatch: (instanceIds: ReadonlyArray<string>) => Promise<WorkflowBatchDeleteResult>;
529
627
  /** Get a handle to an existing instance by id. */
530
628
  get: (id: string) => Promise<WorkflowInstanceLike>;
531
629
  /**
@@ -552,9 +650,9 @@ interface Workflows {
552
650
  interface LunoraWorkflowsOptions {
553
651
  /**
554
652
  * Map of `lunora/workflows.ts` export name → its Cloudflare `Workflow`
555
- * binding. Codegen builds this from `env` (`{ orderPipeline:
556
- * env.WORKFLOW_ORDER_PIPELINE }`); for manual wiring construct it yourself.
653
+ * binding. Codegen builds this from `ctx.exports` (`{ orderPipeline:
654
+ * ctx.exports.OrderPipelineWorkflow }`); for manual wiring construct it yourself.
557
655
  */
558
656
  bindings: Record<string, WorkflowBindingLike>;
559
657
  }
560
- export { ArgsOf as A, BranchCompensationParams as B, WorkflowInstanceLike as C, WorkflowParallelFunction as D, WorkflowRollbackContextLike as E, FunctionKind as F, WorkflowRollbackHandlerLike as G, WorkflowSpawnFunction as H, InferStepArgs as I, WorkflowSpawnOptions as J, WorkflowStatusResult as K, LunoraWorkflowsOptions as L, WorkflowStepConfigLike as M, WorkflowStepContextLike as N, WorkflowStepRollbackOptionsLike as O, RunFunctionOptions as R, StepArgsValidator as S, WorkflowDefinition as W, Workflows as a, WorkflowEventDefinition as b, StepConfig as c, StepDefinition as d, WorkflowConfig as e, WorkflowBranch as f, WorkflowInstanceStatus as g, WorkflowEventLike as h, WorkflowStepLike as i, WorkflowRunContext as j, WorkflowLogger as k, WorkflowRunFunction as l, WorkflowRunStepFunction as m, WorkflowWaitForEventFunction as n, FunctionReference as o, RunStepOptions as p, StepHandler as q, StepRollbackContext as r, StepRollbackHandler as s, StepRunContext as t, WaitForEventOptions as u, WorkflowBindingLike as v, WorkflowBranchOutputs as w, WorkflowCreateOptions as x, WorkflowHandle as y, WorkflowHandler as z };
658
+ export { ArgsOf as A, BranchCompensationParams as B, WorkflowHandle as C, WorkflowHandler as D, WorkflowInstanceEventLike as E, FunctionKind as F, WorkflowInstanceLike as G, WorkflowInstanceSubscribeOptionsLike as H, InferStepArgs as I, WorkflowInstanceSubscriptionLike as J, WorkflowParallelFunction as K, LunoraWorkflowsOptions as L, WorkflowRetention as M, WorkflowRollbackContextLike as N, WorkflowRollbackHandlerLike as O, WorkflowSpawnFunction as P, WorkflowSpawnOptions as Q, RunFunctionOptions as R, StepArgsValidator as S, WorkflowStatusResult as T, WorkflowStepConfigLike as U, WorkflowStepContextLike as V, WorkflowDefinition as W, WorkflowStepRollbackOptionsLike as X, Workflows as a, WorkflowEventDefinition as b, StepConfig as c, StepDefinition as d, WorkflowConfig as e, WorkflowBranch as f, WorkflowInstanceStatus as g, WorkflowEventLike as h, WorkflowStepLike as i, WorkflowRunContext as j, WorkflowLogger as k, WorkflowRunFunction as l, WorkflowRunStepFunction as m, WorkflowWaitForEventFunction as n, FunctionReference as o, RunStepOptions as p, StepHandler as q, StepRollbackContext as r, StepRollbackHandler as s, StepRunContext as t, WaitForEventOptions as u, WorkflowBatchDeleteResult as v, WorkflowBindingLike as w, WorkflowBranchOutputs as x, WorkflowCreateOptions as y, WorkflowDelayFunctionLike as z };
@@ -58,14 +58,59 @@ interface WorkflowCreateOptions<Params = Record<string, unknown>> {
58
58
  id?: string;
59
59
  /** The event payload the instance is triggered with — surfaced as `event.payload`. */
60
60
  params?: Params;
61
- /** Instance retention policy (defaults to the account maximum). */
62
- retention?: {
63
- errorRetention?: string;
64
- successRetention?: string;
65
- };
61
+ /** Instance retention policy (defaults to the workflow's `defaultRetention`, else the plan default). */
62
+ retention?: WorkflowRetention;
63
+ }
64
+ /** Result of `Workflow.deleteBatch`. Mirrors Cloudflare's `WorkflowBatchDeleteResult`: one entry per input position. */
65
+ interface WorkflowBatchDeleteResult {
66
+ deleted: {
67
+ id: string;
68
+ }[];
69
+ errors: {
70
+ code: number;
71
+ id: string;
72
+ message: string;
73
+ }[];
74
+ }
75
+ /**
76
+ * One event a workflow instance emitted, as `WorkflowInstance.subscribe()`
77
+ * streams it. Mirrors Cloudflare's `WorkflowInstanceEvent` loosely: the three
78
+ * fields every event carries are typed, and the per-`type` payload (`stepName`,
79
+ * `attempt`, `output`, `error`, `durationMs`, …) is left open, because the
80
+ * upstream union has thirty members and grows with the engine — a closed copy
81
+ * here would reject the next event kind Cloudflare ships.
82
+ */
83
+ interface WorkflowInstanceEventLike {
84
+ [field: string]: unknown;
85
+ /** Monotonic per-instance id; pass one as `cursor` to resume after it. */
86
+ eventId: number;
87
+ instanceId: string;
88
+ timestamp: number;
89
+ /** `workflow_started`, `step_completed`, `attempt_errored`, `rollback_started`, … */
90
+ type: string;
91
+ }
92
+ /** Options for `WorkflowInstance.subscribe()`, mirroring Cloudflare's subscribe options type. */
93
+ interface WorkflowInstanceSubscribeOptionsLike {
94
+ /** Start after this `eventId` instead of replaying the whole history. */
95
+ cursor?: number;
96
+ /** Only stream events of these types. */
97
+ filter?: string[];
98
+ }
99
+ /**
100
+ * A live subscription to one instance's events, mirroring Cloudflare's
101
+ * subscription type: `next()` replays the history first, then
102
+ * waits for new events, and reports `done` once the instance completes, errors
103
+ * or is terminated. Cloudflare's subscription is also `Disposable`; that half is
104
+ * not mirrored because the ES2024 lib this package compiles against has no
105
+ * `Symbol.dispose`, and the native object keeps it either way.
106
+ */
107
+ interface WorkflowInstanceSubscriptionLike {
108
+ next: () => Promise<IteratorResult<WorkflowInstanceEventLike, void>>;
66
109
  }
67
110
  /** A live handle to a single workflow instance. Mirrors `WorkflowInstance`. */
68
111
  interface WorkflowInstanceLike {
112
+ /** Delete the instance and its stored state, stopping it if it is running. */
113
+ delete: () => Promise<void>;
69
114
  readonly id: string;
70
115
  pause: () => Promise<void>;
71
116
  restart: () => Promise<void>;
@@ -75,6 +120,8 @@ interface WorkflowInstanceLike {
75
120
  type: string;
76
121
  }) => Promise<void>;
77
122
  status: () => Promise<WorkflowStatusResult>;
123
+ /** Stream the instance's events — its full history first, then new ones as it runs. */
124
+ subscribe: (options?: WorkflowInstanceSubscribeOptionsLike) => Promise<WorkflowInstanceSubscriptionLike>;
78
125
  terminate: () => Promise<void>;
79
126
  }
80
127
  /**
@@ -86,6 +133,7 @@ interface WorkflowInstanceLike {
86
133
  interface WorkflowBindingLike<Params = Record<string, unknown>> {
87
134
  create: (options?: WorkflowCreateOptions<Params>) => Promise<WorkflowInstanceLike>;
88
135
  createBatch: (batch: ReadonlyArray<WorkflowCreateOptions<Params>>) => Promise<WorkflowInstanceLike[]>;
136
+ deleteBatch: (instanceIds: ReadonlyArray<string>) => Promise<WorkflowBatchDeleteResult>;
89
137
  get: (id: string) => Promise<WorkflowInstanceLike>;
90
138
  }
91
139
  /** The `event` argument a workflow `run` receives. Mirrors `WorkflowEvent<T>`. */
@@ -95,11 +143,21 @@ interface WorkflowEventLike<Params = Record<string, unknown>> {
95
143
  readonly timestamp: Date;
96
144
  readonly workflowName: string;
97
145
  }
146
+ /**
147
+ * A retry delay computed from the failed attempt. Mirrors `WorkflowDelayFunction`:
148
+ * it receives the failed attempt's step context and error, and returns the wait
149
+ * before the next attempt as a duration.
150
+ */
151
+ type WorkflowDelayFunctionLike = (input: {
152
+ ctx: WorkflowStepContextLike;
153
+ error: Error;
154
+ }) => number | string | Promise<number | string>;
98
155
  /** Per-step durability config. Mirrors the `WorkflowStepConfig.retries` shape. */
99
156
  interface WorkflowStepConfigLike {
100
157
  retries?: {
101
158
  backoff?: "constant" | "exponential" | "linear";
102
- delay?: number | string;
159
+ /** A fixed base delay (scaled by `backoff`), or a function that computes each wait from the failure. */
160
+ delay?: number | string | WorkflowDelayFunctionLike;
103
161
  limit: number;
104
162
  };
105
163
  timeout?: number | string;
@@ -460,6 +518,13 @@ interface WorkflowRunContext<Params = Record<string, unknown>> {
460
518
  readonly env: Record<string, unknown>;
461
519
  /** The triggering event (id, payload, timestamp, workflow name). */
462
520
  readonly event: WorkflowEventLike<Params>;
521
+ /**
522
+ * The invoking context's `ctx.exports` — where Cloudflare exposes the
523
+ * workflows (and agents) declared in wrangler `exports`, keyed by class name.
524
+ * Absent on a host that binds them on `env` instead. A body that resolves a
525
+ * sibling workflow itself (as `@lunora/agent` does) reads both.
526
+ */
527
+ readonly exports?: unknown;
463
528
  /**
464
529
  * The `fetch` the host injected for this run, if it injected one — absent on
465
530
  * a host that relies on the runtime's global.
@@ -492,16 +557,47 @@ interface WorkflowRunContext<Params = Record<string, unknown>> {
492
557
  type WorkflowHandler<Params = Record<string, unknown>, Output = unknown> = (context: WorkflowRunContext<Params>) => Output | Promise<Output>;
493
558
  /** Author-supplied config for `defineWorkflow`. */
494
559
  interface WorkflowConfig<Params = Record<string, unknown>, Output = unknown> {
560
+ /**
561
+ * How long finished instances keep their state and logs unless `create({
562
+ * retention })` says otherwise — written to `exports.<Class>.default_retention`.
563
+ * Durations are Cloudflare's (`"3 days"`, `"12 hours"`); the plan's maximum
564
+ * applies (30 days on Workers Paid, 3 on Free).
565
+ */
566
+ defaultRetention?: WorkflowRetention;
495
567
  /** The workflow body — the multi-step durable program. */
496
568
  handler: WorkflowHandler<Params, Output>;
497
569
  /**
498
- * Optional override for the deployed workflow name — the `workflows[].name`
570
+ * Per-instance limits, written to `exports.<Class>.limits`. `steps` raises (or
571
+ * lowers) the cap on steps one instance may execute — 10,000 by default,
572
+ * up to 25,000.
573
+ */
574
+ limits?: {
575
+ steps?: number;
576
+ };
577
+ /**
578
+ * Optional override for the deployed workflow name — the `exports.<Class>.name`
499
579
  * written to `wrangler.jsonc`. Defaults to a kebab-cased form of the
500
580
  * `lunora/workflows.ts` export name (`orderPipeline` → `order-pipeline`).
501
- * This does NOT change the binding name, which is always derived from the
502
- * export name (`orderPipeline` → `WORKFLOW_ORDER_PIPELINE`).
581
+ * This does NOT change the export key, which is always the generated class
582
+ * name derived from the export name (`orderPipeline` → `OrderPipelineWorkflow`).
503
583
  */
504
584
  name?: string;
585
+ /**
586
+ * Cron expressions that each start a new instance with no params — written
587
+ * to `exports.<Class>.schedules`, so no separate `scheduled()` handler is
588
+ * needed. Five-field Cloudflare cron syntax (`"0 * * * *"`).
589
+ *
590
+ * Deploy configuration: codegen reads these statically, so each entry must
591
+ * be a string literal.
592
+ */
593
+ schedules?: ReadonlyArray<string>;
594
+ }
595
+ /** Instance retention durations. Mirrors `default_retention` / `create({ retention })`. */
596
+ interface WorkflowRetention {
597
+ /** Kept this long after the instance errors. */
598
+ errorRetention?: string;
599
+ /** Kept this long after the instance completes or is terminated. */
600
+ successRetention?: string;
505
601
  }
506
602
  /**
507
603
  * A `defineWorkflow` result — the config plus the runtime brand codegen and the
@@ -526,6 +622,8 @@ interface WorkflowHandle<Params = Record<string, unknown>> {
526
622
  create: (options?: WorkflowCreateOptions<Params>) => Promise<WorkflowInstanceLike>;
527
623
  /** Start many instances in one batched RPC. */
528
624
  createBatch: (batch: ReadonlyArray<WorkflowCreateOptions<Params>>) => Promise<WorkflowInstanceLike[]>;
625
+ /** Delete up to 100 instances and their stored state; ids that do not exist come back as per-instance errors. */
626
+ deleteBatch: (instanceIds: ReadonlyArray<string>) => Promise<WorkflowBatchDeleteResult>;
529
627
  /** Get a handle to an existing instance by id. */
530
628
  get: (id: string) => Promise<WorkflowInstanceLike>;
531
629
  /**
@@ -552,9 +650,9 @@ interface Workflows {
552
650
  interface LunoraWorkflowsOptions {
553
651
  /**
554
652
  * Map of `lunora/workflows.ts` export name → its Cloudflare `Workflow`
555
- * binding. Codegen builds this from `env` (`{ orderPipeline:
556
- * env.WORKFLOW_ORDER_PIPELINE }`); for manual wiring construct it yourself.
653
+ * binding. Codegen builds this from `ctx.exports` (`{ orderPipeline:
654
+ * ctx.exports.OrderPipelineWorkflow }`); for manual wiring construct it yourself.
557
655
  */
558
656
  bindings: Record<string, WorkflowBindingLike>;
559
657
  }
560
- export { ArgsOf as A, BranchCompensationParams as B, WorkflowInstanceLike as C, WorkflowParallelFunction as D, WorkflowRollbackContextLike as E, FunctionKind as F, WorkflowRollbackHandlerLike as G, WorkflowSpawnFunction as H, InferStepArgs as I, WorkflowSpawnOptions as J, WorkflowStatusResult as K, LunoraWorkflowsOptions as L, WorkflowStepConfigLike as M, WorkflowStepContextLike as N, WorkflowStepRollbackOptionsLike as O, RunFunctionOptions as R, StepArgsValidator as S, WorkflowDefinition as W, Workflows as a, WorkflowEventDefinition as b, StepConfig as c, StepDefinition as d, WorkflowConfig as e, WorkflowBranch as f, WorkflowInstanceStatus as g, WorkflowEventLike as h, WorkflowStepLike as i, WorkflowRunContext as j, WorkflowLogger as k, WorkflowRunFunction as l, WorkflowRunStepFunction as m, WorkflowWaitForEventFunction as n, FunctionReference as o, RunStepOptions as p, StepHandler as q, StepRollbackContext as r, StepRollbackHandler as s, StepRunContext as t, WaitForEventOptions as u, WorkflowBindingLike as v, WorkflowBranchOutputs as w, WorkflowCreateOptions as x, WorkflowHandle as y, WorkflowHandler as z };
658
+ export { ArgsOf as A, BranchCompensationParams as B, WorkflowHandle as C, WorkflowHandler as D, WorkflowInstanceEventLike as E, FunctionKind as F, WorkflowInstanceLike as G, WorkflowInstanceSubscribeOptionsLike as H, InferStepArgs as I, WorkflowInstanceSubscriptionLike as J, WorkflowParallelFunction as K, LunoraWorkflowsOptions as L, WorkflowRetention as M, WorkflowRollbackContextLike as N, WorkflowRollbackHandlerLike as O, WorkflowSpawnFunction as P, WorkflowSpawnOptions as Q, RunFunctionOptions as R, StepArgsValidator as S, WorkflowStatusResult as T, WorkflowStepConfigLike as U, WorkflowStepContextLike as V, WorkflowDefinition as W, WorkflowStepRollbackOptionsLike as X, Workflows as a, WorkflowEventDefinition as b, StepConfig as c, StepDefinition as d, WorkflowConfig as e, WorkflowBranch as f, WorkflowInstanceStatus as g, WorkflowEventLike as h, WorkflowStepLike as i, WorkflowRunContext as j, WorkflowLogger as k, WorkflowRunFunction as l, WorkflowRunStepFunction as m, WorkflowWaitForEventFunction as n, FunctionReference as o, RunStepOptions as p, StepHandler as q, StepRollbackContext as r, StepRollbackHandler as s, StepRunContext as t, WaitForEventOptions as u, WorkflowBatchDeleteResult as v, WorkflowBindingLike as w, WorkflowBranchOutputs as x, WorkflowCreateOptions as y, WorkflowDelayFunctionLike as z };
@@ -0,0 +1 @@
1
+ const l=(e,r,o)=>e?.[o]??r?.[o],f=(e,r,o,t)=>{const n=l(e,r,o);if(!(typeof n!="object"||n===null))return t.every(i=>typeof n[i]=="function")?n:void 0};export{f as r};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/workflow",
3
- "version": "1.0.0-alpha.67",
3
+ "version": "1.0.0-alpha.69",
4
4
  "description": "Durable workflows for Lunora: defineWorkflow over Cloudflare Workflows, generated WorkflowEntrypoint classes, and the ctx.workflows surface",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -48,8 +48,8 @@
48
48
  "access": "public"
49
49
  },
50
50
  "dependencies": {
51
- "@lunora/errors": "1.0.0-alpha.45",
52
- "@lunora/values": "1.0.0-alpha.56"
51
+ "@lunora/errors": "1.0.0-alpha.48",
52
+ "@lunora/values": "1.0.0-alpha.58"
53
53
  },
54
54
  "engines": {
55
55
  "node": "^22.15.0 || >=24.11.0"
@@ -1 +0,0 @@
1
- import{LunoraError as R}from"@lunora/errors";import{h as x,B as A,a as g}from"./branch-marker-CCpWfS5k.mjs";import{RESERVED_EVENT_TYPE_PREFIX as P}from"./defineWorkflowEvent-suERPEEV.mjs";import{NonRetryableError as f}from"./NonRetryableError-BPu01mU8.mjs";import{isDuplicateInstanceError as N}from"./isDuplicateInstanceError-CecnqNAa.mjs";const p=t=>t.toString(16).padStart(4,"0"),O=t=>{let e=8997,n=33826,a=40164,o=52210;for(let c=0;c<t.length;c+=1){e^=t.charCodeAt(c);const l=e*435,d=n*435,h=a*435+e*256,r=o*435+n*256,s=d+(l>>>16),i=h+(s>>>16),u=r+(i>>>16);e=l&65535,n=s&65535,a=i&65535,o=u&65535}return p(o)+p(a)+p(n)+p(e)},v=100,I=100,b="lunora:spawn:",k="lunora:await:",C="lunora:signal:",W="lunora:compensate:",F=17,w=(t,e="")=>t.length+e.length<=I?`${t}${e}`:`${t.slice(0,I-e.length-F)}-${O(t)}${e}`,S=`${P}branch:`,G=(t,e,n)=>({compensateWith:n?.compensateWith,id:n?.id,params:e,timeout:n?.timeout,workflow:t}),T=t=>t instanceof Error?{message:t.message,name:t.name}:{message:String(t),name:"Error"},M=t=>({status:"ok",value:t}),U=t=>({error:T(t),status:"error"}),$=1048576,X=t=>{try{return String(t instanceof Error?t.message:t).slice(0,200)}catch{return"the failure itself could not be described"}},B=t=>{let e;try{e=new TextEncoder().encode(JSON.stringify(t)).length}catch(n){return{error:{message:`branch outcome cannot be serialised to JSON (${X(n)}) — the parent can never receive it. Return a plain JSON value (no cycles, no BigInt, no class instance that fails to serialise) or a reference the parent can dereference (an R2 key, a row id)`,name:"BranchOutputUnserializable"},status:"error"}}return e<=$?t:{error:{message:`branch outcome serialises to ${String(e)} bytes, over Cloudflare's ${String($)}-byte event payload limit — the parent can never receive it. Return a reference the parent can dereference (an R2 key, a row id) instead of the payload itself`,name:"BranchOutputTooLarge"},status:"error"}},E=async(t,e)=>{try{return{attached:!1,instance:await t.create(e)}}catch(n){if(!N(n))throw n;return{attached:!0,instance:await t.get(e.id)}}},j=async t=>{const{error:e,output:n,status:a}=await t.status();if(a==="complete")return M(n);if(a==="errored"||a==="terminated")return{error:e??{message:`branch instance ${a}`,name:"Error"},status:"error"}},D=t=>{if(typeof t!="object"||t===null)return;const{status:e}=t;return e==="error"||e==="ok"?t:void 0};class m extends Error{branchError;kind;plan;constructor(e,n,a){super(n.message),this.branchError=n,this.kind=a,this.plan=e}}const H=async(t,e,n)=>{for(let a=e.length-1;a>=0;a-=1){const o=e[a],c=o?.plan.item.compensateWith;if(!(o===void 0||c===void 0))try{const l=t.resolveBinding(c);await t.step.do(`${W}${o.plan.childId}`,async()=>{const d=w(o.plan.childId,"-compensate"),h={branch:o.plan.item.workflow,error:n,index:o.plan.index,output:o.output};return await E(l,{id:d,params:h}),d})}catch(l){t.log?.error(`ctx.parallel: group-saga compensation "${c}" for branch "${o.plan.item.workflow}" (#${String(o.plan.index)}) failed`,l)}}},q=t=>async n=>{if(n.length===0)return[];if(n.length>v)throw new f(`ctx.parallel: ${String(n.length)} branches exceeds the cap of ${String(v)} — split the fan-out or raise the work into fewer child workflows`);const a=n.map((r,s)=>{const i=w(t.nextChildId(r.id));return{childId:i,eventType:`${S}${i}`,index:s,item:r}}),o=new Set;for(const r of a){if(o.has(r.childId))throw new f(`ctx.parallel: duplicate branch id "${r.childId}" — each branch in a group must resolve to a unique child instance id (check explicit \`id\` options)`);o.add(r.childId)}const c=await Promise.all(a.map(r=>t.step.do(`${b}${r.childId}`,async()=>{const s=t.resolveBinding(r.item.workflow),i={eventType:r.eventType,index:r.index,parentBinding:t.parentBinding,parentId:t.instanceId},{attached:u,instance:_}=await E(s,{id:r.childId,params:{...r.item.params,[g]:i}});if(!u)return;const y=await j(_);return y===void 0?void 0:B(y)}))),l=Array.from({length:a.length}),d=Array.from({length:a.length}),h=async(r,s)=>{let i;if(s===void 0)try{i=(await t.step.waitForEvent(`${k}${r.childId}`,{timeout:r.item.timeout,type:r.eventType})).payload}catch(u){throw new m(r,T(u),"join failed")}else i=s;if(i.status==="error")throw new m(r,i.error,"failed");d[r.index]={output:i.value,plan:r},l[r.index]=i.value};try{await Promise.all(a.map((r,s)=>h(r,D(c[s]))))}catch(r){throw r instanceof m?(await H(t,d.filter(s=>s!==void 0),r.branchError),new f(`ctx.parallel: branch "${r.plan.item.workflow}" (#${String(r.plan.index)}) ${r.kind}: ${r.branchError.message}`)):r}return l},Q=t=>async(e,n,a)=>{if(x(n))throw new R("BAD_REQUEST",`@lunora/workflow: params ${A}`);const o=w(t.nextChildId(a?.id));return await t.step.do(`${b}${o}`,async()=>{const c=t.resolveBinding(e);return await E(c,{id:o,params:n}),o}),t.resolveBinding(e).get(o)},Z=t=>{if(typeof t!="object"||t===null)return;const e=t[g];if(typeof e!="object"||e===null)return;const n=e;if(!(typeof n.eventType!="string"||typeof n.parentBinding!="string"||typeof n.parentId!="string"||typeof n.index!="number")&&!(!n.parentBinding.startsWith("WORKFLOW_")||!n.eventType.startsWith(S)))return{eventType:n.eventType,index:n.index,parentBinding:n.parentBinding,parentId:n.parentId}},tt=t=>{if(typeof t!="object"||t===null)return t;const e={...t};return Reflect.deleteProperty(e,g),e},L=async(t,e,n)=>{const a=t.env[e.parentBinding];if(!a||typeof a.get!="function")return;const o=a.get.bind(a),c=B(n);await t.step.do(`${C}${String(e.index)}`,async()=>(await(await o(e.parentId)).sendEvent({payload:c,type:e.eventType}),e.eventType))},et=async(t,e,n)=>{try{await L(t,e,n)}catch(a){t.log?.error(`@lunora/workflow: failed to signal branch parent "${e.parentId}" (event "${e.eventType}")`,a)}};export{v as MAX_BRANCHES,G as branch,q as createParallel,Q as createSpawn,U as errorOutcome,Z as extractBranchMarker,M as okOutcome,L as signalBranchParent,et as signalBranchParentSafe,tt as stripBranchMarker};
@@ -1 +0,0 @@
1
- import{LunoraError as _}from"@lunora/errors";const m=256,A=t=>t.length>m?`${t.slice(0,m)}… (truncated)`:t,$="https://api.cloudflare.com/client/v4/accounts",b={complete:!0,errored:!0,paused:!0,queued:!0,running:!0,terminated:!0,unknown:!0,waiting:!0,waitingForPause:!0},S=t=>typeof t=="string"&&Object.hasOwn(b,t)?t:"unknown",u=t=>typeof t=="string"&&t!==""?t:void 0,R=(t,a)=>typeof t=="string"?t:a,O=t=>typeof t=="boolean"?t:void 0,I=t=>Array.isArray(t)?t.length:typeof t=="number"?t:void 0,f=t=>({createdOn:u(t.created_on),endedOn:u(t.ended_on),id:R(t.id,""),startedOn:u(t.started_on),status:S(t.status)}),C=t=>({attempts:I(t.attempts),end:u(t.end),error:t.error,name:R(t.name,""),output:t.output,start:u(t.start),success:O(t.success),type:u(t.type)});class g extends _{constructor(a,i){super("WORKFLOWS_REST_ERROR",`Cloudflare Workflows REST API returned ${String(a)}: ${A(i)}`,{cause:i,name:"WorkflowsRestError",status:a})}}const E=t=>{const a=t.fetch??globalThis.fetch.bind(globalThis),i=`${$}/${t.accountId}/workflows`,p=async(o,r)=>{const n=await a(`${i}${o}`,{...r,headers:{Authorization:`Bearer ${t.apiToken}`,"Content-Type":"application/json"}}),e=await n.text();let s;try{s=JSON.parse(e)}catch{throw new g(n.status,e)}if(!n.ok||s.success===!1)throw new g(n.status,e);return s};return{getInstance:async({instanceId:o,workflowName:r})=>{const e=(await p(`/${encodeURIComponent(r)}/instances/${encodeURIComponent(o)}`)).result??{},s=Array.isArray(e.steps)?e.steps:[];return{...f(e),error:e.error,output:e.output,params:e.params,steps:s.map(d=>C(d))}},listInstances:async({page:o,perPage:r,status:n,workflowName:e})=>{const s=new URLSearchParams;n!==void 0&&s.set("status",n),o!==void 0&&s.set("page",String(o)),r!==void 0&&s.set("per_page",String(r));const d=s.toString()===""?"":`?${s.toString()}`,l=await p(`/${encodeURIComponent(e)}/instances${d}`),y=Array.isArray(l.result)?l.result:[],c=l.result_info??{};return{instances:y.map(h=>f(h)),page:typeof c.page=="number"?c.page:o??1,perPage:typeof c.per_page=="number"?c.per_page:r??y.length,totalCount:typeof c.total_count=="number"?c.total_count:void 0}},setInstanceStatus:async({action:o,instanceId:r,workflowName:n})=>{const s=(await p(`/${encodeURIComponent(n)}/instances/${encodeURIComponent(r)}/status`,{body:JSON.stringify({status:o}),method:"PATCH"})).result??{};return{status:S(s.status)}}}};export{g as WorkflowsRestError,E as createWorkflowsRestClient};
@@ -1 +0,0 @@
1
- import r from"./createWorkflows-LvAyUyKq.mjs";const i=(n,c)=>{const o={};for(const e of c){const t=n[e.binding];t&&typeof t.create=="function"&&typeof t.createBatch=="function"&&typeof t.get=="function"&&(o[e.exportName]=t)}return r({bindings:o})};export{i as createWorkflowContext};
@@ -1 +0,0 @@
1
- import{l as I,d as R,c as N,p as k,w as T}from"./run-step-CMkT6BI4.mjs";import{LunoraError as C}from"@lunora/errors";import{workflowBindingName as y}from"./defineWorkflow-tKaIifbZ.mjs";import{raiseNonRetryable as O}from"./NonRetryableError-BPu01mU8.mjs";import{createSpawn as $,createParallel as v}from"./MAX_BRANCHES-j59ZUUSu.mjs";import{createWaitForEvent as x}from"./createWaitForEvent-D5Ohn2Pz.mjs";const S=r=>({debug:(n,...t)=>{console.debug(r,n,...t)},error:(n,...t)=>{console.error(r,n,...t)},info:(n,...t)=>{console.info(r,n,...t)},warn:(n,...t)=>{console.warn(r,n,...t)}}),_=r=>{let n="";for(let a=0;a<r.length;a+=32768)n+=String.fromCharCode(...r.subarray(a,a+32768));return btoa(n)},j=r=>{const n=atob(r),t=new Uint8Array(n.length);for(let a=0;a<n.length;a+=1)t[a]=n.codePointAt(a)??0;return t},B="$lunora.wire$",b=64,p=1024,g="__proto__",E={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},h={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},s=(r,n=0)=>{if(n>b)throw new RangeError(`wire-codec: value nesting exceeds the ${b}-level limit`);if(r===null||typeof r!="object")return r;if(Array.isArray(r)){if(r[0]===B)switch(r[1]){case"-inf":return-1/0;case"arr":return r[2].map(e=>s(e,n+1));case"bigint":{const e=r[2];if(typeof e!="string"||e.length>p||!/^-?\d+$/.test(e))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${p} digits)`);return BigInt(e)}case"date":{const e=s(r[2],n+1);if(typeof e!="number")throw new TypeError("wire-codec: malformed date — epoch must be a number");return new Date(e)}case"map":{const e=r[2];return new Map(e.map(o=>{if(!Array.isArray(o)||o.length!==2)throw new TypeError("wire-codec: malformed map entry — expected a [key, value] pair");return[s(o[0],n+1),s(o[1],n+1)]}))}case"set":return new Set(r[2].map(e=>s(e,n+1)));case"url":{const e=r[2];if(typeof e!="string")throw new TypeError("wire-codec: malformed url — href must be a string");return new URL(e)}case"error":{const e=r[2],o=r[3];if(typeof e!="string"||typeof o!="string")throw new TypeError("wire-codec: malformed error — name and message must be strings");const u=(Object.hasOwn(h,e)?h[e]:void 0)??Error,c=new u(o);c.name!==e&&Object.defineProperty(c,"name",{configurable:!0,value:e,writable:!0});const l=s(r[4],n+1);if(l===null||typeof l!="object"||Array.isArray(l))throw new TypeError("wire-codec: malformed error — props must be an object");for(const d of Object.keys(l))d===g?Object.defineProperty(c,d,{configurable:!0,enumerable:!0,value:l[d],writable:!0}):c[d]=l[d];return r.length>5&&Object.defineProperty(c,"cause",{configurable:!0,value:s(r[5],n+1),writable:!0}),c}case"bytes":{const e=r[2];if(typeof e!="string")throw new TypeError("wire-codec: malformed bytes — payload must be a base64 string");const o=j(e);if(_(o)!==e)throw new TypeError("wire-codec: malformed bytes — payload must be canonical padded base64");const u=r[3]??"Uint8Array";if(u==="ArrayBuffer")return o.buffer.byteLength===o.byteLength?o.buffer:o.slice().buffer;const c=Object.hasOwn(E,u)?E[u]:void 0;return c?new c(o.slice().buffer):o}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return r.map(e=>s(e,n+1))}return r.map(i=>s(i,n+1))}const t=r,a={};for(const i of Object.keys(t)){const e=s(t[i],n+1);i===g?Object.defineProperty(a,i,{configurable:!0,enumerable:!0,value:e,writable:!0}):a[i]=e}return a},M=r=>{const n=S(`[workflow:${r.exportName}]`),t=I({env:r.env,fetchImpl:r.fetchImpl,label:"@lunora/workflow"}),a=T(t),i=R(r.exportName,r.event.instanceId),e=k(a,`${i}#body`),o=f=>{const m=y(f),w=r.env[m];if(!w||typeof w.create!="function"||typeof w.get!="function")throw new C("INTERNAL",`@lunora/workflow: cannot spawn child workflow "${f}" — no Workflow binding "${m}" on env (is it declared in lunora/workflows.ts?)`);return w},u=r.exportName.replaceAll(/\W/gu,"_");let c=0;const l=f=>{if(f!==void 0)return f;const m=`${r.event.instanceId}-${u}-c${String(c)}`;return c+=1,m},d={env:r.env,instanceId:r.event.instanceId,log:n,nextChildId:l,parentBinding:y(r.exportName),resolveBinding:o,step:r.step},A=(()=>{try{return s(r.event.payload)}catch(f){return O(`@lunora/workflow: workflow "${r.exportName}" params could not be decoded — ${f instanceof Error?f.message:String(f)}`,f,r.nonRetryableErrorClass)}})();return{env:r.env,event:r.event,...r.fetchImpl===void 0?{}:{fetchImpl:r.fetchImpl},log:n,parallel:v(d),params:A,run:e,runStep:N({dedupNamespace:i,env:r.env,log:n,nonRetryableErrorClass:r.nonRetryableErrorClass,run:t,step:r.step}),spawn:$(d),step:r.step,waitForEvent:x({nonRetryableErrorClass:r.nonRetryableErrorClass,step:r.step})}};export{M as createWorkflowRunContext};
@@ -1 +0,0 @@
1
- import{LunoraError as a}from"@lunora/errors";import{h as w,B as f}from"./branch-marker-CCpWfS5k.mjs";import{eventDefinitionProblem as l}from"./defineWorkflowEvent-suERPEEV.mjs";const c=r=>{if(w(r?.params))throw new a("BAD_REQUEST",`@lunora/workflow: params ${f}`)},i=r=>({create:async o=>(c(o),r.create(o)),createBatch:async o=>{for(const e of o)c(e);return r.createBatch(o)},get:async o=>r.get(o),sendEvent:async(o,e,t)=>{const n=l(e);if(n!==void 0)throw new a("BAD_REQUEST",`@lunora/workflow: sendEvent ${n}`);await(await r.get(o)).sendEvent({payload:e.payload.parse(t),type:e.type})}}),k=r=>{const o=r.bindings??{};return{get:e=>{const t=o[e];if(t===void 0){const n=Object.keys(o),s=n.length===0?"no workflows are declared":`known workflows: ${n.join(", ")}`;throw new a("INTERNAL",`@lunora/workflow: no workflow named "${e}" (${s})`)}return i(t)}}};export{k as default};
@@ -1 +0,0 @@
1
- const e=o=>`${o.charAt(0).toUpperCase()}${o.slice(1)}Workflow`,r=o=>`WORKFLOW_${o.replaceAll(/(?<=[a-z0-9])(?=[A-Z])/g,"_").toUpperCase()}`,n=o=>o.replaceAll(/(?<=[a-z0-9])(?=[A-Z])/g,"-").toLowerCase(),t=o=>{if(typeof o.handler!="function")throw new TypeError("defineWorkflow: `handler` must be a function (the workflow body)");if(o.name!==void 0&&(typeof o.name!="string"||o.name.length===0))throw new TypeError("defineWorkflow: `name` must be a non-empty string when provided");return{...o,isLunoraWorkflow:!0}},l=o=>typeof o=="object"&&o!==null&&o.isLunoraWorkflow===!0;export{t as defineWorkflow,l as isWorkflowDefinition,r as workflowBindingName,e as workflowClassName,n as workflowDefaultName};