@lunora/workflow 1.0.0-alpha.68 → 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 +8 -6
- package/dist/do/index.d.mts +1 -1
- package/dist/do/index.d.ts +1 -1
- package/dist/do/index.mjs +1 -1
- package/dist/index.d.mts +24 -22
- package/dist/index.d.ts +24 -22
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/MAX_BRANCHES-Bcw3dss9.mjs +1 -0
- package/dist/packem_shared/WorkflowsRestError-CxLJskBZ.mjs +1 -0
- package/dist/packem_shared/createWorkflowContext-CiNtEzpn.mjs +1 -0
- package/dist/packem_shared/createWorkflowRunContext-CMweH87g.mjs +1 -0
- package/dist/packem_shared/createWorkflows-BTny3jXV.mjs +1 -0
- package/dist/packem_shared/defineWorkflow-DynRL6LP.mjs +1 -0
- package/dist/packem_shared/{types.d-DKvSidAr.d.mts → types.d-5O82Xdxt.d.mts} +110 -12
- package/dist/packem_shared/{types.d-DKvSidAr.d.ts → types.d-5O82Xdxt.d.ts} +110 -12
- package/dist/packem_shared/workflow-binding-Dm9hBzx_.mjs +1 -0
- package/package.json +3 -3
- package/dist/packem_shared/MAX_BRANCHES-j59ZUUSu.mjs +0 -1
- package/dist/packem_shared/WorkflowsRestError-Ccq1FUR1.mjs +0 -1
- package/dist/packem_shared/createWorkflowContext-zQR_9N-v.mjs +0 -1
- package/dist/packem_shared/createWorkflowRunContext-DTYKQowc.mjs +0 -1
- package/dist/packem_shared/createWorkflows-LvAyUyKq.mjs +0 -1
- package/dist/packem_shared/defineWorkflow-tKaIifbZ.mjs +0 -1
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
|
|
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.
|
|
222
|
+
3. Declare it in `wrangler.jsonc`'s `exports` (Wrangler 4.142.0+):
|
|
221
223
|
|
|
222
224
|
```jsonc
|
|
223
225
|
{
|
|
224
|
-
"
|
|
226
|
+
"exports": { "OrderPipelineWorkflow": { "type": "workflow", "name": "order-pipeline" } },
|
|
225
227
|
}
|
|
226
228
|
```
|
|
227
229
|
|
|
228
|
-
4. Build `ctx.workflows` from the
|
|
230
|
+
4. Build `ctx.workflows` from the invoking context's exports: `createWorkflows({ bindings: { orderPipeline: ctx.exports.OrderPipelineWorkflow } })`.
|
|
229
231
|
|
|
230
|
-
The `workflowClassName` / `
|
|
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
|
|
package/dist/do/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
|
-
import { W as WorkflowDefinition } from "../packem_shared/types.d-
|
|
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
|
package/dist/do/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from 'cloudflare:workers';
|
|
2
|
-
import { W as WorkflowDefinition } from "../packem_shared/types.d-
|
|
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
|
|
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-
|
|
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
|
|
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
|
|
8
|
-
|
|
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
|
-
*
|
|
15
|
-
*
|
|
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
|
|
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`.
|
|
90
|
-
*
|
|
91
|
-
*
|
|
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
|
|
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 `
|
|
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,
|
|
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-
|
|
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
|
|
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
|
|
8
|
-
|
|
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
|
-
*
|
|
15
|
-
*
|
|
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
|
|
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`.
|
|
90
|
-
*
|
|
91
|
-
*
|
|
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
|
|
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 `
|
|
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,
|
|
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-
|
|
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
|
|
62
|
-
retention?:
|
|
63
|
-
|
|
64
|
-
|
|
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
|
|
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
|
-
*
|
|
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
|
|
502
|
-
* export name (`orderPipeline` → `
|
|
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 `
|
|
556
|
-
*
|
|
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,
|
|
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
|
|
62
|
-
retention?:
|
|
63
|
-
|
|
64
|
-
|
|
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
|
|
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
|
-
*
|
|
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
|
|
502
|
-
* export name (`orderPipeline` → `
|
|
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 `
|
|
556
|
-
*
|
|
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,
|
|
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.
|
|
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.
|
|
52
|
-
"@lunora/values": "1.0.0-alpha.
|
|
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};
|