@lunora/scheduler 1.0.0-alpha.44 → 1.0.0-alpha.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -83,7 +83,7 @@ import { api } from "@/lunora/_generated/api";
83
83
 
84
84
  const scheduler = createScheduler({ namespace: env.SCHEDULER, originUrl: "https://app.acme.test" });
85
85
 
86
- const { id } = await scheduler.runAfter(5 * 60_000, api.email.sendReminder, { userId: "u-1" });
86
+ const id = await scheduler.runAfter(5 * 60_000, api.email.sendReminder, { userId: "u-1" });
87
87
  await scheduler.cancel(id);
88
88
  ```
89
89
 
package/dist/index.d.mts CHANGED
@@ -81,6 +81,13 @@ interface RetryPolicy {
81
81
  maxMs?: number;
82
82
  }
83
83
  interface RunOptions {
84
+ /**
85
+ * Cap for the {@link RunOptions.pool} this job joins, applied when the pool
86
+ * is first created and refreshed on every enqueue that carries one. Ignored
87
+ * without `pool`. A pool created by a `runAfter`/`runAt` that omits it caps
88
+ * at 1 — {@link Workpool} is the usual way to set it.
89
+ */
90
+ maxConcurrency?: number;
84
91
  /**
85
92
  * Logical workpool this job belongs to. When set, the SchedulerDO gates the
86
93
  * job behind the pool's `maxConcurrency` (see {@link WorkpoolOptions}).
@@ -165,16 +172,24 @@ interface Scheduler {
165
172
  * `agents.<name>` ref — which starts a fresh instance on fire (args become
166
173
  * its `params`). {@link ScheduleTargetArgs} infers the accepted args from
167
174
  * whichever target was passed.
175
+ *
176
+ * **Resolves the job id, a bare string** — the same value `cancel`/`get`
177
+ * take, and the same value the `ctx.scheduler` surface promises. This object
178
+ * IS `ctx.scheduler` on the shard side (codegen installs it behind
179
+ * `SchedulerLike`, whose `runAfter`/`runAt` are declared `Promise<string>`),
180
+ * so resolving a `{ id, scheduledFor }` record here handed mutations an
181
+ * object where every other gate — `@lunora/server`'s `Scheduler`,
182
+ * `@lunora/shard-engine`'s `SchedulerLike`, `@lunora/runtime`'s httpAction
183
+ * ctx, and the docs — said string. Nothing caught it, because the install is
184
+ * a cast: apps wrote the object into a string column and `cancel(id)`
185
+ * answered `{ cancelled: false }` with no error anywhere.
186
+ *
187
+ * The fire instant is not lost: `runAt` was handed it, and a caller that
188
+ * needs it back reads `scheduledFor` off {@link Scheduler.get}.
168
189
  */
169
- runAfter: <T extends CronTarget>(delayMs: number, target: T, args: ScheduleTargetArgs<T>, options?: RunOptions) => Promise<{
170
- id: string;
171
- scheduledFor: number;
172
- }>;
173
- /** Like {@link Scheduler.runAfter} but fires at an absolute `date`/timestamp. */
174
- runAt: <T extends CronTarget>(date: Date | number, target: T, args: ScheduleTargetArgs<T>, options?: RunOptions) => Promise<{
175
- id: string;
176
- scheduledFor: number;
177
- }>;
190
+ runAfter: <T extends CronTarget>(delayMs: number, target: T, args: ScheduleTargetArgs<T>, options?: RunOptions) => Promise<string>;
191
+ /** Like {@link Scheduler.runAfter} but fires at an absolute `date`/timestamp. Resolves the job id. */
192
+ runAt: <T extends CronTarget>(date: Date | number, target: T, args: ScheduleTargetArgs<T>, options?: RunOptions) => Promise<string>;
178
193
  }
179
194
  /**
180
195
  * Cloudflare Durable Object data-residency jurisdiction. Widening union —
package/dist/index.d.ts CHANGED
@@ -81,6 +81,13 @@ interface RetryPolicy {
81
81
  maxMs?: number;
82
82
  }
83
83
  interface RunOptions {
84
+ /**
85
+ * Cap for the {@link RunOptions.pool} this job joins, applied when the pool
86
+ * is first created and refreshed on every enqueue that carries one. Ignored
87
+ * without `pool`. A pool created by a `runAfter`/`runAt` that omits it caps
88
+ * at 1 — {@link Workpool} is the usual way to set it.
89
+ */
90
+ maxConcurrency?: number;
84
91
  /**
85
92
  * Logical workpool this job belongs to. When set, the SchedulerDO gates the
86
93
  * job behind the pool's `maxConcurrency` (see {@link WorkpoolOptions}).
@@ -165,16 +172,24 @@ interface Scheduler {
165
172
  * `agents.<name>` ref — which starts a fresh instance on fire (args become
166
173
  * its `params`). {@link ScheduleTargetArgs} infers the accepted args from
167
174
  * whichever target was passed.
175
+ *
176
+ * **Resolves the job id, a bare string** — the same value `cancel`/`get`
177
+ * take, and the same value the `ctx.scheduler` surface promises. This object
178
+ * IS `ctx.scheduler` on the shard side (codegen installs it behind
179
+ * `SchedulerLike`, whose `runAfter`/`runAt` are declared `Promise<string>`),
180
+ * so resolving a `{ id, scheduledFor }` record here handed mutations an
181
+ * object where every other gate — `@lunora/server`'s `Scheduler`,
182
+ * `@lunora/shard-engine`'s `SchedulerLike`, `@lunora/runtime`'s httpAction
183
+ * ctx, and the docs — said string. Nothing caught it, because the install is
184
+ * a cast: apps wrote the object into a string column and `cancel(id)`
185
+ * answered `{ cancelled: false }` with no error anywhere.
186
+ *
187
+ * The fire instant is not lost: `runAt` was handed it, and a caller that
188
+ * needs it back reads `scheduledFor` off {@link Scheduler.get}.
168
189
  */
169
- runAfter: <T extends CronTarget>(delayMs: number, target: T, args: ScheduleTargetArgs<T>, options?: RunOptions) => Promise<{
170
- id: string;
171
- scheduledFor: number;
172
- }>;
173
- /** Like {@link Scheduler.runAfter} but fires at an absolute `date`/timestamp. */
174
- runAt: <T extends CronTarget>(date: Date | number, target: T, args: ScheduleTargetArgs<T>, options?: RunOptions) => Promise<{
175
- id: string;
176
- scheduledFor: number;
177
- }>;
190
+ runAfter: <T extends CronTarget>(delayMs: number, target: T, args: ScheduleTargetArgs<T>, options?: RunOptions) => Promise<string>;
191
+ /** Like {@link Scheduler.runAfter} but fires at an absolute `date`/timestamp. Resolves the job id. */
192
+ runAt: <T extends CronTarget>(date: Date | number, target: T, args: ScheduleTargetArgs<T>, options?: RunOptions) => Promise<string>;
178
193
  }
179
194
  /**
180
195
  * Cloudflare Durable Object data-residency jurisdiction. Widening union —
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{default as o}from"./packem_shared/createScheduler-DrXa1iXV.mjs";import{default as a}from"./packem_shared/createWorkpool-d3THj5gc.mjs";import{createCronTrigger as c}from"./packem_shared/createCronTrigger-DSuDZtqj.mjs";import{CRON_SCHEDULE_KINDS as f,compileCronSchedule as l,cronJobs as n}from"./packem_shared/CRON_SCHEDULE_KINDS-xyFk800s.mjs";import{createQueueConsumer as u,createQueueWorkpool as x,httpDispatcher as d}from"./packem_shared/createQueueConsumer-zagVuKf0.mjs";import{MAX_RETRY_ATTEMPTS as S,RETRY_BASE_DELAY_MS as E,SchedulerDO as C}from"./packem_shared/MAX_RETRY_ATTEMPTS-D24I8zY0.mjs";import{createSchedulerHost as h}from"./packem_shared/createSchedulerHost-C4HUMyFs.mjs";import{isWorkflowReference as T}from"./packem_shared/isWorkflowReference-CT3tdefh.mjs";import{assertValidCronExpression as A,isValidCronExpression as g,warnIfSecondsLeading as k}from"./packem_shared/assertValidCronExpression-DnBtukpq.mjs";export{f as CRON_SCHEDULE_KINDS,S as MAX_RETRY_ATTEMPTS,E as RETRY_BASE_DELAY_MS,C as SchedulerDO,A as assertValidCronExpression,l as compileCronSchedule,c as createCronTrigger,u as createQueueConsumer,x as createQueueWorkpool,o as createScheduler,h as createSchedulerHost,a as createWorkpool,n as cronJobs,d as httpDispatcher,g as isValidCronExpression,T as isWorkflowReference,k as warnIfSecondsLeading};
1
+ import{default as o}from"./packem_shared/createScheduler-CW8pPy0j.mjs";import{default as a}from"./packem_shared/createWorkpool-d3THj5gc.mjs";import{createCronTrigger as c}from"./packem_shared/createCronTrigger-DSuDZtqj.mjs";import{CRON_SCHEDULE_KINDS as f,compileCronSchedule as l,cronJobs as n}from"./packem_shared/CRON_SCHEDULE_KINDS-xyFk800s.mjs";import{createQueueConsumer as u,createQueueWorkpool as x,httpDispatcher as d}from"./packem_shared/createQueueConsumer-adiyW-4L.mjs";import{MAX_RETRY_ATTEMPTS as S,RETRY_BASE_DELAY_MS as E,SchedulerDO as C}from"./packem_shared/MAX_RETRY_ATTEMPTS-D24I8zY0.mjs";import{createSchedulerHost as h}from"./packem_shared/createSchedulerHost-B-5nnRt8.mjs";import{isWorkflowReference as T}from"./packem_shared/isWorkflowReference-CT3tdefh.mjs";import{assertValidCronExpression as A,isValidCronExpression as g,warnIfSecondsLeading as k}from"./packem_shared/assertValidCronExpression-DnBtukpq.mjs";export{f as CRON_SCHEDULE_KINDS,S as MAX_RETRY_ATTEMPTS,E as RETRY_BASE_DELAY_MS,C as SchedulerDO,A as assertValidCronExpression,l as compileCronSchedule,c as createCronTrigger,u as createQueueConsumer,x as createQueueWorkpool,o as createScheduler,h as createSchedulerHost,a as createWorkpool,n as cronJobs,d as httpDispatcher,g as isValidCronExpression,T as isWorkflowReference,k as warnIfSecondsLeading};
@@ -1 +1 @@
1
- import{LunoraError as i}from"@lunora/errors";const O=(t,e,n)=>{if(e===void 0)return{dispose:()=>{},signal:t};const o=new AbortController,a=setTimeout(()=>{o.abort(n())},e);return{dispose:()=>{clearTimeout(a)},signal:o.signal}},c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",_=t=>{let e="",n=0;const o=t.length-2;for(;n<o;n+=3){const r=t[n]<<16|t[n+1]<<8|t[n+2];e+=c.charAt(r>>18&63)+c.charAt(r>>12&63)+c.charAt(r>>6&63)+c.charAt(r&63)}const a=t.length-n;if(a===1){const r=t[n]<<16;e+=c.charAt(r>>18&63)+c.charAt(r>>12&63)}else if(a===2){const r=t[n]<<16|t[n+1]<<8;e+=c.charAt(r>>18&63)+c.charAt(r>>12&63)+c.charAt(r>>6&63)}return e};new TextDecoder;const I=new TextEncoder,N="=",b=t=>{for(let e=0;e<t.length;e+=1)if(t.charCodeAt(e)>255)return!1;return!0},E=t=>_(I.encode(JSON.stringify(t))),L=t=>!t.startsWith(N)&&b(t)?t:`${N}${_(I.encode(t))}`,$="/_lunora/scheduler/dispatch",S=3e4,v=t=>{let e=t.length;for(;e>0&&t[e-1]==="/";)e-=1;return t.slice(0,e)},U=Symbol("lunoraDispatchFailure"),D=Symbol("lunoraDispatchMessageId"),w=(t,e)=>(Object.defineProperty(t,U,{value:!0}),e!==void 0&&Object.defineProperty(t,D,{value:e}),t),K=(t,e,n,o)=>{try{const a=JSON.parse(n)?.error;if(typeof a=="object"&&a!==null&&typeof a.code=="string"){const{code:r,data:s,message:u}=a;return w(new i(r,typeof u=="string"?u:void 0,{data:s,status:e}),o)}}catch{}return w(new i("INTERNAL",`${t}: function dispatch failed (${String(e)}): ${n}`,{status:e}),o)},M=(t,e,n)=>new i("INTERNAL",`${t}: function dispatch to "${e}" timed out after ${String(n)}ms`,{status:503}),x=t=>{const{label:e}=t,n=globalThis.fetch,o=t.fetchImpl??(typeof n=="function"?n.bind(globalThis):void 0);return async(a,r,s={})=>{if(typeof o!="function")throw new TypeError(`${e}: no fetch implementation available — pass fetchImpl or run on a platform with global fetch`);const u=t.env.LUNORA_ORIGIN_URL;if(typeof u!="string"||u.length===0)throw new i("INTERNAL",`${e}: \`LUNORA_ORIGIN_URL\` must be set on the Worker env so a handler can call back into Lunora functions`);const f=t.env.LUNORA_ADMIN_TOKEN;if(typeof f!="string"||f.length===0)throw new i("INTERNAL",`${e}: \`LUNORA_ADMIN_TOKEN\` must be set on the Worker env to authenticate function dispatch`);const R=`${v(u)}${$}`,y={authorization:`Bearer ${f}`,"content-type":"application/json"};t.identity?.userId!==void 0&&(y["x-lunora-userid"]=L(t.identity.userId)),t.identity?.claims!==void 0&&(y["x-lunora-identity"]=E(t.identity.claims));const g=s.timeoutMs??S,m=O(void 0,g,()=>new DOMException(`dispatch timed out after ${String(g)}ms`,"TimeoutError")),p=d=>{throw d instanceof Error&&d.name==="TimeoutError"?M(e,a.__lunoraRef,g):d};let l;try{try{l=await o(R,{body:JSON.stringify({args:r??{},functionPath:a.__lunoraRef,id:s.dedupId,shardKey:s.shardKey}),headers:y,method:"POST",signal:m.signal})}catch(h){return p(h)}if(!l.ok){let h;try{h=await l.text()}catch(T){return p(T)}throw K(e,l.status,h,s.messageId)}let d;try{d=await l.text()}catch(h){return p(h)}if(d.length===0)return;try{return JSON.parse(d)}catch{throw new i("INTERNAL",`${e}: function dispatch returned a non-JSON body (${String(l.status)}): ${d}`,{status:l.status})}}finally{m.dispose()}}},A=100,P=3e5,k=t=>{if(!t.queue)throw new i("INTERNAL","@lunora/scheduler: `queue` (a Cloudflare Queue binding) is required");return{enqueue:async(o,a,r={})=>{const s={args:a,functionPath:o.__lunoraRef,shardKey:r.shardKey},u=r.delaySeconds===void 0?void 0:{delaySeconds:r.delaySeconds};await t.queue.send(s,u)},enqueueBatch:async(o,a)=>{if(o.length>A)throw new i("VALIDATION_ERROR",`@lunora/scheduler: enqueueBatch exceeds ${String(A)} (got ${String(o.length)}) — split across calls`);const r=o.map(s=>({body:{args:s.args,functionPath:s.ref.__lunoraRef,shardKey:s.shardKey}}));await t.queue.sendBatch(r,a)}}},q=t=>typeof t=="object"&&t!==null&&typeof t.functionPath=="string",B=t=>async e=>{await Promise.all(e.messages.map(async n=>{try{if(!q(n.body))throw new i("INTERNAL","@lunora/scheduler: queue message body is not a QueueJob (missing functionPath)");await t.dispatch(n.body,n.id),n.ack()}catch{n.retry()}}))},C=t=>{const e=x({env:{LUNORA_ADMIN_TOKEN:t.adminToken,LUNORA_ORIGIN_URL:t.originUrl},fetchImpl:t.fetchImpl,label:"@lunora/scheduler"}),n=t.timeoutMs??P;return async(o,a)=>{await e({__lunoraRef:o.functionPath},o.args,{messageId:a,shardKey:o.shardKey,timeoutMs:n})}};export{B as createQueueConsumer,k as createQueueWorkpool,C as httpDispatcher};
1
+ import{LunoraError as i}from"@lunora/errors";const O=(t,e,n)=>{if(e===void 0)return{dispose:()=>{},signal:t};const o=new AbortController,a=setTimeout(()=>{o.abort(n())},e);return{dispose:()=>{clearTimeout(a)},signal:o.signal}},c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",_=t=>{let e="",n=0;const o=t.length-2;for(;n<o;n+=3){const r=t[n]<<16|t[n+1]<<8|t[n+2];e+=c.charAt(r>>18&63)+c.charAt(r>>12&63)+c.charAt(r>>6&63)+c.charAt(r&63)}const a=t.length-n;if(a===1){const r=t[n]<<16;e+=c.charAt(r>>18&63)+c.charAt(r>>12&63)}else if(a===2){const r=t[n]<<16|t[n+1]<<8;e+=c.charAt(r>>18&63)+c.charAt(r>>12&63)+c.charAt(r>>6&63)}return e};new TextDecoder;const I=new TextEncoder,m="=",b=t=>{for(let e=0;e<t.length;e+=1)if(t.charCodeAt(e)>255)return!1;return!0},E=t=>_(I.encode(JSON.stringify(t))),L=t=>!t.startsWith(m)&&b(t)?t:`${m}${_(I.encode(t))}`,$="/_lunora/scheduler/dispatch",S=3e4,v=t=>{let e=t.length;for(;e>0&&t[e-1]==="/";)e-=1;return t.slice(0,e)},U=Symbol("lunoraDispatchFailure"),D=Symbol("lunoraDispatchMessageId"),w=(t,e)=>(Object.defineProperty(t,U,{value:!0}),e!==void 0&&Object.defineProperty(t,D,{value:e}),t),K=(t,e,n,o)=>{try{const a=JSON.parse(n)?.error;if(typeof a=="object"&&a!==null&&typeof a.code=="string"){const{code:r,data:s,message:u}=a;return w(new i(r,typeof u=="string"?u:void 0,{data:s,status:e}),o)}}catch{}return w(new i("INTERNAL",`${t}: function dispatch failed (${String(e)}): ${n}`,{status:e}),o)},M=(t,e,n)=>new i("INTERNAL",`${t}: function dispatch to "${e}" timed out after ${String(n)}ms`,{status:503}),x=t=>{const{label:e}=t,n=globalThis.fetch,o=t.fetchImpl??(typeof n=="function"?n.bind(globalThis):void 0);return async(a,r,s={})=>{if(typeof o!="function")throw new TypeError(`${e}: no fetch implementation available — pass fetchImpl or run on a platform with global fetch`);const u=t.env.LUNORA_ORIGIN_URL;if(typeof u!="string"||u.length===0)throw new i("INTERNAL",`${e}: \`LUNORA_ORIGIN_URL\` must be set on the Worker env so a handler can call back into Lunora functions`);const f=t.env.LUNORA_ADMIN_TOKEN;if(typeof f!="string"||f.length===0)throw new i("INTERNAL",`${e}: \`LUNORA_ADMIN_TOKEN\` must be set on the Worker env to authenticate function dispatch`);const R=`${v(u)}${$}`,y={authorization:`Bearer ${f}`,"content-type":"application/json"};t.identity?.userId!==void 0&&(y["x-lunora-userid"]=L(t.identity.userId)),t.identity?.claims!==void 0&&(y["x-lunora-identity"]=E(t.identity.claims));const p=s.timeoutMs??S,N=O(void 0,p,()=>new DOMException(`dispatch timed out after ${String(p)}ms`,"TimeoutError")),g=d=>{throw d instanceof Error&&d.name==="TimeoutError"?M(e,a.__lunoraRef,p):d};let l;try{try{l=await o(R,{body:JSON.stringify({args:r??{},functionPath:a.__lunoraRef,id:s.dedupId,shardKey:s.shardKey}),headers:y,method:"POST",signal:N.signal})}catch(h){return g(h)}if(!l.ok){let h;try{h=await l.text()}catch(T){return g(T)}throw K(e,l.status,h,s.messageId)}let d;try{d=await l.text()}catch(h){return g(h)}if(d.length===0)return;try{return JSON.parse(d)}catch{throw new i("INTERNAL",`${e}: function dispatch returned a non-JSON body (${String(l.status)}): ${d}`,{status:l.status})}}finally{N.dispose()}}},A=100,P=3e5,k=t=>{if(!t.queue)throw new i("INTERNAL","@lunora/scheduler: `queue` (a Cloudflare Queue binding) is required");return{enqueue:async(o,a,r={})=>{const s={args:a,functionPath:o.__lunoraRef,shardKey:r.shardKey},u=r.delaySeconds===void 0?void 0:{delaySeconds:r.delaySeconds};await t.queue.send(s,u)},enqueueBatch:async(o,a)=>{if(o.length>A)throw new i("VALIDATION_ERROR",`@lunora/scheduler: enqueueBatch exceeds ${String(A)} (got ${String(o.length)}) — split across calls`);const r=o.map(s=>({body:{args:s.args,functionPath:s.ref.__lunoraRef,shardKey:s.shardKey}}));await t.queue.sendBatch(r,a)}}},q=t=>typeof t=="object"&&t!==null&&typeof t.functionPath=="string",B=t=>async e=>{await Promise.all(e.messages.map(async n=>{try{if(!q(n.body))throw new i("INTERNAL","@lunora/scheduler: queue message body is not a QueueJob (missing functionPath)");await t.dispatch(n.body,n.id),n.ack()}catch{n.retry()}}))},C=t=>{const e=x({env:{LUNORA_ADMIN_TOKEN:t.adminToken,LUNORA_ORIGIN_URL:t.originUrl},fetchImpl:t.fetchImpl,label:"@lunora/scheduler"}),n=t.timeoutMs??P;return async(o,a)=>{await e({__lunoraRef:o.functionPath},o.args,{dedupId:a,messageId:a,shardKey:o.shardKey,timeoutMs:n})}};export{B as createQueueConsumer,k as createQueueWorkpool,C as httpDispatcher};
@@ -0,0 +1 @@
1
+ import{LunoraError as i}from"@lunora/errors";import{a as y,c as a,g as s}from"./do-client-BKEFA9pM.mjs";import{isWorkflowReference as f}from"./isWorkflowReference-CT3tdefh.mjs";const x=n=>{y(n);const d=async(e,r,t,c={})=>{const u=e instanceof Date?e.getTime():e,o={args:t,instanceName:n.instanceName??"default",maxConcurrency:c.pool===void 0?void 0:c.maxConcurrency,originUrl:n.originUrl,pool:c.pool,retry:c.retry,scheduledFor:u,shardKey:c.shardKey};if(f(r)){if(typeof r.binding!="string"||r.binding.length===0)throw new i("INTERNAL","@lunora/scheduler: workflow/agent schedule target is missing its `binding` — pass the generated `workflows.<name>` / `agents.<name>` reference");return(await a(n,"/schedule",{...o,workflow:r.binding})).id}const l=typeof r=="string"?r:r.__lunoraRef;return(await a(n,"/schedule",{...o,functionPath:l})).id};return{cancel:async e=>a(n,"/cancel",{id:e}),dead:async()=>{const e=await s(n,"/dead");return Array.isArray(e.records)?e.records:[]},deadRetry:async e=>{const{retried:r}=await a(n,"/dead/retry",{id:e});return r===!0},get:async e=>(await s(n,`/get?id=${encodeURIComponent(e)}`)).record??null,list:async()=>{const e=await s(n,"/list");return Array.isArray(e.records)?e.records:[]},runAfter:async(e,r,t,c={})=>{if(!Number.isFinite(e)||e<0)throw new i("INTERNAL","@lunora/scheduler: `delayMs` must be a non-negative finite number");return d(Date.now()+e,r,t,c)},runAt:d}};export{x as default};
@@ -1 +1 @@
1
- import d from"./createScheduler-DrXa1iXV.mjs";const u=t=>t?.at!==void 0?typeof t.at=="number"?t.at:t.at.getTime():Date.now()+(t?.delayMs??0),l=t=>{const a=d({instanceName:t.instanceName,jurisdiction:t.jurisdiction,namespace:t.namespace,originUrl:t.originUrl}),n=e=>({attempts:e.attempts??0,functionPath:e.functionPath??e.workflow??"",id:e.id,scheduledFor:e.scheduledFor});return{cancel:async e=>{const{cancelled:r}=await a.cancel(e);return r},deadLetter:{list:async()=>(await a.dead()).map(r=>n(r)),requeue:async e=>a.deadRetry(e)},list:async()=>(await a.list()).map(r=>n(r)),schedule:async(e,r,c)=>{const s=a.runAt;return s(u(c),e,r,{retry:c?.retry,shardKey:c?.shardKey})}}};export{l as createSchedulerHost};
1
+ import u from"./createScheduler-CW8pPy0j.mjs";const i=t=>t?.at!==void 0?typeof t.at=="number"?t.at:t.at.getTime():Date.now()+(t?.delayMs??0),m=t=>{const a=u({instanceName:t.instanceName,jurisdiction:t.jurisdiction,namespace:t.namespace,originUrl:t.originUrl}),n=e=>({attempts:e.attempts??0,functionPath:e.functionPath??e.workflow??"",id:e.id,scheduledFor:e.scheduledFor});return{cancel:async e=>{const{cancelled:r}=await a.cancel(e);return r},deadLetter:{list:async()=>(await a.dead()).map(r=>n(r)),requeue:async e=>a.deadRetry(e)},list:async()=>(await a.list()).map(r=>n(r)),schedule:async(e,r,c)=>{const d=a.runAt,s=i(c);return{id:await d(s,e,r,{retry:c?.retry,shardKey:c?.shardKey}),scheduledFor:s}}}};export{m as createSchedulerHost};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/scheduler",
3
- "version": "1.0.0-alpha.44",
3
+ "version": "1.0.0-alpha.46",
4
4
  "description": "Scheduling for Lunora: runAfter / runAt and Cron Triggers via SchedulerDO",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -46,8 +46,8 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@lunora/errors": "1.0.0-alpha.26",
50
- "@lunora/platform": "1.0.0-alpha.21",
49
+ "@lunora/errors": "1.0.0-alpha.27",
50
+ "@lunora/platform": "1.0.0-alpha.23",
51
51
  "cron-parser": "5.8.1"
52
52
  },
53
53
  "engines": {
@@ -1 +0,0 @@
1
- import{LunoraError as i}from"@lunora/errors";import{a as y,c as s,g as a}from"./do-client-BKEFA9pM.mjs";import{isWorkflowReference as f}from"./isWorkflowReference-CT3tdefh.mjs";const D=n=>{y(n);const o=async(e,r,c,t={})=>{const l=e instanceof Date?e.getTime():e,d={args:c,originUrl:n.originUrl,pool:t.pool,retry:t.retry,scheduledFor:l,shardKey:t.shardKey};if(f(r)){if(typeof r.binding!="string"||r.binding.length===0)throw new i("INTERNAL","@lunora/scheduler: workflow/agent schedule target is missing its `binding` — pass the generated `workflows.<name>` / `agents.<name>` reference");return s(n,"/schedule",{...d,workflow:r.binding})}const u=typeof r=="string"?r:r.__lunoraRef;return s(n,"/schedule",{...d,functionPath:u})};return{cancel:async e=>s(n,"/cancel",{id:e}),dead:async()=>{const e=await a(n,"/dead");return Array.isArray(e.records)?e.records:[]},deadRetry:async e=>{const{retried:r}=await s(n,"/dead/retry",{id:e});return r===!0},get:async e=>(await a(n,`/get?id=${encodeURIComponent(e)}`)).record??null,list:async()=>{const e=await a(n,"/list");return Array.isArray(e.records)?e.records:[]},runAfter:async(e,r,c,t={})=>{if(!Number.isFinite(e)||e<0)throw new i("INTERNAL","@lunora/scheduler: `delayMs` must be a non-negative finite number");return o(Date.now()+e,r,c,t)},runAt:o}};export{D as default};