@lunora/workflow 1.0.0-alpha.42 → 1.0.0-alpha.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/do/index.mjs +1 -1
- package/dist/index.d.mts +26 -2
- package/dist/index.d.ts +26 -2
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/MAX_BRANCHES-DfuJVVkv.mjs +1 -0
- package/dist/packem_shared/NonRetryableError-DEZ-5ywF.mjs +1 -0
- package/dist/packem_shared/WorkflowsRestError-Ccq1FUR1.mjs +1 -0
- package/dist/packem_shared/createRunStep-CyGo9Xzh.mjs +1 -0
- package/dist/packem_shared/{createWaitForEvent-DjWsI895.mjs → createWaitForEvent-C4qIHZlR.mjs} +1 -1
- package/dist/packem_shared/{createWorkflowRunContext-C83Yp2Qp.mjs → createWorkflowRunContext-CAGEEWIh.mjs} +1 -1
- package/dist/packem_shared/run-step-BR8XaJbP.mjs +1 -0
- package/package.json +3 -3
- package/dist/packem_shared/MAX_BRANCHES-C05O5LY9.mjs +0 -1
- package/dist/packem_shared/NonRetryableError-9ZqDUzwT.mjs +0 -1
- package/dist/packem_shared/WorkflowsRestError-HhBsn3PQ.mjs +0 -1
- package/dist/packem_shared/createRunStep-DB1SaYfF.mjs +0 -1
- package/dist/packem_shared/run-step-D7XRYstF.mjs +0 -1
package/dist/do/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{WorkflowEntrypoint as p}from"cloudflare:workers";import{NonRetryableError as i}from"cloudflare:workflows";import{convertNonRetryableError as m}from"../packem_shared/NonRetryableError-
|
|
1
|
+
import{WorkflowEntrypoint as p}from"cloudflare:workers";import{NonRetryableError as i}from"cloudflare:workflows";import{convertNonRetryableError as m}from"../packem_shared/NonRetryableError-DEZ-5ywF.mjs";import{extractBranchMarker as f,stripBranchMarker as h,signalBranchParentSafe as l,errorOutcome as u,okOutcome as y}from"../packem_shared/MAX_BRANCHES-DfuJVVkv.mjs";import{createWorkflowRunContext as d}from"../packem_shared/createWorkflowRunContext-CAGEEWIh.mjs";class N extends p{#r;#t;constructor(t,e,o,r){super(t,e),this.#t=o,this.#r=r??"workflow"}async run(t,e){const o=e,r=f(t.payload),c=r?{...t,payload:h(t.payload)}:t,a=d({env:this.env,event:c,exportName:this.#r,nonRetryableErrorClass:i,step:o});let n;try{n=await this.#t.handler(a)}catch(s){return r&&await l({env:this.env,log:a.log,step:o},r,u(s)),m(s,i)}return r&&await l({env:this.env,log:a.log,step:o},r,y(n)),n}}export{N as default};
|
package/dist/index.d.mts
CHANGED
|
@@ -162,6 +162,23 @@ declare const toNativeNonRetryableError: (error: NonRetryableError, NativeNonRet
|
|
|
162
162
|
* Always throws — the `never` return lets callers `return convertNonRetryableError(...)`.
|
|
163
163
|
*/
|
|
164
164
|
declare const convertNonRetryableError: (error: unknown, NativeNonRetryableError: NativeNonRetryableErrorConstructor | undefined) => never;
|
|
165
|
+
/**
|
|
166
|
+
* Whether a `WorkflowBinding.create()` rejection is a duplicate-instance-id
|
|
167
|
+
* error — the idempotency signal that a *previous* attempt's create already
|
|
168
|
+
* applied — as opposed to a transient or config failure (Workflows service
|
|
169
|
+
* error, instance-creation quota, bad params).
|
|
170
|
+
*
|
|
171
|
+
* `step.do` memoizes a step's RESULT, not its side effects: a spawn body that
|
|
172
|
+
* fails after `create` landed is re-run, and only this rejection means the
|
|
173
|
+
* child is already there to attach to. Every other failure MUST surface, so the
|
|
174
|
+
* durable step retries or fails visibly rather than silently attaching to an
|
|
175
|
+
* unrelated instance.
|
|
176
|
+
*
|
|
177
|
+
* Lives here, in the package that owns the Workflows binding contract, so the
|
|
178
|
+
* fan-out spawn and `@lunora/agent`'s sub-agent/channel dispatch cannot drift
|
|
179
|
+
* apart on what counts as "already exists".
|
|
180
|
+
*/
|
|
181
|
+
declare const isDuplicateInstanceError: (error: unknown) => boolean;
|
|
165
182
|
/** Hard cap on branches per `ctx.parallel` call — auto-scale, never silently spawn unbounded DOs. */
|
|
166
183
|
declare const MAX_BRANCHES = 100;
|
|
167
184
|
/**
|
|
@@ -221,7 +238,14 @@ interface WorkflowInstancePage {
|
|
|
221
238
|
perPage: number;
|
|
222
239
|
totalCount?: number;
|
|
223
240
|
}
|
|
224
|
-
/**
|
|
241
|
+
/**
|
|
242
|
+
* Thrown when the REST API responds non-2xx or `success: false`; carries the
|
|
243
|
+
* status plus a capped body preview, with the full body on `cause`.
|
|
244
|
+
*
|
|
245
|
+
* The preview is capped because the Cloudflare API's auth/authorization error
|
|
246
|
+
* text (and its HTML gateway pages) would otherwise ride out verbatim —
|
|
247
|
+
* `WORKFLOWS_REST_ERROR` is non-internal, so the message reaches the browser.
|
|
248
|
+
*/
|
|
225
249
|
declare class WorkflowsRestError extends LunoraError {
|
|
226
250
|
constructor(status: number, body: string);
|
|
227
251
|
}
|
|
@@ -310,4 +334,4 @@ interface WaitForEventDeps {
|
|
|
310
334
|
* fast.
|
|
311
335
|
*/
|
|
312
336
|
declare const createWaitForEvent: (deps: WaitForEventDeps) => WorkflowWaitForEventFunction;
|
|
313
|
-
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, isNonRetryableError, isStepDefinition, isWorkflowDefinition, isWorkflowEventDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
|
|
337
|
+
export { type LunoraWorkflowsOptions, MAX_BRANCHES, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowBranch, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type WorkflowWaitForEventFunction, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, branch, convertNonRetryableError, createRunStep, createWaitForEvent, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, defineWorkflowEvent, isDuplicateInstanceError, isNonRetryableError, isStepDefinition, isWorkflowDefinition, isWorkflowEventDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
|
package/dist/index.d.ts
CHANGED
|
@@ -162,6 +162,23 @@ declare const toNativeNonRetryableError: (error: NonRetryableError, NativeNonRet
|
|
|
162
162
|
* Always throws — the `never` return lets callers `return convertNonRetryableError(...)`.
|
|
163
163
|
*/
|
|
164
164
|
declare const convertNonRetryableError: (error: unknown, NativeNonRetryableError: NativeNonRetryableErrorConstructor | undefined) => never;
|
|
165
|
+
/**
|
|
166
|
+
* Whether a `WorkflowBinding.create()` rejection is a duplicate-instance-id
|
|
167
|
+
* error — the idempotency signal that a *previous* attempt's create already
|
|
168
|
+
* applied — as opposed to a transient or config failure (Workflows service
|
|
169
|
+
* error, instance-creation quota, bad params).
|
|
170
|
+
*
|
|
171
|
+
* `step.do` memoizes a step's RESULT, not its side effects: a spawn body that
|
|
172
|
+
* fails after `create` landed is re-run, and only this rejection means the
|
|
173
|
+
* child is already there to attach to. Every other failure MUST surface, so the
|
|
174
|
+
* durable step retries or fails visibly rather than silently attaching to an
|
|
175
|
+
* unrelated instance.
|
|
176
|
+
*
|
|
177
|
+
* Lives here, in the package that owns the Workflows binding contract, so the
|
|
178
|
+
* fan-out spawn and `@lunora/agent`'s sub-agent/channel dispatch cannot drift
|
|
179
|
+
* apart on what counts as "already exists".
|
|
180
|
+
*/
|
|
181
|
+
declare const isDuplicateInstanceError: (error: unknown) => boolean;
|
|
165
182
|
/** Hard cap on branches per `ctx.parallel` call — auto-scale, never silently spawn unbounded DOs. */
|
|
166
183
|
declare const MAX_BRANCHES = 100;
|
|
167
184
|
/**
|
|
@@ -221,7 +238,14 @@ interface WorkflowInstancePage {
|
|
|
221
238
|
perPage: number;
|
|
222
239
|
totalCount?: number;
|
|
223
240
|
}
|
|
224
|
-
/**
|
|
241
|
+
/**
|
|
242
|
+
* Thrown when the REST API responds non-2xx or `success: false`; carries the
|
|
243
|
+
* status plus a capped body preview, with the full body on `cause`.
|
|
244
|
+
*
|
|
245
|
+
* The preview is capped because the Cloudflare API's auth/authorization error
|
|
246
|
+
* text (and its HTML gateway pages) would otherwise ride out verbatim —
|
|
247
|
+
* `WORKFLOWS_REST_ERROR` is non-internal, so the message reaches the browser.
|
|
248
|
+
*/
|
|
225
249
|
declare class WorkflowsRestError extends LunoraError {
|
|
226
250
|
constructor(status: number, body: string);
|
|
227
251
|
}
|
|
@@ -310,4 +334,4 @@ interface WaitForEventDeps {
|
|
|
310
334
|
* fast.
|
|
311
335
|
*/
|
|
312
336
|
declare const createWaitForEvent: (deps: WaitForEventDeps) => WorkflowWaitForEventFunction;
|
|
313
|
-
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, isNonRetryableError, isStepDefinition, isWorkflowDefinition, isWorkflowEventDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
|
|
337
|
+
export { type LunoraWorkflowsOptions, MAX_BRANCHES, type NativeNonRetryableErrorConstructor, NonRetryableError, type StepArgsValidator, type StepConfig, type StepDefinition, type WorkflowBindingSpec, type WorkflowBranch, type WorkflowConfig, type WorkflowDefinition, type WorkflowEventDefinition, type WorkflowEventLike, type WorkflowInstanceAction, type WorkflowInstanceDetail, type WorkflowInstancePage, type WorkflowInstanceStatus, type WorkflowInstanceSummary, type WorkflowLogger, type WorkflowRunContext, type WorkflowRunFunction, type WorkflowRunStepFunction, type WorkflowStepDetail, type WorkflowStepLike, type WorkflowWaitForEventFunction, type Workflows, type WorkflowsRestClient, type WorkflowsRestConfig, WorkflowsRestError, branch, convertNonRetryableError, createRunStep, createWaitForEvent, createWorkflowContext, createWorkflowRunContext, createWorkflows, createWorkflowsRestClient, defineStep, defineWorkflow, defineWorkflowEvent, isDuplicateInstanceError, isNonRetryableError, isStepDefinition, isWorkflowDefinition, isWorkflowEventDefinition, toNativeNonRetryableError, validateStepArgs, workflowBindingName, workflowClassName, workflowDefaultName };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createWorkflowContext as e}from"./packem_shared/createWorkflowContext-zQR_9N-v.mjs";import{default as f}from"./packem_shared/createWorkflows-LvAyUyKq.mjs";import{defineWorkflowEvent as a,isWorkflowEventDefinition as i}from"./packem_shared/defineWorkflowEvent-suERPEEV.mjs";import{defineStep as
|
|
1
|
+
import{createWorkflowContext as e}from"./packem_shared/createWorkflowContext-zQR_9N-v.mjs";import{default as f}from"./packem_shared/createWorkflows-LvAyUyKq.mjs";import{defineWorkflowEvent as a,isWorkflowEventDefinition as i}from"./packem_shared/defineWorkflowEvent-suERPEEV.mjs";import{defineStep as s,isStepDefinition as p}from"./packem_shared/defineStep-D1-9eOnA.mjs";import{defineWorkflow as m,isWorkflowDefinition as x,workflowBindingName as k,workflowClassName as c,workflowDefaultName as E}from"./packem_shared/defineWorkflow-tKaIifbZ.mjs";import{NonRetryableError as N,convertNonRetryableError as R,isDuplicateInstanceError as v,isNonRetryableError as d,toNativeNonRetryableError as b}from"./packem_shared/NonRetryableError-DEZ-5ywF.mjs";import{MAX_BRANCHES as C,branch as D}from"./packem_shared/MAX_BRANCHES-DfuJVVkv.mjs";import{WorkflowsRestError as y,createWorkflowsRestClient as A}from"./packem_shared/WorkflowsRestError-Ccq1FUR1.mjs";import{createWorkflowRunContext as B}from"./packem_shared/createWorkflowRunContext-CAGEEWIh.mjs";import{c as F,v as H}from"./packem_shared/run-step-BR8XaJbP.mjs";import{createWaitForEvent as M}from"./packem_shared/createWaitForEvent-C4qIHZlR.mjs";export{C as MAX_BRANCHES,N as NonRetryableError,y as WorkflowsRestError,D as branch,R as convertNonRetryableError,F as createRunStep,M as createWaitForEvent,e as createWorkflowContext,B as createWorkflowRunContext,f as createWorkflows,A as createWorkflowsRestClient,s as defineStep,m as defineWorkflow,a as defineWorkflowEvent,v as isDuplicateInstanceError,d as isNonRetryableError,p as isStepDefinition,x as isWorkflowDefinition,i as isWorkflowEventDefinition,b as toNativeNonRetryableError,H as validateStepArgs,k as workflowBindingName,c as workflowClassName,E as workflowDefaultName};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as v}from"@lunora/errors";import{h as I,B as $,a as p}from"./branch-marker-CCpWfS5k.mjs";import{RESERVED_EVENT_TYPE_PREFIX as b}from"./defineWorkflowEvent-suERPEEV.mjs";import{NonRetryableError as u,isDuplicateInstanceError as B}from"./NonRetryableError-DEZ-5ywF.mjs";const g=100,w="lunora:spawn:",S="lunora:await:",T="lunora:signal:",R="lunora:compensate:",y=`${b}branch:`,F=(e,r,t)=>({compensateWith:t?.compensateWith,id:t?.id,params:r,timeout:t?.timeout,workflow:e}),E=e=>e instanceof Error?{message:e.message,name:e.name}:{message:String(e),name:"Error"},W=e=>({status:"ok",value:e}),M=e=>({error:E(e),status:"error"}),m=1048576,f=async(e,r)=>{try{return await e.create(r)}catch(t){if(!B(t))throw t;return await e.get(r.id)}};class h extends Error{branchError;kind;plan;constructor(r,t,a){super(t.message),this.branchError=t,this.kind=a,this.plan=r}}const x=async(e,r,t)=>{for(let a=r.length-1;a>=0;a-=1){const i=r[a],c=i?.plan.item.compensateWith;if(!(i===void 0||c===void 0))try{const s=e.resolveBinding(c);await e.step.do(`${R}${i.plan.childId}`,async()=>{const d=`${i.plan.childId}:compensate`,n={branch:i.plan.item.workflow,error:t,index:i.plan.index,output:i.output};return await f(s,{id:d,params:n}),d})}catch(s){e.log?.error(`ctx.parallel: group-saga compensation "${c}" for branch "${i.plan.item.workflow}" (#${String(i.plan.index)}) failed`,s)}}},X=e=>async t=>{if(t.length===0)return[];if(t.length>g)throw new u(`ctx.parallel: ${String(t.length)} branches exceeds the cap of ${String(g)} — split the fan-out or raise the work into fewer child workflows`);const a=t.map((n,o)=>{const l=e.nextChildId(n.id);return{childId:l,eventType:`${y}${l}`,index:o,item:n}}),i=new Set;for(const n of a){if(i.has(n.childId))throw new u(`ctx.parallel: duplicate branch id "${n.childId}" — each branch in a group must resolve to a unique child instance id (check explicit \`id\` options)`);i.add(n.childId)}await Promise.all(a.map(n=>e.step.do(`${w}${n.childId}`,async()=>{const o=e.resolveBinding(n.item.workflow),l={eventType:n.eventType,index:n.index,parentBinding:e.parentBinding,parentId:e.instanceId};return await f(o,{id:n.childId,params:{...n.item.params,[p]:l}}),n.childId})));const c=Array.from({length:a.length}),s=Array.from({length:a.length}),d=async n=>{let o;try{o=(await e.step.waitForEvent(`${S}${n.childId}`,{timeout:n.item.timeout,type:n.eventType})).payload}catch(l){throw new h(n,E(l),"join failed")}if(o.status==="error")throw new h(n,o.error,"failed");s[n.index]={output:o.value,plan:n},c[n.index]=o.value};try{await Promise.all(a.map(n=>d(n)))}catch(n){throw n instanceof h?(await x(e,s.filter(o=>o!==void 0),n.branchError),new u(`ctx.parallel: branch "${n.plan.item.workflow}" (#${String(n.plan.index)}) ${n.kind}: ${n.branchError.message}`)):n}return c},j=e=>async(r,t,a)=>{if(I(t))throw new v("BAD_REQUEST",`@lunora/workflow: params ${$}`);const i=e.nextChildId(a?.id);return await e.step.do(`${w}${i}`,async()=>{const c=e.resolveBinding(r);return await f(c,{id:i,params:t}),i}),e.resolveBinding(r).get(i)},J=e=>{if(typeof e!="object"||e===null)return;const r=e[p];if(typeof r!="object"||r===null)return;const t=r;if(!(typeof t.eventType!="string"||typeof t.parentBinding!="string"||typeof t.parentId!="string"||typeof t.index!="number")&&!(!t.parentBinding.startsWith("WORKFLOW_")||!t.eventType.startsWith(y)))return{eventType:t.eventType,index:t.index,parentBinding:t.parentBinding,parentId:t.parentId}},L=e=>{if(typeof e!="object"||e===null)return e;const r={...e};return Reflect.deleteProperty(r,p),r},_=e=>{try{return String(e instanceof Error?e.message:e).slice(0,200)}catch{return"the failure itself could not be described"}},P=e=>{let r;try{r=new TextEncoder().encode(JSON.stringify(e)).length}catch(t){return{error:{message:`branch outcome cannot be serialised to JSON (${_(t)}) — 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 r<=m?e:{error:{message:`branch outcome serialises to ${String(r)} bytes, over Cloudflare's ${String(m)}-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"}},A=async(e,r,t)=>{const a=e.env[r.parentBinding];if(!a||typeof a.get!="function")return;const i=a.get.bind(a),c=P(t);await e.step.do(`${T}${String(r.index)}`,async()=>(await(await i(r.parentId)).sendEvent({payload:c,type:r.eventType}),r.eventType))},D=async(e,r,t)=>{try{await A(e,r,t)}catch(a){e.log?.error(`@lunora/workflow: failed to signal branch parent "${r.parentId}" (event "${r.eventType}")`,a)}};export{g as MAX_BRANCHES,F as branch,X as createParallel,j as createSpawn,M as errorOutcome,J as extractBranchMarker,W as okOutcome,A as signalBranchParent,D as signalBranchParentSafe,L as stripBranchMarker};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const o="__lunoraNonRetryable";class a extends Error{constructor(s,n="NonRetryableError"){super(s),this.name=n,this[o]=!0}}const c=t=>t instanceof Error&&t[o]===!0,i=(t,s)=>{const n=new s(t.message,t.name);return t.stack!==void 0&&(n.stack=t.stack),t.cause!==void 0&&n.cause===void 0&&(n.cause=t.cause),n},r=(t,s)=>{throw s!==void 0&&c(t)?i(t,s):t},E=(t,s,n)=>{const e=new a(t);return s!==void 0&&(e.cause=s),r(e,n)},u=/already[\s-]?exists/iu,N=t=>u.test(t instanceof Error?t.message:String(t));export{a as NonRetryableError,r as convertNonRetryableError,N as isDuplicateInstanceError,c as isNonRetryableError,E as raiseNonRetryable,i as toNativeNonRetryableError};
|
|
@@ -0,0 +1 @@
|
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as p,v as o}from"./run-step-BR8XaJbP.mjs";import"./defineWorkflowEvent-suERPEEV.mjs";import"./NonRetryableError-DEZ-5ywF.mjs";export{p as createRunStep,o as validateStepArgs};
|
package/dist/packem_shared/{createWaitForEvent-DjWsI895.mjs → createWaitForEvent-C4qIHZlR.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{eventDefinitionProblem as m,RESERVED_EVENT_TYPE_PREFIX as i}from"./defineWorkflowEvent-suERPEEV.mjs";import{raiseNonRetryable as a}from"./NonRetryableError-
|
|
1
|
+
import{eventDefinitionProblem as m,RESERVED_EVENT_TYPE_PREFIX as i}from"./defineWorkflowEvent-suERPEEV.mjs";import{raiseNonRetryable as a}from"./NonRetryableError-DEZ-5ywF.mjs";const c=e=>async(r,t)=>{const n=m(r);if(n!==void 0)return a(`@lunora/workflow: ctx.waitForEvent ${n}`,void 0,e.nonRetryableErrorClass);if(t?.name?.startsWith(i)===!0)return a(`@lunora/workflow: ctx.waitForEvent step name "${t.name}" is reserved — the "${i}" prefix is used by the framework's own steps`,void 0,e.nonRetryableErrorClass);const s=await e.step.waitForEvent(t?.name??`event:${r.type}`,{timeout:t?.timeout,type:r.type});try{return r.payload.parse(s.payload)}catch(o){const l=o instanceof Error?o.message:String(o);return a(`@lunora/workflow: event "${r.type}" payload validation failed: ${l}`,o,e.nonRetryableErrorClass)}};export{c as createWaitForEvent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{J as w,c as v}from"./run-step-BR8XaJbP.mjs";import{LunoraError as i}from"@lunora/errors";import{workflowBindingName as s}from"./defineWorkflow-tKaIifbZ.mjs";import{createSpawn as u,createParallel as m}from"./MAX_BRANCHES-DfuJVVkv.mjs";import{createWaitForEvent as p}from"./createWaitForEvent-C4qIHZlR.mjs";const g=e=>({debug:(r,...n)=>{console.debug(e,r,...n)},error:(r,...n)=>{console.error(e,r,...n)},info:(r,...n)=>{console.info(e,r,...n)},warn:(r,...n)=>{console.warn(e,r,...n)}}),I=e=>{const r=g(`[workflow:${e.exportName}]`),n=w({env:e.env,fetchImpl:e.fetchImpl,label:"@lunora/workflow"}),f=t=>{const a=s(t),o=e.env[a];if(!o||typeof o.create!="function"||typeof o.get!="function")throw new i("INTERNAL",`@lunora/workflow: cannot spawn child workflow "${t}" — no Workflow binding "${a}" on env (is it declared in lunora/workflows.ts?)`);return o};let l=0;const d=t=>{if(t!==void 0)return t;const a=`${e.event.instanceId}-c${String(l)}`;return l+=1,a},c={env:e.env,instanceId:e.event.instanceId,log:r,nextChildId:d,parentBinding:s(e.exportName),resolveBinding:f,step:e.step};return{env:e.env,event:e.event,log:r,parallel:m(c),params:e.event.payload,run:n,runStep:v({env:e.env,log:r,nonRetryableErrorClass:e.nonRetryableErrorClass,run:n,step:e.step}),spawn:u(c),step:e.step,waitForEvent:p({nonRetryableErrorClass:e.nonRetryableErrorClass,step:e.step})}};export{I as createWorkflowRunContext};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as m,isLunoraError as $}from"@lunora/errors";import{parseValidatorMap as S}from"@lunora/values";import{RESERVED_EVENT_TYPE_PREFIX as E}from"./defineWorkflowEvent-suERPEEV.mjs";import{raiseNonRetryable as N,convertNonRetryableError as O}from"./NonRetryableError-DEZ-5ywF.mjs";const _=(t,r,e)=>{if(r===void 0)return{dispose:()=>{},signal:t};const a=new AbortController,o=setTimeout(()=>{a.abort(e())},r);return{dispose:()=>{clearTimeout(o)},signal:a.signal}},f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",A=t=>{let r="",e=0;const a=t.length-2;for(;e<a;e+=3){const n=t[e]<<16|t[e+1]<<8|t[e+2];r+=f.charAt(n>>18&63)+f.charAt(n>>12&63)+f.charAt(n>>6&63)+f.charAt(n&63)}const o=t.length-e;if(o===1){const n=t[e]<<16;r+=f.charAt(n>>18&63)+f.charAt(n>>12&63)}else if(o===2){const n=t[e]<<16|t[e+1]<<8;r+=f.charAt(n>>18&63)+f.charAt(n>>12&63)+f.charAt(n>>6&63)}return r};new TextDecoder;const v=new TextEncoder,w="=",L=t=>{for(let r=0;r<t.length;r+=1)if(t.charCodeAt(r)>255)return!1;return!0},k=t=>A(v.encode(JSON.stringify(t))),D=t=>!t.startsWith(w)&&L(t)?t:`${w}${A(v.encode(t))}`,x="/_lunora/scheduler/dispatch",C=3e4,U=t=>{let r=t.length;for(;r>0&&t[r-1]==="/";)r-=1;return t.slice(0,r)},R=Symbol("lunoraDispatchFailure"),P=Symbol("lunoraDispatchMessageId"),T=(t,r)=>(r!==void 0&&Object.defineProperty(t,P,{value:r}),t),M=(t,r)=>(Object.defineProperty(t,R,{value:!0}),T(t,r)),J=(t,r,e,a)=>{try{const o=JSON.parse(e)?.error;if(typeof o=="object"&&o!==null&&typeof o.code=="string"){const{code:n,data:i,message:l}=o;return M(new m(n,typeof l=="string"?l:void 0,{data:i,status:r}),a)}}catch{}return T(new m("INTERNAL",`${t}: function dispatch failed (${String(r)}): ${e}`,{status:r}),a)},j=new Set([400,403,404,422]),H=new Set(["DISPATCH_UNAUTHENTICATED"]),K=t=>$(t)&&t[R]===!0&&j.has(t.status)&&!H.has(t.code),W=(t,r,e)=>new m("INTERNAL",`${t}: function dispatch to "${r}" timed out after ${String(e)}ms`,{status:503}),X=t=>{const{label:r}=t,e=globalThis.fetch,a=t.fetchImpl??(typeof e=="function"?e.bind(globalThis):void 0);return async(o,n,i={})=>{if(typeof a!="function")throw new TypeError(`${r}: no fetch implementation available — pass fetchImpl or run on a platform with global fetch`);const l=t.env.LUNORA_ORIGIN_URL;if(typeof l!="string"||l.length===0)throw new m("INTERNAL",`${r}: \`LUNORA_ORIGIN_URL\` must be set on the Worker env so a handler can call back into Lunora functions`);const d=t.env.LUNORA_ADMIN_TOKEN;if(typeof d!="string"||d.length===0)throw new m("INTERNAL",`${r}: \`LUNORA_ADMIN_TOKEN\` must be set on the Worker env to authenticate function dispatch`);const b=`${U(l)}${x}`,c={authorization:`Bearer ${d}`,"content-type":"application/json"};t.identity?.userId!==void 0&&(c["x-lunora-userid"]=D(t.identity.userId)),t.identity?.claims!==void 0&&(c["x-lunora-identity"]=k(t.identity.claims));const p=i.timeoutMs??C,g=_(void 0,p,()=>new DOMException(`dispatch timed out after ${String(p)}ms`,"TimeoutError")),s=h=>{throw h instanceof Error&&h.name==="TimeoutError"?W(r,o.__lunoraRef,p):h};let u;try{try{u=await a(b,{body:JSON.stringify({args:n??{},functionPath:o.__lunoraRef,id:i.dedupId,shardKey:i.shardKey}),headers:c,method:"POST",signal:g.signal})}catch(y){return s(y)}if(!u.ok){let y;try{y=await u.text()}catch(I){return s(I)}throw J(r,u.status,y,i.messageId)}let h;try{h=await u.text()}catch(y){return s(y)}if(h.length===0)return;try{return JSON.parse(h)}catch{throw new m("INTERNAL",`${r}: function dispatch returned a non-JSON body (${String(u.status)}): ${h}`,{status:u.status})}}finally{g.dispose()}}},V=(t,r)=>S(t,r,"step args"),Y=t=>async(r,e,a)=>{const o=a?.config??r.config,n=a?.name??r.name;if(n.startsWith(E))return N(`@lunora/workflow: ctx.runStep step name "${n}" is reserved — the "${E}" prefix is used by the framework's own steps`,void 0,t.nonRetryableErrorClass);const i=V(r.args,e),l=async c=>{const p={attempt:c.attempt,config:c.config,env:t.env,log:t.log,run:t.run,step:c.step};let g;try{g=await r.handler(p,i)}catch(s){return K(s)?N(s.message,s,t.nonRetryableErrorClass):O(s,t.nonRetryableErrorClass)}if(!r.returns)return g;try{return r.returns.parse(g)}catch(s){const u=s instanceof Error?s.message:String(s);return N(`step "${r.name}" returns validation failed: ${u}`,s,t.nonRetryableErrorClass)}},d=r.rollback,b=d?{rollback:async c=>{await d({args:i,env:t.env,error:c.error,log:t.log,output:c.output,run:t.run})},rollbackConfig:r.rollbackConfig}:void 0;return o===void 0?t.step.do(n,l,b):t.step.do(n,o,l,b)};export{X as J,Y as c,V as v};
|
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.43",
|
|
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.30",
|
|
52
|
+
"@lunora/values": "1.0.0-alpha.38"
|
|
53
53
|
},
|
|
54
54
|
"engines": {
|
|
55
55
|
"node": "^22.15.0 || >=24.11.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as E}from"@lunora/errors";import{h as y,B as I,a as p}from"./branch-marker-CCpWfS5k.mjs";import{RESERVED_EVENT_TYPE_PREFIX as v}from"./defineWorkflowEvent-suERPEEV.mjs";import{NonRetryableError as d}from"./NonRetryableError-9ZqDUzwT.mjs";const h=100,g="lunora:spawn:",$="lunora:await:",x="lunora:signal:",B="lunora:compensate:",m=`${v}branch:`,b=(t,r,n)=>({compensateWith:n?.compensateWith,id:n?.id,params:r,timeout:n?.timeout,workflow:t}),w=t=>t instanceof Error?{message:t.message,name:t.name}:{message:String(t),name:"Error"},A=t=>({status:"ok",value:t}),N=t=>({error:w(t),status:"error"}),f=async(t,r,n)=>{for(let a=r.length-1;a>=0;a-=1){const o=r[a],c=o?.plan.item.compensateWith;if(!(o===void 0||c===void 0))try{const s=t.resolveBinding(c);await t.step.do(`${B}${o.plan.childId}`,async()=>{const e=`${o.plan.childId}:compensate`,i={branch:o.plan.item.workflow,error:n,index:o.plan.index,output:o.output};return await s.create({id:e,params:i}),e})}catch(s){t.log?.error(`ctx.parallel: group-saga compensation "${c}" for branch "${o.plan.item.workflow}" (#${String(o.plan.index)}) failed`,s)}}},k=t=>async n=>{if(n.length===0)return[];if(n.length>h)throw new d(`ctx.parallel: ${String(n.length)} branches exceeds the cap of ${String(h)} — split the fan-out or raise the work into fewer child workflows`);const a=n.map((e,i)=>{const l=t.nextChildId(e.id);return{childId:l,eventType:`${m}${l}`,index:i,item:e}}),o=new Set;for(const e of a){if(o.has(e.childId))throw new d(`ctx.parallel: duplicate branch id "${e.childId}" — each branch in a group must resolve to a unique child instance id (check explicit \`id\` options)`);o.add(e.childId)}await Promise.all(a.map(e=>t.step.do(`${g}${e.childId}`,async()=>{const i=t.resolveBinding(e.item.workflow),l={eventType:e.eventType,index:e.index,parentBinding:t.parentBinding,parentId:t.instanceId};return await i.create({id:e.childId,params:{...e.item.params,[p]:l}}),e.childId})));const c=[],s=[];for(const e of a){let i;try{i=(await t.step.waitForEvent(`${$}${e.childId}`,{timeout:e.item.timeout,type:e.eventType})).payload}catch(l){const u=w(l);throw await f(t,s,u),new d(`ctx.parallel: branch "${e.item.workflow}" (#${String(e.index)}) join failed: ${u.message}`)}if(i.status==="error")throw await f(t,s,i.error),new d(`ctx.parallel: branch "${e.item.workflow}" (#${String(e.index)}) failed: ${i.error.message}`);s.push({output:i.value,plan:e}),c.push(i.value)}return c},W=t=>async(r,n,a)=>{if(y(n))throw new E("BAD_REQUEST",`@lunora/workflow: params ${I}`);const o=t.nextChildId(a?.id);return await t.step.do(`${g}${o}`,async()=>(await t.resolveBinding(r).create({id:o,params:n}),o)),t.resolveBinding(r).get(o)},C=t=>{if(typeof t!="object"||t===null)return;const r=t[p];if(typeof r!="object"||r===null)return;const n=r;if(!(typeof n.eventType!="string"||typeof n.parentBinding!="string"||typeof n.parentId!="string"||typeof n.index!="number")&&!(!n.parentBinding.startsWith("WORKFLOW_")||!n.eventType.startsWith(m)))return{eventType:n.eventType,index:n.index,parentBinding:n.parentBinding,parentId:n.parentId}},F=t=>{if(typeof t!="object"||t===null)return t;const r={...t};return Reflect.deleteProperty(r,p),r},T=async(t,r,n)=>{const a=t.env[r.parentBinding];if(!a||typeof a.get!="function")return;const o=a.get.bind(a);await t.step.do(`${x}${String(r.index)}`,async()=>(await(await o(r.parentId)).sendEvent({payload:n,type:r.eventType}),r.eventType))},M=async(t,r,n)=>{try{await T(t,r,n)}catch(a){t.log?.error(`@lunora/workflow: failed to signal branch parent "${r.parentId}" (event "${r.eventType}")`,a)}};export{h as MAX_BRANCHES,b as branch,k as createParallel,W as createSpawn,N as errorOutcome,C as extractBranchMarker,A as okOutcome,T as signalBranchParent,M as signalBranchParentSafe,F as stripBranchMarker};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const s="__lunoraNonRetryable";class a extends Error{constructor(e,n="NonRetryableError"){super(e),this.name=n,this[s]=!0}}const c=t=>t instanceof Error&&t[s]===!0,r=(t,e)=>{const n=new e(t.message,t.name);return t.stack!==void 0&&(n.stack=t.stack),t.cause!==void 0&&n.cause===void 0&&(n.cause=t.cause),n},i=(t,e)=>{throw e!==void 0&&c(t)?r(t,e):t},u=(t,e,n)=>{const o=new a(t);return e!==void 0&&(o.cause=e),i(o,n)};export{a as NonRetryableError,i as convertNonRetryableError,c as isNonRetryableError,u as raiseNonRetryable,r as toNativeNonRetryableError};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as h}from"@lunora/errors";const R="https://api.cloudflare.com/client/v4/accounts",$={complete:!0,errored:!0,paused:!0,queued:!0,running:!0,terminated:!0,unknown:!0,waiting:!0,waitingForPause:!0},g=t=>typeof t=="string"&&Object.hasOwn($,t)?t:"unknown",u=t=>typeof t=="string"&&t!==""?t:void 0,S=(t,a)=>typeof t=="string"?t:a,A=t=>typeof t=="boolean"?t:void 0,_=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:S(t.id,""),startedOn:u(t.started_on),status:g(t.status)}),I=t=>({attempts:_(t.attempts),end:u(t.end),error:t.error,name:S(t.name,""),output:t.output,start:u(t.start),success:A(t.success),type:u(t.type)});class l extends h{constructor(a,i){super("WORKFLOWS_REST_ERROR",`Cloudflare Workflows REST API returned ${String(a)}: ${i}`,{name:"WorkflowsRestError",status:a})}}const w=t=>{const a=t.fetch??globalThis.fetch.bind(globalThis),i=`${R}/${t.accountId}/workflows`,p=async(o,r)=>{const s=await a(`${i}${o}`,{...r,headers:{Authorization:`Bearer ${t.apiToken}`,"Content-Type":"application/json"}}),e=await s.text();let n;try{n=JSON.parse(e)}catch{throw new l(s.status,e)}if(!s.ok||n.success===!1)throw new l(s.status,e);return n};return{getInstance:async({instanceId:o,workflowName:r})=>{const e=(await p(`/${encodeURIComponent(r)}/instances/${encodeURIComponent(o)}`)).result??{},n=Array.isArray(e.steps)?e.steps:[];return{...f(e),error:e.error,output:e.output,params:e.params,steps:n.map(d=>I(d))}},listInstances:async({page:o,perPage:r,status:s,workflowName:e})=>{const n=new URLSearchParams;s!==void 0&&n.set("status",s),o!==void 0&&n.set("page",String(o)),r!==void 0&&n.set("per_page",String(r));const d=n.toString()===""?"":`?${n.toString()}`,y=await p(`/${encodeURIComponent(e)}/instances${d}`),m=Array.isArray(y.result)?y.result:[],c=y.result_info??{};return{instances:m.map(b=>f(b)),page:typeof c.page=="number"?c.page:o??1,perPage:typeof c.per_page=="number"?c.per_page:r??m.length,totalCount:typeof c.total_count=="number"?c.total_count:void 0}},setInstanceStatus:async({action:o,instanceId:r,workflowName:s})=>{const n=(await p(`/${encodeURIComponent(s)}/instances/${encodeURIComponent(r)}`,{body:JSON.stringify({status:o}),method:"PATCH"})).result??{};return{status:g(n.status)}}}};export{l as WorkflowsRestError,w as createWorkflowsRestClient};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as p,v as o}from"./run-step-D7XRYstF.mjs";import"./defineWorkflowEvent-suERPEEV.mjs";import"./NonRetryableError-9ZqDUzwT.mjs";export{p as createRunStep,o as validateStepArgs};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as m,isLunoraError as T}from"@lunora/errors";import{parseValidatorMap as O}from"@lunora/values";import{RESERVED_EVENT_TYPE_PREFIX as w}from"./defineWorkflowEvent-suERPEEV.mjs";import{raiseNonRetryable as N,convertNonRetryableError as S}from"./NonRetryableError-9ZqDUzwT.mjs";const _=(t,r,e)=>{if(r===void 0)return{dispose:()=>{},signal:t};const a=new AbortController,o=setTimeout(()=>{a.abort(e())},r);return{dispose:()=>{clearTimeout(o)},signal:a.signal}},f="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",R=t=>{let r="",e=0;const a=t.length-2;for(;e<a;e+=3){const n=t[e]<<16|t[e+1]<<8|t[e+2];r+=f.charAt(n>>18&63)+f.charAt(n>>12&63)+f.charAt(n>>6&63)+f.charAt(n&63)}const o=t.length-e;if(o===1){const n=t[e]<<16;r+=f.charAt(n>>18&63)+f.charAt(n>>12&63)}else if(o===2){const n=t[e]<<16|t[e+1]<<8;r+=f.charAt(n>>18&63)+f.charAt(n>>12&63)+f.charAt(n>>6&63)}return r};new TextDecoder;const A=new TextEncoder,E="=",L=t=>{for(let r=0;r<t.length;r+=1)if(t.charCodeAt(r)>255)return!1;return!0},k=t=>R(A.encode(JSON.stringify(t))),x=t=>!t.startsWith(E)&&L(t)?t:`${E}${R(A.encode(t))}`,D="/_lunora/scheduler/dispatch",C=3e4,P=t=>{let r=t.length;for(;r>0&&t[r-1]==="/";)r-=1;return t.slice(0,r)},$=Symbol("lunoraDispatchFailure"),U=Symbol("lunoraDispatchMessageId"),v=(t,r)=>(Object.defineProperty(t,$,{value:!0}),r!==void 0&&Object.defineProperty(t,U,{value:r}),t),M=(t,r,e,a)=>{try{const o=JSON.parse(e)?.error;if(typeof o=="object"&&o!==null&&typeof o.code=="string"){const{code:n,data:c,message:l}=o;return v(new m(n,typeof l=="string"?l:void 0,{data:c,status:r}),a)}}catch{}return v(new m("INTERNAL",`${t}: function dispatch failed (${String(r)}): ${e}`,{status:r}),a)},J=new Set([400,403,404,422]),j=t=>T(t)&&t[$]===!0&&J.has(t.status),K=(t,r,e)=>new m("INTERNAL",`${t}: function dispatch to "${r}" timed out after ${String(e)}ms`,{status:503}),z=t=>{const{label:r}=t,e=globalThis.fetch,a=t.fetchImpl??(typeof e=="function"?e.bind(globalThis):void 0);return async(o,n,c={})=>{if(typeof a!="function")throw new TypeError(`${r}: no fetch implementation available — pass fetchImpl or run on a platform with global fetch`);const l=t.env.LUNORA_ORIGIN_URL;if(typeof l!="string"||l.length===0)throw new m("INTERNAL",`${r}: \`LUNORA_ORIGIN_URL\` must be set on the Worker env so a handler can call back into Lunora functions`);const d=t.env.LUNORA_ADMIN_TOKEN;if(typeof d!="string"||d.length===0)throw new m("INTERNAL",`${r}: \`LUNORA_ADMIN_TOKEN\` must be set on the Worker env to authenticate function dispatch`);const b=`${P(l)}${D}`,i={authorization:`Bearer ${d}`,"content-type":"application/json"};t.identity?.userId!==void 0&&(i["x-lunora-userid"]=x(t.identity.userId)),t.identity?.claims!==void 0&&(i["x-lunora-identity"]=k(t.identity.claims));const p=c.timeoutMs??C,g=_(void 0,p,()=>new DOMException(`dispatch timed out after ${String(p)}ms`,"TimeoutError")),s=h=>{throw h instanceof Error&&h.name==="TimeoutError"?K(r,o.__lunoraRef,p):h};let u;try{try{u=await a(b,{body:JSON.stringify({args:n??{},functionPath:o.__lunoraRef,id:c.dedupId,shardKey:c.shardKey}),headers:i,method:"POST",signal:g.signal})}catch(y){return s(y)}if(!u.ok){let y;try{y=await u.text()}catch(I){return s(I)}throw M(r,u.status,y,c.messageId)}let h;try{h=await u.text()}catch(y){return s(y)}if(h.length===0)return;try{return JSON.parse(h)}catch{throw new m("INTERNAL",`${r}: function dispatch returned a non-JSON body (${String(u.status)}): ${h}`,{status:u.status})}}finally{g.dispose()}}},W=(t,r)=>O(t,r,"step args"),H=t=>async(r,e,a)=>{const o=a?.config??r.config,n=a?.name??r.name;if(n.startsWith(w))return N(`@lunora/workflow: ctx.runStep step name "${n}" is reserved — the "${w}" prefix is used by the framework's own steps`,void 0,t.nonRetryableErrorClass);const c=W(r.args,e),l=async i=>{const p={attempt:i.attempt,config:i.config,env:t.env,log:t.log,run:t.run,step:i.step};let g;try{g=await r.handler(p,c)}catch(s){return j(s)?N(s.message,s,t.nonRetryableErrorClass):S(s,t.nonRetryableErrorClass)}if(!r.returns)return g;try{return r.returns.parse(g)}catch(s){const u=s instanceof Error?s.message:String(s);return N(`step "${r.name}" returns validation failed: ${u}`,s,t.nonRetryableErrorClass)}},d=r.rollback,b=d?{rollback:async i=>{await d({args:c,env:t.env,error:i.error,log:t.log,output:i.output,run:t.run})},rollbackConfig:r.rollbackConfig}:void 0;return o===void 0?t.step.do(n,l,b):t.step.do(n,o,l,b)};export{z as F,H as c,W as v};
|