@lunora/workflow 1.0.0-alpha.45 → 1.0.0-alpha.47

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 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-BV6ELTK1.mjs";import{extractBranchMarker as f,stripBranchMarker as h,signalBranchParentSafe as l,errorOutcome as u,okOutcome as y}from"../packem_shared/MAX_BRANCHES-DQ7WZU8W.mjs";import{createWorkflowRunContext as d}from"../packem_shared/createWorkflowRunContext-B00Q8USs.mjs";class N extends p{#r;#t;constructor(t,e,o,r){super(t,e),this.#t=o,this.#r=r??"workflow"}async run(t,e){const o=e,r=f(t.payload),c=r?{...t,payload:h(t.payload)}:t,a=d({env:this.env,event:c,exportName:this.#r,nonRetryableErrorClass:i,step:o});let n;try{n=await this.#t.handler(a)}catch(s){return r&&await l({env:this.env,log:a.log,step:o},r,u(s)),m(s,i)}return r&&await l({env:this.env,log:a.log,step:o},r,y(n)),n}}export{N as default};
1
+ import{WorkflowEntrypoint as p}from"cloudflare:workers";import{NonRetryableError as i}from"cloudflare:workflows";import{convertNonRetryableError as m}from"../packem_shared/NonRetryableError-BPu01mU8.mjs";import{extractBranchMarker as f,stripBranchMarker as h,signalBranchParentSafe as l,errorOutcome as u,okOutcome as y}from"../packem_shared/MAX_BRANCHES-j59ZUUSu.mjs";import{createWorkflowRunContext as d}from"../packem_shared/createWorkflowRunContext-DUGwefYI.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
@@ -129,6 +129,16 @@ declare const workflowDefaultName: (exportName: string) => string;
129
129
  declare const defineWorkflow: <Params = Record<string, unknown>, Output = unknown>(config: WorkflowConfig<Params, Output>) => WorkflowDefinition<Params, Output>;
130
130
  /** True when a value is a `defineWorkflow` result (the runtime brand check). */
131
131
  declare const isWorkflowDefinition: (value: unknown) => value is WorkflowDefinition;
132
+ /**
133
+ * Whether a `WorkflowBinding.create()` rejection is a duplicate-instance-id
134
+ * error — the idempotency signal that a *previous* attempt's create already
135
+ * applied — as opposed to a transient or config failure (Workflows service
136
+ * error, instance-creation quota, bad params).
137
+ *
138
+ * Every other failure MUST surface, so the caller retries or fails visibly
139
+ * rather than silently reporting success for work that never started.
140
+ */
141
+ declare const isDuplicateInstanceError: (error: unknown) => boolean;
132
142
  /**
133
143
  * Throw from a workflow step (or handler) to fail the instance immediately
134
144
  * **without** retrying — the portable mirror of `cloudflare:workflows`'
@@ -162,23 +172,6 @@ declare const toNativeNonRetryableError: (error: NonRetryableError, NativeNonRet
162
172
  * Always throws — the `never` return lets callers `return convertNonRetryableError(...)`.
163
173
  */
164
174
  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;
182
175
  /** Hard cap on branches per `ctx.parallel` call — auto-scale, never silently spawn unbounded DOs. */
183
176
  declare const MAX_BRANCHES = 100;
184
177
  /**
package/dist/index.d.ts CHANGED
@@ -129,6 +129,16 @@ declare const workflowDefaultName: (exportName: string) => string;
129
129
  declare const defineWorkflow: <Params = Record<string, unknown>, Output = unknown>(config: WorkflowConfig<Params, Output>) => WorkflowDefinition<Params, Output>;
130
130
  /** True when a value is a `defineWorkflow` result (the runtime brand check). */
131
131
  declare const isWorkflowDefinition: (value: unknown) => value is WorkflowDefinition;
132
+ /**
133
+ * Whether a `WorkflowBinding.create()` rejection is a duplicate-instance-id
134
+ * error — the idempotency signal that a *previous* attempt's create already
135
+ * applied — as opposed to a transient or config failure (Workflows service
136
+ * error, instance-creation quota, bad params).
137
+ *
138
+ * Every other failure MUST surface, so the caller retries or fails visibly
139
+ * rather than silently reporting success for work that never started.
140
+ */
141
+ declare const isDuplicateInstanceError: (error: unknown) => boolean;
132
142
  /**
133
143
  * Throw from a workflow step (or handler) to fail the instance immediately
134
144
  * **without** retrying — the portable mirror of `cloudflare:workflows`'
@@ -162,23 +172,6 @@ declare const toNativeNonRetryableError: (error: NonRetryableError, NativeNonRet
162
172
  * Always throws — the `never` return lets callers `return convertNonRetryableError(...)`.
163
173
  */
164
174
  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;
182
175
  /** Hard cap on branches per `ctx.parallel` call — auto-scale, never silently spawn unbounded DOs. */
183
176
  declare const MAX_BRANCHES = 100;
184
177
  /**
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 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-BV6ELTK1.mjs";import{MAX_BRANCHES as C,branch as D}from"./packem_shared/MAX_BRANCHES-DQ7WZU8W.mjs";import{WorkflowsRestError as y,createWorkflowsRestClient as A}from"./packem_shared/WorkflowsRestError-Ccq1FUR1.mjs";import{createWorkflowRunContext as B}from"./packem_shared/createWorkflowRunContext-B00Q8USs.mjs";import{c as F,v as H}from"./packem_shared/run-step-CAUCn1UO.mjs";import{createWaitForEvent as M}from"./packem_shared/createWaitForEvent-KkdE11qX.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};
1
+ import{createWorkflowContext as e}from"./packem_shared/createWorkflowContext-zQR_9N-v.mjs";import{default as f}from"./packem_shared/createWorkflows-LvAyUyKq.mjs";import{defineWorkflowEvent as a,isWorkflowEventDefinition as i}from"./packem_shared/defineWorkflowEvent-suERPEEV.mjs";import{defineStep as p,isStepDefinition as s}from"./packem_shared/defineStep-D1-9eOnA.mjs";import{defineWorkflow as w,isWorkflowDefinition as x,workflowBindingName as k,workflowClassName as c,workflowDefaultName as E}from"./packem_shared/defineWorkflow-tKaIifbZ.mjs";import{NonRetryableError as N,convertNonRetryableError as R,isNonRetryableError as v,toNativeNonRetryableError as d}from"./packem_shared/NonRetryableError-BPu01mU8.mjs";import{MAX_BRANCHES as u,branch as C}from"./packem_shared/MAX_BRANCHES-j59ZUUSu.mjs";import{WorkflowsRestError as S,createWorkflowsRestClient as y}from"./packem_shared/WorkflowsRestError-Ccq1FUR1.mjs";import{createWorkflowRunContext as g}from"./packem_shared/createWorkflowRunContext-DUGwefYI.mjs";import{c as h,v as F}from"./packem_shared/run-step-C8J1B8nx.mjs";import{createWaitForEvent as I}from"./packem_shared/createWaitForEvent-D5Ohn2Pz.mjs";import{isDuplicateInstanceError as X}from"./packem_shared/isDuplicateInstanceError-CecnqNAa.mjs";export{u as MAX_BRANCHES,N as NonRetryableError,S as WorkflowsRestError,C as branch,R as convertNonRetryableError,h as createRunStep,I as createWaitForEvent,e as createWorkflowContext,g as createWorkflowRunContext,f as createWorkflows,y as createWorkflowsRestClient,p as defineStep,w as defineWorkflow,a as defineWorkflowEvent,X as isDuplicateInstanceError,v as isNonRetryableError,s as isStepDefinition,x as isWorkflowDefinition,i as isWorkflowEventDefinition,d as toNativeNonRetryableError,F as validateStepArgs,k as workflowBindingName,c as workflowClassName,E as workflowDefaultName};
@@ -0,0 +1 @@
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};
@@ -0,0 +1 @@
1
+ import{isDuplicateInstanceError as E}from"./isDuplicateInstanceError-CecnqNAa.mjs";const s="__lunoraNonRetryable";class r extends Error{constructor(e,n="NonRetryableError"){super(e),this.name=n,this[s]=!0}}const a=t=>t instanceof Error&&t[s]===!0,c=(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&&a(t)?c(t,e):t},u=(t,e,n)=>{const o=new r(t);return e!==void 0&&(o.cause=e),i(o,n)};export{r as NonRetryableError,i as convertNonRetryableError,E as isDuplicateInstanceError,a as isNonRetryableError,u as raiseNonRetryable,c as toNativeNonRetryableError};
@@ -0,0 +1 @@
1
+ import{c as p,v as o}from"./run-step-C8J1B8nx.mjs";import"./defineWorkflowEvent-suERPEEV.mjs";import"./NonRetryableError-BPu01mU8.mjs";export{p as createRunStep,o as validateStepArgs};
@@ -1 +1 @@
1
- import{eventDefinitionProblem as m,RESERVED_EVENT_TYPE_PREFIX as i}from"./defineWorkflowEvent-suERPEEV.mjs";import{raiseNonRetryable as a}from"./NonRetryableError-BV6ELTK1.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
+ import{eventDefinitionProblem as m,RESERVED_EVENT_TYPE_PREFIX as i}from"./defineWorkflowEvent-suERPEEV.mjs";import{raiseNonRetryable as a}from"./NonRetryableError-BPu01mU8.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};
@@ -0,0 +1 @@
1
+ import{e as p,c as E}from"./run-step-C8J1B8nx.mjs";import{LunoraError as A}from"@lunora/errors";import{workflowBindingName as y}from"./defineWorkflow-tKaIifbZ.mjs";import{createSpawn as h,createParallel as R}from"./MAX_BRANCHES-j59ZUUSu.mjs";import{createWaitForEvent as I}from"./createWaitForEvent-D5Ohn2Pz.mjs";const T=r=>({debug:(n,...o)=>{console.debug(r,n,...o)},error:(n,...o)=>{console.error(r,n,...o)},info:(n,...o)=>{console.info(r,n,...o)},warn:(n,...o)=>{console.warn(r,n,...o)}}),k=r=>{let n="";for(let a=0;a<r.length;a+=32768)n+=String.fromCharCode(...r.subarray(a,a+32768));return btoa(n)},C=r=>{const n=atob(r),o=new Uint8Array(n.length);for(let a=0;a<n.length;a+=1)o[a]=n.codePointAt(a)??0;return o},O="$lunora.wire$",w=64,d=1024,m="__proto__",b={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},g={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},f=(r,n=0)=>{if(n>w)throw new RangeError(`wire-codec: value nesting exceeds the ${w}-level limit`);if(r===null||typeof r!="object")return r;if(Array.isArray(r)){if(r[0]===O)switch(r[1]){case"-inf":return-1/0;case"arr":return r[2].map(e=>f(e,n+1));case"bigint":{const e=r[2];if(typeof e!="string"||e.length>d||!/^-?\d+$/.test(e))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${d} digits)`);return BigInt(e)}case"date":{const e=f(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(t=>{if(!Array.isArray(t)||t.length!==2)throw new TypeError("wire-codec: malformed map entry — expected a [key, value] pair");return[f(t[0],n+1),f(t[1],n+1)]}))}case"set":return new Set(r[2].map(e=>f(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],t=r[3];if(typeof e!="string"||typeof t!="string")throw new TypeError("wire-codec: malformed error — name and message must be strings");const s=(Object.hasOwn(g,e)?g[e]:void 0)??Error,c=new s(t);c.name!==e&&Object.defineProperty(c,"name",{configurable:!0,value:e,writable:!0});const i=f(r[4],n+1);if(i===null||typeof i!="object"||Array.isArray(i))throw new TypeError("wire-codec: malformed error — props must be an object");for(const u of Object.keys(i))u===m?Object.defineProperty(c,u,{configurable:!0,enumerable:!0,value:i[u],writable:!0}):c[u]=i[u];return r.length>5&&Object.defineProperty(c,"cause",{configurable:!0,value:f(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 t=C(e);if(k(t)!==e)throw new TypeError("wire-codec: malformed bytes — payload must be canonical padded base64");const s=r[3]??"Uint8Array";if(s==="ArrayBuffer")return t.buffer.byteLength===t.byteLength?t.buffer:t.slice().buffer;const c=Object.hasOwn(b,s)?b[s]:void 0;return c?new c(t.slice().buffer):t}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return r.map(e=>f(e,n+1))}return r.map(l=>f(l,n+1))}const o=r,a={};for(const l of Object.keys(o)){const e=f(o[l],n+1);l===m?Object.defineProperty(a,l,{configurable:!0,enumerable:!0,value:e,writable:!0}):a[l]=e}return a},x=r=>{const n=T(`[workflow:${r.exportName}]`),o=p({env:r.env,fetchImpl:r.fetchImpl,label:"@lunora/workflow"}),a=s=>{const c=y(s),i=r.env[c];if(!i||typeof i.create!="function"||typeof i.get!="function")throw new A("INTERNAL",`@lunora/workflow: cannot spawn child workflow "${s}" — no Workflow binding "${c}" on env (is it declared in lunora/workflows.ts?)`);return i};let l=0;const e=s=>{if(s!==void 0)return s;const c=`${r.event.instanceId}-c${String(l)}`;return l+=1,c},t={env:r.env,instanceId:r.event.instanceId,log:n,nextChildId:e,parentBinding:y(r.exportName),resolveBinding:a,step:r.step};return{env:r.env,event:r.event,log:n,parallel:R(t),params:f(r.event.payload),run:o,runStep:E({env:r.env,log:n,nonRetryableErrorClass:r.nonRetryableErrorClass,run:o,step:r.step}),spawn:h(t),step:r.step,waitForEvent:I({nonRetryableErrorClass:r.nonRetryableErrorClass,step:r.step})}};export{x as createWorkflowRunContext};
@@ -0,0 +1 @@
1
+ const t=/already[\s_-]?exists/iu,e=s=>t.test(s instanceof Error?s.message:String(s));export{e as isDuplicateInstanceError};
@@ -0,0 +1 @@
1
+ import{LunoraError as m,isLunoraError as D}from"@lunora/errors";import{parseValidatorMap as C}from"@lunora/values";import{RESERVED_EVENT_TYPE_PREFIX as $}from"./defineWorkflowEvent-suERPEEV.mjs";import{raiseNonRetryable as T,convertNonRetryableError as B}from"./NonRetryableError-BPu01mU8.mjs";const M=(e,t,o)=>{if(t===void 0)return{dispose:()=>{},signal:e};const a=new AbortController,n=setTimeout(()=>{a.abort(o())},t);return{dispose:()=>{clearTimeout(n)},signal:a.signal}},N=e=>{let t="";for(let o=0;o<e.length;o+=32768)t+=String.fromCharCode(...e.subarray(o,o+32768));return btoa(t)},J=e=>{const t=atob(e),o=new Uint8Array(t.length);for(let a=0;a<t.length;a+=1)o[a]=t.codePointAt(a)??0;return o},g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",L=e=>{let t="",o=0;const a=e.length-2;for(;o<a;o+=3){const r=e[o]<<16|e[o+1]<<8|e[o+2];t+=g.charAt(r>>18&63)+g.charAt(r>>12&63)+g.charAt(r>>6&63)+g.charAt(r&63)}const n=e.length-o;if(n===1){const r=e[o]<<16;t+=g.charAt(r>>18&63)+g.charAt(r>>12&63)}else if(n===2){const r=e[o]<<16|e[o+1]<<8;t+=g.charAt(r>>18&63)+g.charAt(r>>12&63)+g.charAt(r>>6&63)}return t};new TextDecoder;const U=new TextEncoder,S="=",F=e=>{for(let t=0;t<e.length;t+=1)if(e.charCodeAt(t)>255)return!1;return!0},K=e=>L(U.encode(JSON.stringify(e))),V=e=>!e.startsWith(S)&&F(e)?e:`${S}${L(U.encode(e))}`,u="$lunora.wire$",O=64,I=1024,R="__proto__",j={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},_={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},W=e=>{if(e===null||typeof e!="object")return!1;const t=Object.getPrototypeOf(e);return t===null||t===Object.prototype},h=(e,t=0)=>{if(t>O)throw new RangeError(`wire-codec: value nesting exceeds the ${O}-level limit`);if(e===void 0)return[u,"undefined"];if(e===null)return null;const o=typeof e;if(o==="bigint")return[u,"bigint",e.toString()];if(o==="number"){const r=e;return Number.isNaN(r)?[u,"nan"]:r===1/0?[u,"inf"]:r===-1/0?[u,"-inf"]:r}if(o!=="object")return e;if(e instanceof Date)return[u,"date",h(e.getTime(),t+1)];if(e instanceof Error){const r=e,s={};for(const c of Object.keys(r)){if(r[c]===void 0)continue;const l=h(r[c],t+1);c===R?Object.defineProperty(s,c,{configurable:!0,enumerable:!0,value:l,writable:!0}):s[c]=l}const i=[u,"error",String(r.name),String(r.message),s];return r.cause!==void 0&&i.push(h(r.cause,t+1)),i}if(e instanceof URL)return[u,"url",e.href];if(e instanceof Map)return[u,"map",[...e.entries()].map(([r,s])=>[h(r,t+1),h(s,t+1)])];if(e instanceof Set)return[u,"set",[...e].map(r=>h(r,t+1))];if(e instanceof ArrayBuffer)return[u,"bytes",N(new Uint8Array(e)),"ArrayBuffer"];if(ArrayBuffer.isView(e)){const r=e,s=r.constructor.name,i=new Uint8Array(r.buffer,r.byteOffset,r.byteLength);return s==="Uint8Array"?[u,"bytes",N(i)]:[u,"bytes",N(i),s]}if(Array.isArray(e)){const r=e.map(s=>h(s,t+1));return r.length>0&&r[0]===u?[u,"arr",r]:r}if(!W(e)){const r=e.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${r} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const a=e,n={};for(const r of Object.keys(a)){const s=a[r];if(s===void 0)continue;const i=h(s,t+1);r===R?Object.defineProperty(n,r,{configurable:!0,enumerable:!0,value:i,writable:!0}):n[r]=i}return n},b=(e,t=0)=>{if(t>O)throw new RangeError(`wire-codec: value nesting exceeds the ${O}-level limit`);if(e===null||typeof e!="object")return e;if(Array.isArray(e)){if(e[0]===u)switch(e[1]){case"-inf":return-1/0;case"arr":return e[2].map(n=>b(n,t+1));case"bigint":{const n=e[2];if(typeof n!="string"||n.length>I||!/^-?\d+$/.test(n))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${I} digits)`);return BigInt(n)}case"date":{const n=b(e[2],t+1);if(typeof n!="number")throw new TypeError("wire-codec: malformed date — epoch must be a number");return new Date(n)}case"map":{const n=e[2];return new Map(n.map(r=>{if(!Array.isArray(r)||r.length!==2)throw new TypeError("wire-codec: malformed map entry — expected a [key, value] pair");return[b(r[0],t+1),b(r[1],t+1)]}))}case"set":return new Set(e[2].map(n=>b(n,t+1)));case"url":{const n=e[2];if(typeof n!="string")throw new TypeError("wire-codec: malformed url — href must be a string");return new URL(n)}case"error":{const n=e[2],r=e[3];if(typeof n!="string"||typeof r!="string")throw new TypeError("wire-codec: malformed error — name and message must be strings");const s=(Object.hasOwn(_,n)?_[n]:void 0)??Error,i=new s(r);i.name!==n&&Object.defineProperty(i,"name",{configurable:!0,value:n,writable:!0});const c=b(e[4],t+1);if(c===null||typeof c!="object"||Array.isArray(c))throw new TypeError("wire-codec: malformed error — props must be an object");for(const l of Object.keys(c))l===R?Object.defineProperty(i,l,{configurable:!0,enumerable:!0,value:c[l],writable:!0}):i[l]=c[l];return e.length>5&&Object.defineProperty(i,"cause",{configurable:!0,value:b(e[5],t+1),writable:!0}),i}case"bytes":{const n=e[2];if(typeof n!="string")throw new TypeError("wire-codec: malformed bytes — payload must be a base64 string");const r=J(n);if(N(r)!==n)throw new TypeError("wire-codec: malformed bytes — payload must be canonical padded base64");const s=e[3]??"Uint8Array";if(s==="ArrayBuffer")return r.buffer.byteLength===r.byteLength?r.buffer:r.slice().buffer;const i=Object.hasOwn(j,s)?j[s]:void 0;return i?new i(r.slice().buffer):r}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return e.map(n=>b(n,t+1))}return e.map(n=>b(n,t+1))}const o=e,a={};for(const n of Object.keys(o)){const r=b(o[n],t+1);n===R?Object.defineProperty(a,n,{configurable:!0,enumerable:!0,value:r,writable:!0}):a[n]=r}return a},H=(e,t,o)=>{try{return h(o)}catch(a){throw new TypeError(`${e}: cannot encode args for '${t}' — ${a instanceof Error?a.message:String(a)}`,a instanceof Error?{cause:a}:void 0)}},G="/_lunora/scheduler/dispatch",z=3e4,X=e=>{let t=e.length;for(;t>0&&e[t-1]==="/";)t-=1;return e.slice(0,t)},k=Symbol("lunoraDispatchFailure"),Y=Symbol("lunoraDispatchMessageId"),P=(e,t)=>(t!==void 0&&Object.defineProperty(e,Y,{value:t}),e),q=(e,t)=>(Object.defineProperty(e,k,{value:!0}),P(e,t)),Q=(e,t,o,a)=>{try{const n=JSON.parse(o)?.error;if(typeof n=="object"&&n!==null&&typeof n.code=="string"){const{code:r,data:s,message:i}=n;return q(new m(r,typeof i=="string"?i:void 0,{data:s,status:t}),a)}}catch{}return P(new m("INTERNAL",`${e}: function dispatch failed (${String(t)}): ${o}`,{status:t}),a)},Z=new Set([400,403,404,422]),ee=new Set(["DISPATCH_UNAUTHENTICATED"]),te=e=>D(e)&&e[k]===!0&&Z.has(e.status)&&!ee.has(e.code),re=(e,t,o)=>new m("INTERNAL",`${e}: function dispatch to "${t}" timed out after ${String(o)}ms`,{status:503}),ce=e=>{const{label:t}=e,o=globalThis.fetch,a=e.fetchImpl??(typeof o=="function"?o.bind(globalThis):void 0);return async(n,r,s={})=>{if(typeof a!="function")throw new TypeError(`${t}: no fetch implementation available — pass fetchImpl or run on a platform with global fetch`);const i=e.env.LUNORA_ORIGIN_URL;if(typeof i!="string"||i.length===0)throw new m("INTERNAL",`${t}: \`LUNORA_ORIGIN_URL\` must be set on the Worker env so a handler can call back into Lunora functions`);const c=e.env.LUNORA_ADMIN_TOKEN;if(typeof c!="string"||c.length===0)throw new m("INTERNAL",`${t}: \`LUNORA_ADMIN_TOKEN\` must be set on the Worker env to authenticate function dispatch`);const l=`${X(i)}${G}`,y={authorization:`Bearer ${c}`,"content-type":"application/json"};e.traceparent!==void 0&&e.traceparent.length>0&&(y.traceparent=e.traceparent),e.identity?.userId!==void 0&&(y["x-lunora-userid"]=V(e.identity.userId)),e.identity?.claims!==void 0&&(y["x-lunora-identity"]=K(e.identity.claims));const v=s.timeoutMs??z,w=M(void 0,v,()=>new DOMException(`dispatch timed out after ${String(v)}ms`,"TimeoutError")),f=p=>{throw p instanceof Error&&p.name==="TimeoutError"?re(t,n.__lunoraRef,v):p};let d;try{try{d=await a(l,{body:JSON.stringify({args:H(t,n.__lunoraRef,r??{}),functionPath:n.__lunoraRef,id:s.dedupId,shardKey:s.shardKey}),headers:y,method:"POST",signal:w.signal})}catch(E){return f(E)}if(!d.ok){let E;try{E=await d.text()}catch(x){return f(x)}throw Q(t,d.status,E,s.messageId)}let p;try{p=await d.text()}catch(E){return f(E)}if(p.length===0)return;let A;try{A=JSON.parse(p)}catch{throw new m("INTERNAL",`${t}: function dispatch returned a non-JSON body (${String(d.status)}): ${p}`,{status:d.status})}if(A===null||typeof A!="object"||Array.isArray(A)||!("result"in A))throw new m("INTERNAL",`${t}: function dispatch returned a JSON body that is not a { result } envelope (${String(d.status)}): ${p}`,{status:d.status});return b(A.result)}finally{w.dispose()}}},ne=(e,t)=>C(e,t,"step args"),ue=e=>async(t,o,a)=>{const n=a?.config??t.config,r=a?.name??t.name;if(r.startsWith($))return T(`@lunora/workflow: ctx.runStep step name "${r}" is reserved — the "${$}" prefix is used by the framework's own steps`,void 0,e.nonRetryableErrorClass);const s=ne(t.args,o),i=async y=>{const v={attempt:y.attempt,config:y.config,env:e.env,log:e.log,run:e.run,step:y.step};let w;try{w=await t.handler(v,s)}catch(f){return te(f)?T(f.message,f,e.nonRetryableErrorClass):B(f,e.nonRetryableErrorClass)}if(!t.returns)return w;try{return t.returns.parse(w)}catch(f){const d=f instanceof Error?f.message:String(f);return T(`step "${t.name}" returns validation failed: ${d}`,f,e.nonRetryableErrorClass)}},c=t.rollback,l=c?{rollback:async y=>{await c({args:s,env:e.env,error:y.error,log:e.log,output:y.output,run:e.run})},rollbackConfig:t.rollbackConfig}:void 0;return n===void 0?e.step.do(r,i,l):e.step.do(r,n,i,l)};export{ue as c,ce as e,ne as v};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/workflow",
3
- "version": "1.0.0-alpha.45",
3
+ "version": "1.0.0-alpha.47",
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.31",
52
- "@lunora/values": "1.0.0-alpha.39"
51
+ "@lunora/errors": "1.0.0-alpha.33",
52
+ "@lunora/values": "1.0.0-alpha.41"
53
53
  },
54
54
  "engines": {
55
55
  "node": "^22.15.0 || >=24.11.0"
@@ -1 +0,0 @@
1
- import{LunoraError as B}from"@lunora/errors";import{h as _,B as R,a as g}from"./branch-marker-CCpWfS5k.mjs";import{RESERVED_EVENT_TYPE_PREFIX as A}from"./defineWorkflowEvent-suERPEEV.mjs";import{NonRetryableError as f,isDuplicateInstanceError as P}from"./NonRetryableError-BV6ELTK1.mjs";const p=t=>t.toString(16).padStart(4,"0"),N=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)},y=100,v=100,$="lunora:spawn:",O="lunora:await:",k="lunora:signal:",C="lunora:compensate:",F=t=>{const e=`${t}-compensate`;return e.length<=v?e:`${t.slice(0,v-28)}-${N(t)}-compensate`},b=`${A}branch:`,Y=(t,e,n)=>({compensateWith:n?.compensateWith,id:n?.id,params:e,timeout:n?.timeout,workflow:t}),S=t=>t instanceof Error?{message:t.message,name:t.name}:{message:String(t),name:"Error"},W=t=>({status:"ok",value:t}),z=t=>({error:S(t),status:"error"}),I=1048576,M=t=>{try{return String(t instanceof Error?t.message:t).slice(0,200)}catch{return"the failure itself could not be described"}},T=t=>{let e;try{e=new TextEncoder().encode(JSON.stringify(t)).length}catch(n){return{error:{message:`branch outcome cannot be serialised to JSON (${M(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<=I?t:{error:{message:`branch outcome serialises to ${String(e)} bytes, over Cloudflare's ${String(I)}-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"}},w=async(t,e)=>{try{return{attached:!1,instance:await t.create(e)}}catch(n){if(!P(n))throw n;return{attached:!0,instance:await t.get(e.id)}}},X=async t=>{const{error:e,output:n,status:a}=await t.status();if(a==="complete")return W(n);if(a==="errored"||a==="terminated")return{error:e??{message:`branch instance ${a}`,name:"Error"},status:"error"}},j=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(`${C}${o.plan.childId}`,async()=>{const d=F(o.plan.childId),h={branch:o.plan.item.workflow,error:n,index:o.plan.index,output:o.output};return await w(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)}}},G=t=>async n=>{if(n.length===0)return[];if(n.length>y)throw new f(`ctx.parallel: ${String(n.length)} branches exceeds the cap of ${String(y)} — split the fan-out or raise the work into fewer child workflows`);const a=n.map((r,s)=>{const i=t.nextChildId(r.id);return{childId:i,eventType:`${b}${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(`${$}${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:x}=await w(s,{id:r.childId,params:{...r.item.params,[g]:i}});if(!u)return;const E=await X(x);return E===void 0?void 0:T(E)}))),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(`${O}${r.childId}`,{timeout:r.item.timeout,type:r.eventType})).payload}catch(u){throw new m(r,S(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,j(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},U=t=>async(e,n,a)=>{if(_(n))throw new B("BAD_REQUEST",`@lunora/workflow: params ${R}`);const o=t.nextChildId(a?.id);return await t.step.do(`${$}${o}`,async()=>{const c=t.resolveBinding(e);return await w(c,{id:o,params:n}),o}),t.resolveBinding(e).get(o)},q=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(b)))return{eventType:n.eventType,index:n.index,parentBinding:n.parentBinding,parentId:n.parentId}},Q=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=T(n);await t.step.do(`${k}${String(e.index)}`,async()=>(await(await o(e.parentId)).sendEvent({payload:c,type:e.eventType}),e.eventType))},Z=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{y as MAX_BRANCHES,Y as branch,G as createParallel,U as createSpawn,z as errorOutcome,q as extractBranchMarker,W as okOutcome,L as signalBranchParent,Z as signalBranchParentSafe,Q as stripBranchMarker};
@@ -1 +0,0 @@
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};
@@ -1 +0,0 @@
1
- import{c as p,v as o}from"./run-step-CAUCn1UO.mjs";import"./defineWorkflowEvent-suERPEEV.mjs";import"./NonRetryableError-BV6ELTK1.mjs";export{p as createRunStep,o as validateStepArgs};
@@ -1 +0,0 @@
1
- import{J as w,c as v}from"./run-step-CAUCn1UO.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-DQ7WZU8W.mjs";import{createWaitForEvent as p}from"./createWaitForEvent-KkdE11qX.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};
@@ -1 +0,0 @@
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-BV6ELTK1.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};