@stacksjs/cron 0.75.382 → 0.75.387

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/index.d.ts CHANGED
@@ -1,13 +1,18 @@
1
1
  /// <reference path="./bun-cron.d.ts" />
2
2
  import { parseCron } from './parser';
3
- // Parse a cron expression and return the next matching Date.
4
- // Uses Bun's native cron parser when available, otherwise falls back
5
- // to our own 5-field parser with identical behavior.
3
+ // Parse a cron expression and return the next matching Date, in UTC unless
4
+ // `options.tz` names a zone.
6
5
  //
7
6
  // Examples:
8
7
  // parse('0 0 * * *') → next midnight UTC
9
8
  // parse('@hourly') → next hour
10
9
  // parse('0,15,30,45 * * * *') → next 15-min mark
10
+ //
11
+ // Not `Bun.cron.parse`, though it exists. That one answers in the process's
12
+ // local time, as crontab does, so handing it the call made "midnight" mean
13
+ // midnight UTC on a UTC server and midnight wherever the server was otherwise.
14
+ // The scheduler's UTC path calls this without a `tz`, so a UTC app on a New
15
+ // York box ran its daily tasks at 05:00 UTC.
11
16
  export declare function parse(expression: string, relativeDate?: Date | number, options?: import('./parser').ParseCronOptions): Date | null;
12
17
  /**
13
18
  * Register an OS-level cron job that persists across process restarts.
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // @bun
2
- var F={"@yearly":"0 0 1 1 *","@annually":"0 0 1 1 *","@monthly":"0 0 1 * *","@weekly":"0 0 * * 0","@daily":"0 0 * * *","@midnight":"0 0 * * *","@hourly":"0 * * * *"},O={jan:1,feb:2,mar:3,apr:4,may:5,jun:6,jul:7,aug:8,sep:9,oct:10,nov:11,dec:12,january:1,february:2,march:3,april:4,june:6,july:7,august:8,september:9,october:10,november:11,december:12},P={sun:0,mon:1,tue:2,wed:3,thu:4,fri:5,sat:6,sunday:0,monday:1,tuesday:2,wednesday:3,thursday:4,friday:5,saturday:6},S=new Set;function z(r,t){if(S.has(r))return;S.add(r),console.warn(`[cron] 6-field cron expression '${r}' has seconds='${t}' - the parser is 5-field only. Seconds field IGNORED. For second-precision use the scheduler's '.everySecond()' instead.`)}function R(r,t){return r.replace(/[a-z]+/gi,(o)=>{let c=t[o.toLowerCase()];if(c===void 0)throw Error(`Invalid cron value: ${o}`);return String(c)})}function w(r,t,o,c){let b=c?R(r,c):r,a=new Set;for(let m of b.split(",")){let l=m.match(/^(.+)\/(\d+)$/),u,d=1;if(l){if(u=l[1]??"",d=Number.parseInt(l[2]??"",10),d<=0)throw Error(`Invalid step: ${d}`)}else u=m;if(u==="*")for(let s=t;s<=o;s+=d)a.add(s);else if(u.includes("-")){let[s,i]=u.split("-"),h=Number.parseInt(s??"",10),f=Number.parseInt(i??"",10);if(Number.isNaN(h)||Number.isNaN(f))throw Error(`Invalid range: ${u}`);if(h<t||f>o)throw Error(`Range out of bounds: ${u} (${t}-${o})`);for(let g=h;g<=f;g+=d)a.add(g)}else{let s=Number.parseInt(u,10);if(Number.isNaN(s))throw Error(`Invalid cron value: ${u}`);if(s<t||s>o)throw Error(`Value out of range: ${s} (${t}-${o})`);a.add(s)}}return a}function M(r,t,o={}){let c=r.trim(),a=(F[c.toLowerCase()]??c).split(/\s+/).filter(Boolean);if(a.length===6){let e=a[0];if(e!=="0"&&e!=="*")z(r,e);a=a.slice(1)}if(a.length!==5)throw Error(`Invalid cron expression: expected 5 fields (or 6 with leading seconds), got ${a.length}`);let[m,l,u,d,s]=a,i=w(m,0,59),h=w(l,0,23),f=w(u,1,31),g=w(d,1,12,O),p=w(s,0,7,P);if(p.has(7))p.add(0),p.delete(7);let T=u==="*",v=s==="*",C=t instanceof Date?t.getTime():typeof t==="number"?t:Date.now();if(Number.isNaN(C)||!Number.isFinite(C))throw Error("Invalid date");let N=o.tz,D=N?j(N):(e)=>({year:e.getUTCFullYear(),month:e.getUTCMonth()+1,day:e.getUTCDate(),hour:e.getUTCHours(),minute:e.getUTCMinutes(),dow:e.getUTCDay()}),n=new Date(C);n.setUTCSeconds(0,0),n.setUTCMinutes(n.getUTCMinutes()+1);let E=n.getTime()+126230400000;while(n.getTime()<E){let e=D(n);if(N){let B=T&&v?!0:T?p.has(e.dow):v?f.has(e.day):f.has(e.day)||p.has(e.dow);if(!g.has(e.month)||!B||!h.has(e.hour)){n.setTime(n.getTime()+(60-e.minute)*60000);continue}if(!i.has(e.minute)){n.setTime(n.getTime()+60000);continue}return new Date(n.getTime())}if(!g.has(e.month)){n.setUTCMonth(n.getUTCMonth()+1,1),n.setUTCHours(0,0,0,0);continue}let U=f.has(e.day),I=p.has(e.dow),y;if(T&&v)y=!0;else if(T)y=I;else if(v)y=U;else y=U||I;if(!y){n.setUTCDate(n.getUTCDate()+1),n.setUTCHours(0,0,0,0);continue}if(!h.has(e.hour)){n.setUTCHours(n.getUTCHours()+1,0,0,0);continue}if(!i.has(e.minute)){n.setUTCMinutes(n.getUTCMinutes()+1,0,0);continue}return new Date(n.getTime())}return null}function j(r){let t=new Intl.DateTimeFormat("en-US",{timeZone:r,hourCycle:"h23",year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",weekday:"short"}),o={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};return(c)=>{let b=t.formatToParts(c),a=0,m=0,l=0,u=0,d=0,s=0;for(let i of b)if(i.type==="year")a=Number.parseInt(i.value,10);else if(i.type==="month")m=Number.parseInt(i.value,10);else if(i.type==="day")l=Number.parseInt(i.value,10);else if(i.type==="hour")u=Number.parseInt(i.value,10)%24;else if(i.type==="minute")d=Number.parseInt(i.value,10);else if(i.type==="weekday")s=o[i.value]??0;return{year:a,month:m,day:l,hour:u,minute:d,dow:s}}}function k(r,t,o={}){if(!o.tz&&typeof Bun<"u"&&Bun.cron?.parse)return Bun.cron.parse(r,t);return M(r,t,o)}async function x(r,t,o){if(typeof Bun>"u"||!Bun.cron)throw Error("Bun.cron is not available. OS-level cron requires a Bun version with native cron support.");await Bun.cron(r,t,o)}async function A(r){if(typeof Bun>"u"||!Bun.cron?.remove)throw Error("Bun.cron is not available. OS-level cron requires a Bun version with native cron support.");await Bun.cron.remove(r)}export{k as parse,M as parseCron,x as register,A as remove};
2
+ var B={"@yearly":"0 0 1 1 *","@annually":"0 0 1 1 *","@monthly":"0 0 1 * *","@weekly":"0 0 * * 0","@daily":"0 0 * * *","@midnight":"0 0 * * *","@hourly":"0 * * * *"},F={jan:1,feb:2,mar:3,apr:4,may:5,jun:6,jul:7,aug:8,sep:9,oct:10,nov:11,dec:12,january:1,february:2,march:3,april:4,june:6,july:7,august:8,september:9,october:10,november:11,december:12},P={sun:0,mon:1,tue:2,wed:3,thu:4,fri:5,sat:6,sunday:0,monday:1,tuesday:2,wednesday:3,thursday:4,friday:5,saturday:6},O=/^(\*|\d+(?:-\d+)?)(?:\/(\d+))?$/;function R(i,r){return i.replace(/[a-z]+/gi,(o)=>{let c=r[o.toLowerCase()];if(c===void 0)throw Error(`Invalid cron value: ${o}`);return String(c)})}function y(i,r,o,c){let w=c?R(i,c):i,s=new Set;for(let m of w.split(",")){let f=O.exec(m);if(!f)throw Error(`Invalid cron value: ${m}`);let[,u="",l]=f,a=l===void 0?1:Number(l);if(a<=0)throw Error(`Invalid step: ${a}`);if(u==="*")for(let e=r;e<=o;e+=a)s.add(e);else if(u.includes("-")){let[e,d]=u.split("-").map(Number);if(e<r||d>o)throw Error(`Range out of bounds: ${u} (${r}-${o})`);if(e>d)throw Error(`Range must be ascending: ${u} (list both ends, e.g. '${e}-${o},${r}-${d}')`);for(let h=e;h<=d;h+=a)s.add(h)}else{let e=Number(u);if(e<r||e>o)throw Error(`Value out of range: ${e} (${r}-${o})`);if(l===void 0)s.add(e);else for(let d=e;d<=o;d+=a)s.add(d)}}return s}function U(i,r,o={}){let c=i.trim(),s=(B[c.toLowerCase()]??c).split(/\s+/).filter(Boolean);if(s.length===6){if(s[0]!=="0")throw Error(`Invalid cron expression: '${i}' runs on seconds ('${s[0]}'), and this parser has minute resolution. Use a seconds field of 0, or the scheduler's .everySecond() / .cron('*/N * * * * *')`);s=s.slice(1)}if(s.length!==5)throw Error(`Invalid cron expression: expected 5 fields (or 6 with leading seconds), got ${s.length}`);let[m,f,u,l,a]=s,e=y(m,0,59),d=y(f,0,23),h=y(u,1,31),M=y(l,1,12,F),g=y(a,0,7,P);if(g.has(7))g.add(0),g.delete(7);let b=u==="*",T=a==="*",v=r instanceof Date?r.getTime():typeof r==="number"?r:Date.now();if(Number.isNaN(v)||!Number.isFinite(v))throw Error("Invalid date");let C=o.tz,E=C?x(C):(t)=>({year:t.getUTCFullYear(),month:t.getUTCMonth()+1,day:t.getUTCDate(),hour:t.getUTCHours(),minute:t.getUTCMinutes(),dow:t.getUTCDay()}),n=new Date(v);n.setUTCSeconds(0,0),n.setUTCMinutes(n.getUTCMinutes()+1);let I=n.getTime()+126230400000;while(n.getTime()<I){let t=E(n);if(C){let S=b&&T?!0:b?g.has(t.dow):T?h.has(t.day):h.has(t.day)||g.has(t.dow);if(!M.has(t.month)||!S||!d.has(t.hour)){n.setTime(n.getTime()+(60-t.minute)*60000);continue}if(!e.has(t.minute)){n.setTime(n.getTime()+60000);continue}return new Date(n.getTime())}if(!M.has(t.month)){n.setUTCMonth(n.getUTCMonth()+1,1),n.setUTCHours(0,0,0,0);continue}let N=h.has(t.day),D=g.has(t.dow),p;if(b&&T)p=!0;else if(b)p=D;else if(T)p=N;else p=N||D;if(!p){n.setUTCDate(n.getUTCDate()+1),n.setUTCHours(0,0,0,0);continue}if(!d.has(t.hour)){n.setUTCHours(n.getUTCHours()+1,0,0,0);continue}if(!e.has(t.minute)){n.setUTCMinutes(n.getUTCMinutes()+1,0,0);continue}return new Date(n.getTime())}return null}function x(i){let r=new Intl.DateTimeFormat("en-US",{timeZone:i,hourCycle:"h23",year:"numeric",month:"numeric",day:"numeric",hour:"numeric",minute:"numeric",weekday:"short"}),o={Sun:0,Mon:1,Tue:2,Wed:3,Thu:4,Fri:5,Sat:6};return(c)=>{let w=r.formatToParts(c),s=0,m=0,f=0,u=0,l=0,a=0;for(let e of w)if(e.type==="year")s=Number.parseInt(e.value,10);else if(e.type==="month")m=Number.parseInt(e.value,10);else if(e.type==="day")f=Number.parseInt(e.value,10);else if(e.type==="hour")u=Number.parseInt(e.value,10)%24;else if(e.type==="minute")l=Number.parseInt(e.value,10);else if(e.type==="weekday")a=o[e.value]??0;return{year:s,month:m,day:f,hour:u,minute:l,dow:a}}}function A(i,r,o={}){return U(i,r,o)}async function H(i,r,o){if(typeof Bun>"u"||!Bun.cron)throw Error("Bun.cron is not available. OS-level cron requires a Bun version with native cron support.");await Bun.cron(i,r,o)}async function k(i){if(typeof Bun>"u"||!Bun.cron?.remove)throw Error("Bun.cron is not available. OS-level cron requires a Bun version with native cron support.");await Bun.cron.remove(i)}export{A as parse,U as parseCron,H as register,k as remove};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/cron",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.382",
5
+ "version": "0.75.387",
6
6
  "description": "The Stacks cron.",
7
7
  "author": "Chris Breuer",
8
8
  "contributors": [