@lunora/workflow 1.0.0-alpha.2 → 1.0.0-alpha.21

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.
Files changed (28) hide show
  1. package/LICENSE.md +6 -0
  2. package/dist/do/index.d.mts +16 -16
  3. package/dist/do/index.d.ts +16 -16
  4. package/dist/do/index.mjs +1 -32
  5. package/dist/index.d.mts +127 -132
  6. package/dist/index.d.ts +127 -132
  7. package/dist/index.mjs +1 -8
  8. package/dist/packem_shared/MAX_BRANCHES-L0FzeGTH.mjs +1 -0
  9. package/dist/packem_shared/NonRetryableError-CXD-mZe4.mjs +1 -0
  10. package/dist/packem_shared/WorkflowsRestError--PIoe9uw.mjs +1 -0
  11. package/dist/packem_shared/branch-marker-B2lebQA6.mjs +1 -0
  12. package/dist/packem_shared/createRunStep-CzGKC1eZ.mjs +1 -0
  13. package/dist/packem_shared/createWorkflowContext-Dw8a1U68.mjs +1 -0
  14. package/dist/packem_shared/createWorkflowRunContext-BNh1APpj.mjs +1 -0
  15. package/dist/packem_shared/createWorkflows-3djec-oS.mjs +1 -0
  16. package/dist/packem_shared/defineStep-rJ0XPdAx.mjs +1 -0
  17. package/dist/packem_shared/defineWorkflow-fBuCDkGT.mjs +1 -0
  18. package/dist/packem_shared/{types.d-CQO_koGe.d.mts → types.d-CZ1pcdmw.d.mts} +162 -81
  19. package/dist/packem_shared/{types.d-CQO_koGe.d.ts → types.d-CZ1pcdmw.d.ts} +162 -81
  20. package/package.json +4 -3
  21. package/dist/packem_shared/NonRetryableError-Dn2dTyBS.mjs +0 -27
  22. package/dist/packem_shared/WorkflowsRestError-b06i7K5j.mjs +0 -118
  23. package/dist/packem_shared/createRunStep-8jOXxP2o.mjs +0 -54
  24. package/dist/packem_shared/createWorkflowContext-D6thzmlF.mjs +0 -14
  25. package/dist/packem_shared/createWorkflowLogger-DR8P4ZoY.mjs +0 -76
  26. package/dist/packem_shared/createWorkflows-BoSYVIXg.mjs +0 -23
  27. package/dist/packem_shared/defineStep-DJQtLw7g.mjs +0 -28
  28. package/dist/packem_shared/defineWorkflow-DbUC-oCN.mjs +0 -15
@@ -1,13 +1,13 @@
1
1
  import { ValidatorMap, InferValidatorMap, Validator } from '@lunora/values';
2
2
  /**
3
- * Opaque reference to a Lunora function. Mirrors the `FunctionReference` shape
4
- * emitted by `@lunora/codegen` (and consumed by `@lunora/client`). We avoid a
5
- * direct dependency to keep this package usable from the codegen pipeline
6
- * itself — identical rationale to `@lunora/scheduler`'s copy.
7
- *
8
- * The runtime identifier lives in `__lunoraRef` — this MUST stay in lockstep
9
- * with the codegen emit + `@lunora/client`'s `FunctionReference`.
10
- */
3
+ * Opaque reference to a Lunora function. Mirrors the `FunctionReference` shape
4
+ * emitted by `@lunora/codegen` (and consumed by `@lunora/client`). We avoid a
5
+ * direct dependency to keep this package usable from the codegen pipeline
6
+ * itself — identical rationale to `@lunora/scheduler`'s copy.
7
+ *
8
+ * The runtime identifier lives in `__lunoraRef` — this MUST stay in lockstep
9
+ * with the codegen emit + `@lunora/client`'s `FunctionReference`.
10
+ */
11
11
  interface FunctionReference {
12
12
  readonly __lunoraRef: string;
13
13
  /** Marker phantom type — discriminates queries / mutations / actions. */
@@ -53,17 +53,17 @@ interface WorkflowInstanceLike {
53
53
  terminate: () => Promise<void>;
54
54
  }
55
55
  /**
56
- * The subset of the Cloudflare `Workflow` binding the package consumes.
57
- * `createBatch` is a non-optional method on the real binding (Cloudflare's
58
- * `Workflow` class declares it unconditionally), so it is required here too —
59
- * the handle never has to guard for its absence.
60
- */
56
+ * The subset of the Cloudflare `Workflow` binding the package consumes.
57
+ * `createBatch` is a non-optional method on the real binding (Cloudflare's
58
+ * `Workflow` class declares it unconditionally), so it is required here too —
59
+ * the handle never has to guard for its absence.
60
+ */
61
61
  interface WorkflowBindingLike<Params = Record<string, unknown>> {
62
62
  create: (options?: WorkflowCreateOptions<Params>) => Promise<WorkflowInstanceLike>;
63
63
  createBatch: (batch: ReadonlyArray<WorkflowCreateOptions<Params>>) => Promise<WorkflowInstanceLike[]>;
64
64
  get: (id: string) => Promise<WorkflowInstanceLike>;
65
65
  }
66
- /** The `event` argument a workflow `run` receives. Mirrors `WorkflowEvent&lt;T>`. */
66
+ /** The `event` argument a workflow `run` receives. Mirrors `WorkflowEvent<T>`. */
67
67
  interface WorkflowEventLike<Params = Record<string, unknown>> {
68
68
  readonly instanceId: string;
69
69
  readonly payload: Readonly<Params>;
@@ -80,10 +80,10 @@ interface WorkflowStepConfigLike {
80
80
  timeout?: number | string;
81
81
  }
82
82
  /**
83
- * The per-attempt info Cloudflare passes a `step.do` callback. Mirrors
84
- * `WorkflowStepContext` — `attempt` is the 1-based retry counter (`> 1` on
85
- * retries) and `step` carries the durable step's name + invocation count.
86
- */
83
+ * The per-attempt info Cloudflare passes a `step.do` callback. Mirrors
84
+ * `WorkflowStepContext` — `attempt` is the 1-based retry counter (`> 1` on
85
+ * retries) and `step` carries the durable step's name + invocation count.
86
+ */
87
87
  interface WorkflowStepContextLike {
88
88
  /** 1-based attempt counter — `> 1` means this is a retry. */
89
89
  attempt: number;
@@ -114,19 +114,19 @@ interface WorkflowStepRollbackOptionsLike<T = unknown> {
114
114
  rollbackConfig?: WorkflowStepConfigLike;
115
115
  }
116
116
  /**
117
- * The durable step API Cloudflare hands the workflow body. Mirrors
118
- * `WorkflowStep` — `do` memoizes + retries its callback, `sleep`/`sleepUntil`
119
- * are durable delays, and `waitForEvent` hibernates until an external event.
120
- * `do`'s two overloads mirror Cloudflare's: an optional leading `config` and an
121
- * optional trailing `rollback` (compensation run when a later step fails).
122
- *
123
- * Known mirror gap: Cloudflare constrains `do&lt;T extends Rpc.Serializable&lt;T>>` so
124
- * a non-serializable step result (a function, `Map`, class instance, …) is a
125
- * compile error there. `Rpc.Serializable` lives in `@cloudflare/workers-types`
126
- * and is not Node-importable, so this Node-safe mirror uses a bare `&lt;T>` and
127
- * cannot enforce that — a non-serializable result type-checks here but fails at
128
- * runtime on the platform. Keep step results JSON-serialisable.
129
- */
117
+ * The durable step API Cloudflare hands the workflow body. Mirrors
118
+ * `WorkflowStep` — `do` memoizes + retries its callback, `sleep`/`sleepUntil`
119
+ * are durable delays, and `waitForEvent` hibernates until an external event.
120
+ * `do`'s two overloads mirror Cloudflare's: an optional leading `config` and an
121
+ * optional trailing `rollback` (compensation run when a later step fails).
122
+ *
123
+ * Known mirror gap: Cloudflare constrains `do<T extends Rpc.Serializable<T>>` so
124
+ * a non-serializable step result (a function, `Map`, class instance, …) is a
125
+ * compile error there. `Rpc.Serializable` lives in `@cloudflare/workers-types`
126
+ * and is not Node-importable, so this Node-safe mirror uses a bare `<T>` and
127
+ * cannot enforce that — a non-serializable result type-checks here but fails at
128
+ * runtime on the platform. Keep step results JSON-serialisable.
129
+ */
130
130
  interface WorkflowStepLike {
131
131
  do: {
132
132
  <T>(name: string, callback: (context: WorkflowStepContextLike) => Promise<T>, rollback?: WorkflowStepRollbackOptionsLike<T>): Promise<T>;
@@ -155,25 +155,25 @@ interface RunFunctionOptions {
155
155
  shardKey?: string;
156
156
  }
157
157
  /**
158
- * Calls a Lunora query / mutation / action from inside a workflow and resolves
159
- * with its result. Wrap it in {@link WorkflowStepLike.do} to make the call a
160
- * durable, memoized, retried step:
161
- *
162
- * ```ts
163
- * const charge = await ctx.step.do("charge", () => ctx.run(api.payments.charge, { id }));
164
- * ```
165
- */
158
+ * Calls a Lunora query / mutation / action from inside a workflow and resolves
159
+ * with its result. Wrap it in {@link WorkflowStepLike.do} to make the call a
160
+ * durable, memoized, retried step:
161
+ *
162
+ * ```ts
163
+ * const charge = await ctx.step.do("charge", () => ctx.run(api.payments.charge, { id }));
164
+ * ```
165
+ */
166
166
  type WorkflowRunFunction = <F extends FunctionReference>(function_: F, args?: ArgsOf<F>, options?: RunFunctionOptions) => Promise<unknown>;
167
167
  /** Map of validators describing a step's args record — the same shape a Lunora function's `args` uses. Alias of `@lunora/values`' shared {@link ValidatorMap}. */
168
168
  type StepArgsValidator = ValidatorMap;
169
169
  /** Infer the args object type from a {@link StepArgsValidator} (optional validators → optional keys). Alias of `@lunora/values`' shared {@link InferValidatorMap}. */
170
170
  type InferStepArgs<A extends StepArgsValidator> = InferValidatorMap<A>;
171
171
  /**
172
- * The context a {@link StepDefinition} handler receives as its first argument
173
- * (the validated args are the second). Bundles the native per-attempt info
174
- * (`attempt`, `config`, `step`) with the Worker `env`, the Lunora runner, and a
175
- * logger.
176
- */
172
+ * The context a {@link StepDefinition} handler receives as its first argument
173
+ * (the validated args are the second). Bundles the native per-attempt info
174
+ * (`attempt`, `config`, `step`) with the Worker `env`, the Lunora runner, and a
175
+ * logger.
176
+ */
177
177
  interface StepRunContext {
178
178
  /** 1-based retry counter — `> 1` means Cloudflare is retrying the step. */
179
179
  readonly attempt: number;
@@ -226,10 +226,10 @@ interface StepConfig<A extends StepArgsValidator, Result> {
226
226
  rollbackConfig?: WorkflowStepConfigLike;
227
227
  }
228
228
  /**
229
- * A `defineStep` result — a reusable, schema-validated durable step. Run it from
230
- * a workflow body with `ctx.runStep(step, args)`. The phantom generics carry the
231
- * inferred args + result types to the call site.
232
- */
229
+ * A `defineStep` result — a reusable, schema-validated durable step. Run it from
230
+ * a workflow body with `ctx.runStep(step, args)`. The phantom generics carry the
231
+ * inferred args + result types to the call site.
232
+ */
233
233
  interface StepDefinition<A extends StepArgsValidator = StepArgsValidator, Result = unknown> {
234
234
  /** Validators for the step's args. */
235
235
  readonly args: A;
@@ -254,20 +254,97 @@ interface RunStepOptions {
254
254
  config?: WorkflowStepConfigLike;
255
255
  }
256
256
  /**
257
- * Run a reusable {@link StepDefinition} as a durable, memoized, retried step:
258
- * validates the args before the body runs and the result after (when the step
259
- * declares `returns`), and forwards any rollback handler to Cloudflare.
260
- *
261
- * ```ts
262
- * const data = await ctx.runStep(fetchImage, { imageKey });
263
- * ```
264
- */
257
+ * Run a reusable {@link StepDefinition} as a durable, memoized, retried step:
258
+ * validates the args before the body runs and the result after (when the step
259
+ * declares `returns`), and forwards any rollback handler to Cloudflare.
260
+ *
261
+ * ```ts
262
+ * const data = await ctx.runStep(fetchImage, { imageKey });
263
+ * ```
264
+ */
265
265
  type WorkflowRunStepFunction = <A extends StepArgsValidator, Result>(step: StepDefinition<A, Result>, args: InferStepArgs<A>, options?: RunStepOptions) => Promise<Result>;
266
266
  /**
267
- * The context object passed to a `defineWorkflow` handler. Bundles the native
268
- * Cloudflare durability primitives (`step`, `event`) with the Lunora runner
269
- * (`run`), the reusable-step runner (`runStep`), the Worker `env`, and a logger.
270
- */
267
+ * One branch of a {@link WorkflowParallelFunction} fan-out a declared child
268
+ * workflow (referenced by its `lunora/workflows.ts` export name) plus the params
269
+ * it is created with. The phantom `Output` carries the child's result type into
270
+ * the `ctx.parallel(...)` result tuple. Build one with the `branch(...)` helper.
271
+ */
272
+ interface WorkflowBranch<Output = unknown> {
273
+ /** Phantom marker for the branch output type — never present at runtime. */
274
+ readonly __output?: Output;
275
+ /**
276
+ * Optional group-saga compensation (plan 075 Phase 3): the `lunora/workflows.ts`
277
+ * export name of a workflow to run if a **sibling** branch in the same
278
+ * `ctx.parallel(...)` group fails **after** this branch has already completed.
279
+ * It is spawned fire-and-forget (a durable, replay-safe idempotent create) with
280
+ * {@link BranchCompensationParams} as its `ctx.params`. Omit for no
281
+ * compensation — a group where no branch sets this behaves exactly as a plain
282
+ * fan-out (fail-fast, no rollback).
283
+ */
284
+ readonly compensateWith?: string;
285
+ /** Optional explicit child instance id (defaults to a deterministic parent-derived id). */
286
+ readonly id?: string;
287
+ /** The params the child instance is created with — surfaced as the child's `ctx.params`. */
288
+ readonly params?: Record<string, unknown>;
289
+ /** Optional wait timeout for this branch (the parent's `waitForEvent` timeout). */
290
+ readonly timeout?: number | string;
291
+ /** The `lunora/workflows.ts` export name of the child workflow to run. */
292
+ readonly workflow: string;
293
+ }
294
+ /**
295
+ * The `ctx.params` a group-saga compensation workflow (a branch's
296
+ * {@link WorkflowBranch.compensateWith}) receives when a sibling's failure rolls
297
+ * back the group. Everything is plain-serialisable — the compensation is an
298
+ * ordinary declared workflow, so it can `ctx.runStep(...)` its own undo logic.
299
+ */
300
+ interface BranchCompensationParams {
301
+ /** Index signature: this is a workflow `params` bag, so it is a valid `Record<string, unknown>` payload. */
302
+ [key: string]: unknown;
303
+ /** The export name of the completed branch being compensated. */
304
+ branch: string;
305
+ /** The serialised error of the sibling branch whose failure triggered the group rollback. */
306
+ error: {
307
+ message: string;
308
+ name: string;
309
+ };
310
+ /** Declaration-order index of the completed branch being compensated. */
311
+ index: number;
312
+ /** The completed branch's output value — what it returned before the group failed. */
313
+ output?: unknown;
314
+ }
315
+ /** Map a tuple of {@link WorkflowBranch}es to the tuple of their output types, preserving order. */
316
+ type WorkflowBranchOutputs<B extends ReadonlyArray<WorkflowBranch>> = { -readonly [K in keyof B]: B[K] extends WorkflowBranch<infer Output> ? Output : never; };
317
+ /**
318
+ * Run branches as isolated child workflow instances and resolve with their
319
+ * outputs in declaration order. Each branch gets its own Durable Object (own
320
+ * memory / CPU / retry budget); the parent hibernates while they execute. Rejects
321
+ * (non-retryable) on the first branch that fails.
322
+ *
323
+ * ```ts
324
+ * const [tags, thumb] = await ctx.parallel([
325
+ * branch("imageTag", { key }),
326
+ * branch("thumbnail", { key }),
327
+ * ]);
328
+ * ```
329
+ */
330
+ type WorkflowParallelFunction = <const B extends ReadonlyArray<WorkflowBranch>>(branches: B) => Promise<WorkflowBranchOutputs<B>>;
331
+ /** Per-call options for {@link WorkflowSpawnFunction}. */
332
+ interface WorkflowSpawnOptions {
333
+ /** Explicit child instance id (defaults to a deterministic parent-derived id). */
334
+ id?: string;
335
+ }
336
+ /**
337
+ * Fire-and-forget start of a declared child workflow from inside a workflow body
338
+ * — replay-safe (idempotent create), returns a live handle to the child. Use
339
+ * {@link WorkflowParallelFunction} instead when you need to await results.
340
+ */
341
+ type WorkflowSpawnFunction = (workflow: string, params?: Record<string, unknown>, options?: WorkflowSpawnOptions) => Promise<WorkflowInstanceLike>;
342
+ /**
343
+ * The context object passed to a `defineWorkflow` handler. Bundles the native
344
+ * Cloudflare durability primitives (`step`, `event`) with the Lunora runner
345
+ * (`run`), the reusable-step runner (`runStep`), the fan-out primitives
346
+ * (`parallel` / `spawn`), the Worker `env`, and a logger.
347
+ */
271
348
  interface WorkflowRunContext<Params = Record<string, unknown>> {
272
349
  /** The Worker environment bindings. */
273
350
  readonly env: Record<string, unknown>;
@@ -275,12 +352,16 @@ interface WorkflowRunContext<Params = Record<string, unknown>> {
275
352
  readonly event: WorkflowEventLike<Params>;
276
353
  /** Structured logger surfaced in `wrangler tail` / Studio logs. */
277
354
  readonly log: WorkflowLogger;
355
+ /** Run branches as isolated child workflow instances and await their outputs (declaration-ordered tuple). */
356
+ readonly parallel: WorkflowParallelFunction;
278
357
  /** Convenience alias for `event.payload`. */
279
358
  readonly params: Readonly<Params>;
280
359
  /** Invoke a Lunora function; wrap in `step.do(...)` for durability. */
281
360
  readonly run: WorkflowRunFunction;
282
361
  /** Run a reusable, schema-validated {@link StepDefinition} as a durable step. */
283
362
  readonly runStep: WorkflowRunStepFunction;
363
+ /** Fire-and-forget start of a declared child workflow (replay-safe; returns a live handle). */
364
+ readonly spawn: WorkflowSpawnFunction;
284
365
  /** The native Cloudflare Workflows durable-step API. */
285
366
  readonly step: WorkflowStepLike;
286
367
  }
@@ -291,19 +372,19 @@ interface WorkflowConfig<Params = Record<string, unknown>, Output = unknown> {
291
372
  /** The workflow body — the multi-step durable program. */
292
373
  handler: WorkflowHandler<Params, Output>;
293
374
  /**
294
- * Optional override for the deployed workflow name — the `workflows[].name`
295
- * written to `wrangler.jsonc`. Defaults to a kebab-cased form of the
296
- * `lunora/workflows.ts` export name (`orderPipeline` → `order-pipeline`).
297
- * This does NOT change the binding name, which is always derived from the
298
- * export name (`orderPipeline` → `WORKFLOW_ORDER_PIPELINE`).
299
- */
375
+ * Optional override for the deployed workflow name — the `workflows[].name`
376
+ * written to `wrangler.jsonc`. Defaults to a kebab-cased form of the
377
+ * `lunora/workflows.ts` export name (`orderPipeline` → `order-pipeline`).
378
+ * This does NOT change the binding name, which is always derived from the
379
+ * export name (`orderPipeline` → `WORKFLOW_ORDER_PIPELINE`).
380
+ */
300
381
  name?: string;
301
382
  }
302
383
  /**
303
- * A `defineWorkflow` result — the config plus the runtime brand codegen and the
304
- * config layer use to discover it. The phantom `__params` / `__output` carry
305
- * the inferred types to the generated `ctx.workflows` handle.
306
- */
384
+ * A `defineWorkflow` result — the config plus the runtime brand codegen and the
385
+ * config layer use to discover it. The phantom `__params` / `__output` carry
386
+ * the inferred types to the generated `ctx.workflows` handle.
387
+ */
307
388
  interface WorkflowDefinition<Params = Record<string, unknown>, Output = unknown> extends WorkflowConfig<Params, Output> {
308
389
  /** Phantom marker for the output type — never present at runtime. */
309
390
  readonly __output?: Output;
@@ -313,9 +394,9 @@ interface WorkflowDefinition<Params = Record<string, unknown>, Output = unknown>
313
394
  readonly isLunoraWorkflow: true;
314
395
  }
315
396
  /**
316
- * A typed handle to one declared workflow, addressable from `ctx.workflows`.
317
- * Thin pass-through over the Cloudflare `Workflow` binding.
318
- */
397
+ * A typed handle to one declared workflow, addressable from `ctx.workflows`.
398
+ * Thin pass-through over the Cloudflare `Workflow` binding.
399
+ */
319
400
  interface WorkflowHandle<Params = Record<string, unknown>> {
320
401
  /** Start a new instance (optionally with an id + params). */
321
402
  create: (options?: WorkflowCreateOptions<Params>) => Promise<WorkflowInstanceLike>;
@@ -325,9 +406,9 @@ interface WorkflowHandle<Params = Record<string, unknown>> {
325
406
  get: (id: string) => Promise<WorkflowInstanceLike>;
326
407
  }
327
408
  /**
328
- * The `ctx.workflows` surface available on `MutationCtx` and `ActionCtx`. Each
329
- * declared workflow is reachable by its `lunora/workflows.ts` export name.
330
- */
409
+ * The `ctx.workflows` surface available on `MutationCtx` and `ActionCtx`. Each
410
+ * declared workflow is reachable by its `lunora/workflows.ts` export name.
411
+ */
331
412
  interface Workflows {
332
413
  /** Resolve the handle for a declared workflow by export name. */
333
414
  get: <Params = Record<string, unknown>>(name: string) => WorkflowHandle<Params>;
@@ -335,10 +416,10 @@ interface Workflows {
335
416
  /** Options for `createWorkflows`. */
336
417
  interface LunoraWorkflowsOptions {
337
418
  /**
338
- * Map of `lunora/workflows.ts` export name → its Cloudflare `Workflow`
339
- * binding. Codegen builds this from `env` (`{ orderPipeline:
340
- * env.WORKFLOW_ORDER_PIPELINE }`); for manual wiring construct it yourself.
341
- */
419
+ * Map of `lunora/workflows.ts` export name → its Cloudflare `Workflow`
420
+ * binding. Codegen builds this from `env` (`{ orderPipeline:
421
+ * env.WORKFLOW_ORDER_PIPELINE }`); for manual wiring construct it yourself.
422
+ */
342
423
  bindings: Record<string, WorkflowBindingLike>;
343
424
  }
344
- export { ArgsOf as A, WorkflowStepRollbackOptionsLike as B, FunctionReference as F, InferStepArgs as I, LunoraWorkflowsOptions as L, RunFunctionOptions as R, StepArgsValidator as S, WorkflowDefinition as W, Workflows as a, StepConfig as b, StepDefinition as c, WorkflowConfig as d, WorkflowInstanceStatus as e, WorkflowLogger as f, WorkflowEventLike as g, WorkflowStepLike as h, WorkflowRunContext as i, WorkflowRunFunction as j, WorkflowRunStepFunction as k, RunStepOptions as l, StepHandler as m, StepRollbackContext as n, StepRollbackHandler as o, StepRunContext as p, WorkflowBindingLike as q, WorkflowCreateOptions as r, WorkflowHandle as s, WorkflowHandler as t, WorkflowInstanceLike as u, WorkflowRollbackContextLike as v, WorkflowRollbackHandlerLike as w, WorkflowStatusResult as x, WorkflowStepConfigLike as y, WorkflowStepContextLike as z };
425
+ export { ArgsOf as A, BranchCompensationParams as B, WorkflowSpawnFunction as C, WorkflowSpawnOptions as D, WorkflowStatusResult as E, FunctionReference as F, WorkflowStepConfigLike as G, WorkflowStepContextLike as H, InferStepArgs as I, WorkflowStepRollbackOptionsLike as J, LunoraWorkflowsOptions as L, RunFunctionOptions as R, StepArgsValidator as S, WorkflowDefinition as W, Workflows as a, StepConfig as b, StepDefinition as c, WorkflowConfig as d, WorkflowBranch as e, WorkflowInstanceStatus as f, WorkflowEventLike as g, WorkflowStepLike as h, WorkflowRunContext as i, WorkflowLogger as j, WorkflowRunFunction as k, WorkflowRunStepFunction as l, RunStepOptions as m, StepHandler as n, StepRollbackContext as o, StepRollbackHandler as p, StepRunContext as q, WorkflowBindingLike as r, WorkflowBranchOutputs as s, WorkflowCreateOptions as t, WorkflowHandle as u, WorkflowHandler as v, WorkflowInstanceLike as w, WorkflowParallelFunction as x, WorkflowRollbackContextLike as y, WorkflowRollbackHandlerLike as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/workflow",
3
- "version": "1.0.0-alpha.2",
3
+ "version": "1.0.0-alpha.21",
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",
@@ -23,7 +23,7 @@
23
23
  "directory": "packages/workflow"
24
24
  },
25
25
  "files": [
26
- "dist",
26
+ "./dist",
27
27
  "README.md",
28
28
  "LICENSE.md",
29
29
  "__assets__"
@@ -48,7 +48,8 @@
48
48
  "access": "public"
49
49
  },
50
50
  "dependencies": {
51
- "@lunora/values": "1.0.0-alpha.2"
51
+ "@lunora/errors": "1.0.0-alpha.14",
52
+ "@lunora/values": "1.0.0-alpha.19"
52
53
  },
53
54
  "engines": {
54
55
  "node": "^22.15.0 || >=24.11.0"
@@ -1,27 +0,0 @@
1
- const NON_RETRYABLE_BRAND = "__lunoraNonRetryable";
2
- class NonRetryableError extends Error {
3
- constructor(message, name = "NonRetryableError") {
4
- super(message);
5
- this.name = name;
6
- this[NON_RETRYABLE_BRAND] = true;
7
- }
8
- }
9
- const isNonRetryableError = (value) => value instanceof Error && value[NON_RETRYABLE_BRAND] === true;
10
- const toNativeNonRetryableError = (error, NativeNonRetryableError) => {
11
- const native = new NativeNonRetryableError(error.message, error.name);
12
- if (error.stack !== void 0) {
13
- native.stack = error.stack;
14
- }
15
- if (error.cause !== void 0 && native.cause === void 0) {
16
- native.cause = error.cause;
17
- }
18
- return native;
19
- };
20
- const convertNonRetryableError = (error, NativeNonRetryableError) => {
21
- if (NativeNonRetryableError !== void 0 && isNonRetryableError(error)) {
22
- throw toNativeNonRetryableError(error, NativeNonRetryableError);
23
- }
24
- throw error;
25
- };
26
-
27
- export { NonRetryableError, convertNonRetryableError, isNonRetryableError, toNativeNonRetryableError };
@@ -1,118 +0,0 @@
1
- const API_BASE = "https://api.cloudflare.com/client/v4/accounts";
2
- const KNOWN_STATUSES = {
3
- complete: true,
4
- errored: true,
5
- paused: true,
6
- queued: true,
7
- running: true,
8
- terminated: true,
9
- unknown: true,
10
- waiting: true,
11
- waitingForPause: true
12
- };
13
- const toStatus = (value) => typeof value === "string" && Object.hasOwn(KNOWN_STATUSES, value) ? value : "unknown";
14
- const asString = (value) => typeof value === "string" && value !== "" ? value : void 0;
15
- const stringOr = (value, fallback) => typeof value === "string" ? value : fallback;
16
- const asBoolean = (value) => typeof value === "boolean" ? value : void 0;
17
- const countAttempts = (value) => {
18
- if (Array.isArray(value)) {
19
- return value.length;
20
- }
21
- return typeof value === "number" ? value : void 0;
22
- };
23
- const toSummary = (raw) => {
24
- return {
25
- createdOn: asString(raw["created_on"]),
26
- endedOn: asString(raw["ended_on"]),
27
- id: stringOr(raw["id"], ""),
28
- startedOn: asString(raw["started_on"]),
29
- status: toStatus(raw["status"])
30
- };
31
- };
32
- const toStep = (raw) => {
33
- return {
34
- attempts: countAttempts(raw["attempts"]),
35
- end: asString(raw["end"]),
36
- error: raw["error"],
37
- name: stringOr(raw["name"], ""),
38
- output: raw["output"],
39
- start: asString(raw["start"]),
40
- success: asBoolean(raw["success"]),
41
- type: asString(raw["type"])
42
- };
43
- };
44
- class WorkflowsRestError extends Error {
45
- status;
46
- constructor(status, body) {
47
- super(`Cloudflare Workflows REST API returned ${String(status)}: ${body}`);
48
- this.name = "WorkflowsRestError";
49
- this.status = status;
50
- }
51
- }
52
- const createWorkflowsRestClient = (config) => {
53
- const fetchImpl = config.fetch ?? globalThis.fetch.bind(globalThis);
54
- const base = `${API_BASE}/${config.accountId}/workflows`;
55
- const request = async (path, init) => {
56
- const response = await fetchImpl(`${base}${path}`, {
57
- ...init,
58
- headers: { Authorization: `Bearer ${config.apiToken}`, "Content-Type": "application/json" }
59
- });
60
- const text = await response.text();
61
- let body;
62
- try {
63
- body = JSON.parse(text);
64
- } catch {
65
- throw new WorkflowsRestError(response.status, text);
66
- }
67
- if (!response.ok || body["success"] === false) {
68
- throw new WorkflowsRestError(response.status, text);
69
- }
70
- return body;
71
- };
72
- return {
73
- getInstance: async ({ instanceId, workflowName }) => {
74
- const body = await request(`/${encodeURIComponent(workflowName)}/instances/${encodeURIComponent(instanceId)}`);
75
- const result = body["result"] ?? {};
76
- const steps = Array.isArray(result["steps"]) ? result["steps"] : [];
77
- return {
78
- ...toSummary(result),
79
- error: result["error"],
80
- output: result["output"],
81
- params: result["params"],
82
- steps: steps.map((step) => toStep(step))
83
- };
84
- },
85
- listInstances: async ({ page, perPage, status, workflowName }) => {
86
- const query = new URLSearchParams();
87
- if (status !== void 0) {
88
- query.set("status", status);
89
- }
90
- if (page !== void 0) {
91
- query.set("page", String(page));
92
- }
93
- if (perPage !== void 0) {
94
- query.set("per_page", String(perPage));
95
- }
96
- const suffix = query.toString() === "" ? "" : `?${query.toString()}`;
97
- const body = await request(`/${encodeURIComponent(workflowName)}/instances${suffix}`);
98
- const result = Array.isArray(body["result"]) ? body["result"] : [];
99
- const info = body["result_info"] ?? {};
100
- return {
101
- instances: result.map((instance) => toSummary(instance)),
102
- page: typeof info["page"] === "number" ? info["page"] : page ?? 1,
103
- perPage: typeof info["per_page"] === "number" ? info["per_page"] : perPage ?? result.length,
104
- totalCount: typeof info["total_count"] === "number" ? info["total_count"] : void 0
105
- };
106
- },
107
- setInstanceStatus: async ({ action, instanceId, workflowName }) => {
108
- const body = await request(`/${encodeURIComponent(workflowName)}/instances/${encodeURIComponent(instanceId)}`, {
109
- body: JSON.stringify({ status: action }),
110
- method: "PATCH"
111
- });
112
- const result = body["result"] ?? {};
113
- return { status: toStatus(result["status"]) };
114
- }
115
- };
116
- };
117
-
118
- export { WorkflowsRestError, createWorkflowsRestClient };
@@ -1,54 +0,0 @@
1
- import { parseValidatorMap } from '@lunora/values';
2
- import { convertNonRetryableError, NonRetryableError } from './NonRetryableError-Dn2dTyBS.mjs';
3
-
4
- const validateStepArgs = (validators, source) => parseValidatorMap(validators, source, "step args");
5
- const createRunStep = (deps) => async (step, args, options) => {
6
- const config = options?.config ?? step.config;
7
- const validatedArgs = validateStepArgs(step.args, args);
8
- const callback = async (nativeContext) => {
9
- const stepContext = {
10
- attempt: nativeContext.attempt,
11
- config: nativeContext.config,
12
- env: deps.env,
13
- log: deps.log,
14
- run: deps.run,
15
- step: nativeContext.step
16
- };
17
- let result;
18
- try {
19
- result = await step.handler(stepContext, validatedArgs);
20
- } catch (error) {
21
- return convertNonRetryableError(error, deps.nonRetryableErrorClass);
22
- }
23
- if (!step.returns) {
24
- return result;
25
- }
26
- try {
27
- return step.returns.parse(result);
28
- } catch (error) {
29
- const message = error instanceof Error ? error.message : String(error);
30
- const nonRetryable = new NonRetryableError(`step "${step.name}" returns validation failed: ${message}`);
31
- if (error !== void 0) {
32
- nonRetryable.cause = error;
33
- }
34
- return convertNonRetryableError(nonRetryable, deps.nonRetryableErrorClass);
35
- }
36
- };
37
- const rollbackHandler = step.rollback;
38
- const rollbackOptions = rollbackHandler ? {
39
- rollback: async (rollbackContext) => {
40
- await rollbackHandler({
41
- args: validatedArgs,
42
- env: deps.env,
43
- error: rollbackContext.error,
44
- log: deps.log,
45
- output: rollbackContext.output,
46
- run: deps.run
47
- });
48
- },
49
- rollbackConfig: step.rollbackConfig
50
- } : void 0;
51
- return config === void 0 ? deps.step.do(step.name, callback, rollbackOptions) : deps.step.do(step.name, config, callback, rollbackOptions);
52
- };
53
-
54
- export { createRunStep, validateStepArgs };
@@ -1,14 +0,0 @@
1
- import createWorkflows from './createWorkflows-BoSYVIXg.mjs';
2
-
3
- const createWorkflowContext = (env, specs) => {
4
- const bindings = {};
5
- for (const spec of specs) {
6
- const binding = env[spec.binding];
7
- if (binding && typeof binding.create === "function" && typeof binding.createBatch === "function" && typeof binding.get === "function") {
8
- bindings[spec.exportName] = binding;
9
- }
10
- }
11
- return createWorkflows({ bindings });
12
- };
13
-
14
- export { createWorkflowContext };