@stacksjs/cron 0.70.23 → 0.70.25
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 +21 -21
- package/dist/index.js +1 -1
- package/dist/src/index.d.ts +41 -0
- package/dist/src/parser.d.ts +8 -0
- package/dist/src/types.d.ts +5 -0
- package/package.json +19 -6
- package/dist/index.d.ts +0 -3
- package/dist/types.d.ts +0 -4
package/README.md
CHANGED
|
@@ -38,62 +38,62 @@ Drivers are configured with the following environment variables:
|
|
|
38
38
|
#### Twilio
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
TWILIO*ACCOUNT*SID=ACtest
|
|
42
|
+
TWILIO*AUTH*TOKEN=testtoken
|
|
43
|
+
TWILIO*FROM*NUMBER=+112345
|
|
44
|
+
TWILIO*TO*NUMBER=+145678
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
#### Nexmo
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
VONAGE*API*KEY=VN123
|
|
51
|
+
VONAGE*API*SECRET=testkey
|
|
52
|
+
VONAGE*FROM*NUMBER=+112345
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
#### Gupshup
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
GUPSHUP*USER*ID=GU123
|
|
59
|
+
GUPSHUP*PASSWORD=password
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
#### Plivo
|
|
63
63
|
|
|
64
64
|
```bash
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
PLIVO*ACCOUNT*ID=PA123
|
|
66
|
+
PLIVO*AUTH*TOKEN=testtoken
|
|
67
|
+
PLIVO*FROM*NUMBER=+112345
|
|
68
68
|
```
|
|
69
69
|
|
|
70
70
|
#### SMS77
|
|
71
71
|
|
|
72
72
|
```bash
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
SMS77*API*KEY=SA123
|
|
74
|
+
SMS77*FROM=from@example.com
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
#### SNS
|
|
78
78
|
|
|
79
79
|
```bash
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
SMS77*API*KEY=SA123
|
|
81
|
+
SMS77*FROM=from@example.com
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
#### Telnyx
|
|
85
85
|
|
|
86
86
|
```bash
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
TELNYX*API*KEY=TA123
|
|
88
|
+
TELNYX*MESSAGE*PROFILE*ID=testprofileid
|
|
89
|
+
TELNYX*FROM=from@example.com
|
|
90
90
|
```
|
|
91
91
|
|
|
92
92
|
#### Termii
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
TERMII*API*KEY=TermA123
|
|
96
|
+
TERMII*SENDER=from@example.com
|
|
97
97
|
```
|
|
98
98
|
|
|
99
99
|
Learn more in the docs.
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
function l(t,e,i,r,s,n,o,a){return l.fromTZ(l.tp(t,e,i,r,s,n,o),a)}l.fromTZISO=(t,e,i)=>l.fromTZ(_(t,e),i);l.fromTZ=function(t,e){let i=new Date(Date.UTC(t.y,t.m-1,t.d,t.h,t.i,t.s)),r=T(t.tz,i),s=new Date(i.getTime()-r),n=T(t.tz,s);if(n-r===0)return s;{let o=new Date(i.getTime()-n),a=T(t.tz,o);if(a-n===0)return o;if(!e&&a-n>0)return o;if(e)throw new Error("Invalid date passed to fromTZ()");return s}};l.toTZ=function(t,e){let i=t.toLocaleString("en-US",{timeZone:e}).replace(/[\u202f]/," "),r=new Date(i);return{y:r.getFullYear(),m:r.getMonth()+1,d:r.getDate(),h:r.getHours(),i:r.getMinutes(),s:r.getSeconds(),tz:e}};l.tp=(t,e,i,r,s,n,o)=>({y:t,m:e,d:i,h:r,i:s,s:n,tz:o});function T(t,e=new Date){let i=e.toLocaleString("en-US",{timeZone:t,timeZoneName:"shortOffset"}).split(" ").slice(-1)[0],r=e.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${r} GMT`)-Date.parse(`${r} ${i}`)}function _(t,e){let i=new Date(Date.parse(t));if(isNaN(i))throw new Error("minitz: Invalid ISO8601 passed to parser.");let r=t.substring(9);return t.includes("Z")||r.includes("-")||r.includes("+")?l.tp(i.getUTCFullYear(),i.getUTCMonth()+1,i.getUTCDate(),i.getUTCHours(),i.getUTCMinutes(),i.getUTCSeconds(),"Etc/UTC"):l.tp(i.getFullYear(),i.getMonth()+1,i.getDate(),i.getHours(),i.getMinutes(),i.getSeconds(),e)}l.minitz=l;var v=32,m=31|v,x=[1,2,4,8,16],C=class{pattern;timezone;second;minute;hour;day;month;dayOfWeek;lastDayOfMonth;starDOM;starDOW;constructor(t,e){this.pattern=t,this.timezone=e,this.second=Array(60).fill(0),this.minute=Array(60).fill(0),this.hour=Array(24).fill(0),this.day=Array(31).fill(0),this.month=Array(12).fill(0),this.dayOfWeek=Array(7).fill(0),this.lastDayOfMonth=!1,this.starDOM=!1,this.starDOW=!1,this.parse()}parse(){if(!(typeof this.pattern=="string"||this.pattern instanceof String))throw new TypeError("CronPattern: Pattern has to be of type string.");this.pattern.indexOf("@")>=0&&(this.pattern=this.handleNicknames(this.pattern).trim());let t=this.pattern.replace(/\s+/g," ").split(" ");if(t.length<5||t.length>6)throw new TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five or six space separated parts are required.");if(t.length===5&&t.unshift("0"),t[3].indexOf("L")>=0&&(t[3]=t[3].replace("L",""),this.lastDayOfMonth=!0),t[3]=="*"&&(this.starDOM=!0),t[4].length>=3&&(t[4]=this.replaceAlphaMonths(t[4])),t[5].length>=3&&(t[5]=this.replaceAlphaDays(t[5])),t[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0){let e=new u(new Date,this.timezone).getDate(!0);t[0]=t[0].replace("?",e.getSeconds().toString()),t[1]=t[1].replace("?",e.getMinutes().toString()),t[2]=t[2].replace("?",e.getHours().toString()),this.starDOM||(t[3]=t[3].replace("?",e.getDate().toString())),t[4]=t[4].replace("?",(e.getMonth()+1).toString()),this.starDOW||(t[5]=t[5].replace("?",e.getDay().toString()))}this.throwAtIllegalCharacters(t),this.partToArray("second",t[0],0,1),this.partToArray("minute",t[1],0,1),this.partToArray("hour",t[2],0,1),this.partToArray("day",t[3],-1,1),this.partToArray("month",t[4],-1,1),this.partToArray("dayOfWeek",t[5],0,m),this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])}partToArray(t,e,i,r){let s=this[t],n=t==="day"&&this.lastDayOfMonth;if(e===""&&!n)throw new TypeError("CronPattern: configuration entry "+t+" ("+e+") is empty, check for trailing spaces.");if(e==="*")return s.fill(r);let o=e.split(",");if(o.length>1)for(let a=0;a<o.length;a++)this.partToArray(t,o[a],i,r);else e.indexOf("-")!==-1&&e.indexOf("/")!==-1?this.handleRangeWithStepping(e,t,i,r):e.indexOf("-")!==-1?this.handleRange(e,t,i,r):e.indexOf("/")!==-1?this.handleStepping(e,t,i,r):e!==""&&this.handleNumber(e,t,i,r)}throwAtIllegalCharacters(t){for(let e=0;e<t.length;e++)if((e===5?/[^/*0-9,\-#L]+/:/[^/*0-9,-]+/).test(t[e]))throw new TypeError("CronPattern: configuration entry "+e+" ("+t[e]+") contains illegal characters.")}handleNumber(t,e,i,r){let s=this.extractNth(t,e),n=parseInt(s[0],10)+i;if(isNaN(n))throw new TypeError("CronPattern: "+e+" is not a number: '"+t+"'");this.setPart(e,n,s[1]||r)}setPart(t,e,i){if(!Object.prototype.hasOwnProperty.call(this,t))throw new TypeError("CronPattern: Invalid part specified: "+t);if(t==="dayOfWeek"){if(e===7&&(e=0),e<0||e>6)throw new RangeError("CronPattern: Invalid value for dayOfWeek: "+e);this.setNthWeekdayOfMonth(e,i);return}if(t==="second"||t==="minute"){if(e<0||e>=60)throw new RangeError("CronPattern: Invalid value for "+t+": "+e)}else if(t==="hour"){if(e<0||e>=24)throw new RangeError("CronPattern: Invalid value for "+t+": "+e)}else if(t==="day"){if(e<0||e>=31)throw new RangeError("CronPattern: Invalid value for "+t+": "+e)}else if(t==="month"&&(e<0||e>=12))throw new RangeError("CronPattern: Invalid value for "+t+": "+e);this[t][e]=i}handleRangeWithStepping(t,e,i,r){let s=this.extractNth(t,e),n=s[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(n===null)throw new TypeError("CronPattern: Syntax error, illegal range with stepping: '"+t+"'");let[,o,a,h]=n,p=parseInt(o,10)+i,f=parseInt(a,10)+i,y=parseInt(h,10);if(isNaN(p))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(f))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(isNaN(y))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(y===0)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(y>this[e].length)throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[e].length+")");if(p>f)throw new TypeError("CronPattern: From value is larger than to value: '"+t+"'");for(let w=p;w<=f;w+=y)this.setPart(e,w,s[1]||r)}extractNth(t,e){let i=t,r;if(i.includes("#")){if(e!=="dayOfWeek")throw new Error("CronPattern: nth (#) only allowed in day-of-week field");r=i.split("#")[1],i=i.split("#")[0]}return[i,r]}handleRange(t,e,i,r){let s=this.extractNth(t,e),n=s[0].split("-");if(n.length!==2)throw new TypeError("CronPattern: Syntax error, illegal range: '"+t+"'");let o=parseInt(n[0],10)+i,a=parseInt(n[1],10)+i;if(isNaN(o))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(a))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(o>a)throw new TypeError("CronPattern: From value is larger than to value: '"+t+"'");for(let h=o;h<=a;h++)this.setPart(e,h,s[1]||r)}handleStepping(t,e,i,r){let s=this.extractNth(t,e),n=s[0].split("/");if(n.length!==2)throw new TypeError("CronPattern: Syntax error, illegal stepping: '"+t+"'");n[0]===""&&(n[0]="*");let o=0;n[0]!=="*"&&(o=parseInt(n[0],10)+i);let a=parseInt(n[1],10);if(isNaN(a))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(a===0)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(a>this[e].length)throw new TypeError("CronPattern: Syntax error, max steps for part is ("+this[e].length+")");for(let h=o;h<this[e].length;h+=a)this.setPart(e,h,s[1]||r)}replaceAlphaDays(t){return t.replace(/-sun/gi,"-7").replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")}replaceAlphaMonths(t){return t.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")}handleNicknames(t){let e=t.trim().toLowerCase();return e==="@yearly"||e==="@annually"?"0 0 1 1 *":e==="@monthly"?"0 0 1 * *":e==="@weekly"?"0 0 * * 0":e==="@daily"?"0 0 * * *":e==="@hourly"?"0 * * * *":t}setNthWeekdayOfMonth(t,e){if(typeof e!="number"&&e==="L")this.dayOfWeek[t]=this.dayOfWeek[t]|v;else if(e===m)this.dayOfWeek[t]=m;else if(e<6&&e>0)this.dayOfWeek[t]=this.dayOfWeek[t]|x[e-1];else throw new TypeError(`CronPattern: nth weekday out of range, should be 1-5 or L. Value: ${e}, Type: ${typeof e}`)}},D=[31,28,31,30,31,30,31,31,30,31,30,31],c=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]],u=class t{tz;ms;second;minute;hour;day;month;year;constructor(e,i){if(this.tz=i,e&&e instanceof Date)if(!isNaN(e))this.fromDate(e);else throw new TypeError("CronDate: Invalid date passed to CronDate constructor");else if(e===void 0)this.fromDate(new Date);else if(e&&typeof e=="string")this.fromString(e);else if(e instanceof t)this.fromCronDate(e);else throw new TypeError("CronDate: Invalid type ("+typeof e+") passed to CronDate constructor")}isNthWeekdayOfMonth(e,i,r,s){let n=new Date(Date.UTC(e,i,r)).getUTCDay(),o=0;for(let a=1;a<=r;a++)new Date(Date.UTC(e,i,a)).getUTCDay()===n&&o++;if(s&m&&x[o-1]&s)return!0;if(s&v){let a=new Date(Date.UTC(e,i+1,0)).getUTCDate();for(let h=r+1;h<=a;h++)if(new Date(Date.UTC(e,i,h)).getUTCDay()===n)return!1;return!0}return!1}fromDate(e){if(this.tz!==void 0)if(typeof this.tz=="number")this.ms=e.getUTCMilliseconds(),this.second=e.getUTCSeconds(),this.minute=e.getUTCMinutes()+this.tz,this.hour=e.getUTCHours(),this.day=e.getUTCDate(),this.month=e.getUTCMonth(),this.year=e.getUTCFullYear(),this.apply();else{let i=l.toTZ(e,this.tz);this.ms=e.getMilliseconds(),this.second=i.s,this.minute=i.i,this.hour=i.h,this.day=i.d,this.month=i.m-1,this.year=i.y}else this.ms=e.getMilliseconds(),this.second=e.getSeconds(),this.minute=e.getMinutes(),this.hour=e.getHours(),this.day=e.getDate(),this.month=e.getMonth(),this.year=e.getFullYear()}fromCronDate(e){this.tz=e.tz,this.year=e.year,this.month=e.month,this.day=e.day,this.hour=e.hour,this.minute=e.minute,this.second=e.second,this.ms=e.ms}apply(){if(this.month>11||this.day>D[this.month]||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){let e=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));return this.ms=e.getUTCMilliseconds(),this.second=e.getUTCSeconds(),this.minute=e.getUTCMinutes(),this.hour=e.getUTCHours(),this.day=e.getUTCDate(),this.month=e.getUTCMonth(),this.year=e.getUTCFullYear(),!0}else return!1}fromString(e){if(typeof this.tz=="number"){let i=l.fromTZISO(e);this.ms=i.getUTCMilliseconds(),this.second=i.getUTCSeconds(),this.minute=i.getUTCMinutes(),this.hour=i.getUTCHours(),this.day=i.getUTCDate(),this.month=i.getUTCMonth(),this.year=i.getUTCFullYear(),this.apply()}else return this.fromDate(l.fromTZISO(e,this.tz))}findNext(e,i,r,s){let n=this[i],o;r.lastDayOfMonth&&(this.month!==1?o=D[this.month]:o=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate());let a=!r.starDOW&&i=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0;for(let h=this[i]+s;h<r[i].length;h++){let p=r[i][h];if(i==="day"&&r.lastDayOfMonth&&h-s==o&&(p=1),i==="day"&&!r.starDOW){let f=r.dayOfWeek[(a+(h-s-1))%7];if(f&&f&m)f=this.isNthWeekdayOfMonth(this.year,this.month,h-s,f)?1:0;else if(f)throw new Error(`CronDate: Invalid value for dayOfWeek encountered. ${f}`);e.legacyMode&&!r.starDOM?p=p||f:p=p&&f}if(p)return this[i]=h-s,n!==this[i]?2:1}return 3}recurse(e,i,r){let s=this.findNext(i,c[r][0],e,c[r][2]);if(s>1){let n=r+1;for(;n<c.length;)this[c[n][0]]=-c[n][2],n++;if(s===3)return this[c[r][1]]++,this[c[r][0]]=-c[r][2],this.apply(),this.recurse(e,i,0);if(this.apply())return this.recurse(e,i,r-1)}return r+=1,r>=c.length?this:this.year>=3000?null:this.recurse(e,i,r)}increment(e,i,r){return this.second+=i.interval!==void 0&&i.interval>1&&r?i.interval:1,this.ms=0,this.apply(),this.recurse(e,i,0)}getDate(e){return e||this.tz===void 0?new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms):typeof this.tz=="number"?new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms)):l.fromTZ(l.tp(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz),!1)}getTime(){return this.getDate(!1).getTime()}};function N(t){if(t===void 0&&(t={}),delete t.name,t.legacyMode=t.legacyMode===void 0?!0:t.legacyMode,t.paused=t.paused===void 0?!1:t.paused,t.maxRuns=t.maxRuns===void 0?1/0:t.maxRuns,t.catch=t.catch===void 0?!1:t.catch,t.interval=t.interval===void 0?0:parseInt(t.interval.toString(),10),t.utcOffset=t.utcOffset===void 0?void 0:parseInt(t.utcOffset.toString(),10),t.unref=t.unref===void 0?!1:t.unref,t.startAt&&(t.startAt=new u(t.startAt,t.timezone)),t.stopAt&&(t.stopAt=new u(t.stopAt,t.timezone)),t.interval!==null){if(isNaN(t.interval))throw new Error("CronOptions: Supplied value for interval is not a number");if(t.interval<0)throw new Error("CronOptions: Supplied value for interval can not be negative")}if(t.utcOffset!==void 0){if(isNaN(t.utcOffset))throw new Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");if(t.utcOffset<-870||t.utcOffset>870)throw new Error("CronOptions: utcOffset out of bounds.");if(t.utcOffset!==void 0&&t.timezone)throw new Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}if(t.unref!==!0&&t.unref!==!1)throw new Error("CronOptions: Unref should be either true, false or undefined(false).");return t}function g(t){return Object.prototype.toString.call(t)==="[object Function]"||typeof t=="function"||t instanceof Function}function S(t){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(t):t&&typeof t.unref<"u"&&t.unref()}var O=30000,d=[],M=class{name;options;_states;fn;constructor(t,e,i){let r,s;if(g(e))s=e;else if(typeof e=="object")r=e;else if(e!==void 0)throw new Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(g(i))s=i;else if(typeof i=="object")r=i;else if(i!==void 0)throw new Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=r?.name,this.options=N(r),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:r?r.maxRuns:void 0,paused:r?r.paused:!1,pattern:new C("* * * * *")},t&&(t instanceof Date||typeof t=="string"&&t.indexOf(":")>0)?this._states.once=new u(t,this.options.timezone||this.options.utcOffset):this._states.pattern=new C(t,this.options.timezone),this.name){if(d.find((n)=>n.name===this.name))throw new Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");d.push(this)}return s!==void 0&&g(s)&&(this.fn=s,this.schedule()),this}nextRun(t){let e=this._next(t);return e?e.getDate(!1):null}nextRuns(t,e){this._states.maxRuns!==void 0&&t>this._states.maxRuns&&(t=this._states.maxRuns);let i=[],r=e||this._states.currentRun||void 0;for(;t--&&(r=this.nextRun(r));)i.push(r);return i}getPattern(){return this._states.pattern?this._states.pattern.pattern:void 0}isRunning(){let t=this.nextRun(this._states.currentRun),e=!this._states.paused,i=this.fn!==void 0,r=!this._states.kill;return e&&i&&r&&t!==null}isStopped(){return this._states.kill}isBusy(){return this._states.blocking}currentRun(){return this._states.currentRun?this._states.currentRun.getDate():null}previousRun(){return this._states.previousRun?this._states.previousRun.getDate():null}msToNext(t){t=t||new Date;let e=this._next(t);return e?t instanceof u||t instanceof Date?e.getTime()-t.getTime():e.getTime()-new u(t).getTime():null}stop(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let t=d.indexOf(this);t>=0&&d.splice(t,1)}pause(){return this._states.paused=!0,!this._states.kill}resume(){return this._states.paused=!1,!this._states.kill}schedule(t){if(t&&this.fn)throw new Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");t&&(this.fn=t);let e=this.msToNext(),i=this.nextRun(this._states.currentRun);return e==null||isNaN(e)||i===null?this:(e>O&&(e=O),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(i),e),this._states.currentTimeout&&this.options.unref&&S(this._states.currentTimeout),this)}async _trigger(t){if(this._states.blocking=!0,this._states.currentRun=new u(void 0,this.options.timezone||this.options.utcOffset),this.options.catch)try{this.fn!==void 0&&await this.fn(this,this.options.context)}catch(e){g(this.options.catch)&&this.options.catch(e,this)}else this.fn!==void 0&&await this.fn(this,this.options.context);this._states.previousRun=new u(t,this.options.timezone||this.options.utcOffset),this._states.blocking=!1}async trigger(){await this._trigger()}runsLeft(){return this._states.maxRuns}_checkTrigger(t){let e=new Date,i=!this._states.paused&&e.getTime()>=t.getTime(),r=this._states.blocking&&this.options.protect;i&&!r?(this._states.maxRuns!==void 0&&this._states.maxRuns--,this._trigger()):i&&r&&g(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()}_next(t){let e=!!(t||this._states.currentRun),i=!1;!t&&this.options.startAt&&this.options.interval&&([t,e]=this._calculatePreviousRun(t,e),i=!t),t=new u(t,this.options.timezone||this.options.utcOffset),this.options.startAt&&t&&t.getTime()<this.options.startAt.getTime()&&(t=this.options.startAt);let r=this._states.once||new u(t,this.options.timezone||this.options.utcOffset);return!i&&r!==this._states.once&&(r=r.increment(this._states.pattern,this.options,e)),this._states.once&&this._states.once.getTime()<=t.getTime()||r===null||this._states.maxRuns!==void 0&&this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&r.getTime()>=this.options.stopAt.getTime()?null:r}_calculatePreviousRun(t,e){let i=new u(void 0,this.options.timezone||this.options.utcOffset),r=t;if(this.options.startAt.getTime()<=i.getTime()){r=this.options.startAt;let s=r.getTime()+this.options.interval*1000;for(;s<=i.getTime();)r=new u(r,this.options.timezone||this.options.utcOffset).increment(this._states.pattern,this.options,!0),s=r.getTime()+this.options.interval*1000;e=!0}return r===null&&(r=void 0),[r,e]}};export{d as scheduledJobs,C as CronPattern,u as CronDate,M as Cron};
|
|
2
|
+
var A={"@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 * * * *"},S={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},w={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};function N(P,C){return P.replace(/[a-z]+/gi,(q)=>{let J=C[q.toLowerCase()];if(J===void 0)throw Error(`Invalid cron value: ${q}`);return String(J)})}function Z(P,C,q,J){let R=J?N(P,J):P,L=new Set;for(let $ of R.split(",")){let Q=$.match(/^(.+)\/(\d+)$/),B,G=1;if(Q){if(B=Q[1]??"",G=Number.parseInt(Q[2]??"",10),G<=0)throw Error(`Invalid step: ${G}`)}else B=$;if(B==="*")for(let z=C;z<=q;z+=G)L.add(z);else if(B.includes("-")){let[z,H]=B.split("-"),U=Number.parseInt(z??"",10),V=Number.parseInt(H??"",10);if(Number.isNaN(U)||Number.isNaN(V))throw Error(`Invalid range: ${B}`);if(U<C||V>q)throw Error(`Range out of bounds: ${B} (${C}-${q})`);for(let I=U;I<=V;I+=G)L.add(I)}else{let z=Number.parseInt(B,10);if(Number.isNaN(z))throw Error(`Invalid cron value: ${B}`);if(z<C||z>q)throw Error(`Value out of range: ${z} (${C}-${q})`);L.add(z)}}return L}function Y(P,C){let q=P.trim(),R=(A[q.toLowerCase()]??q).split(/\s+/).filter(Boolean);if(R.length!==5)throw Error(`Invalid cron expression: expected 5 fields, got ${R.length}`);let[L,$,Q,B,G]=R,z=Z(L,0,59),H=Z($,0,23),U=Z(Q,1,31),V=Z(B,1,12,S),I=Z(G,0,7,w);if(I.has(7))I.add(0),I.delete(7);let _=Q==="*",j=G==="*",K=C instanceof Date?C.getTime():typeof C==="number"?C:Date.now();if(Number.isNaN(K)||!Number.isFinite(K))throw Error("Invalid date");let b=new Date(K);b.setUTCSeconds(0,0),b.setUTCMinutes(b.getUTCMinutes()+1);let T=b.getTime()+126230400000;while(b.getTime()<T){if(!V.has(b.getUTCMonth()+1)){b.setUTCMonth(b.getUTCMonth()+1,1),b.setUTCHours(0,0,0,0);continue}let k=U.has(b.getUTCDate()),E=I.has(b.getUTCDay()),X;if(_&&j)X=!0;else if(_)X=E;else if(j)X=k;else X=k||E;if(!X){b.setUTCDate(b.getUTCDate()+1),b.setUTCHours(0,0,0,0);continue}if(!H.has(b.getUTCHours())){b.setUTCHours(b.getUTCHours()+1,0,0,0);continue}if(!z.has(b.getUTCMinutes())){b.setUTCMinutes(b.getUTCMinutes()+1,0,0);continue}return new Date(b.getTime())}return null}function W(P,C){if(typeof Bun<"u"&&Bun.cron?.parse)return Bun.cron.parse(P,C);return Y(P,C)}async function g(P,C,q){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(P,C,q)}async function y(P){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(P)}export{y as remove,g as register,Y as parseCron,W as parse};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/// <reference path="./bun-cron.d.ts" />
|
|
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.
|
|
6
|
+
//
|
|
7
|
+
// Examples:
|
|
8
|
+
// parse('0 0 * * *') → next midnight UTC
|
|
9
|
+
// parse('@hourly') → next hour
|
|
10
|
+
// parse('0,15,30,45 * * * *') → next 15-min mark
|
|
11
|
+
export declare function parse(expression: string, relativeDate?: Date | number): Date | null;
|
|
12
|
+
/**
|
|
13
|
+
* Register an OS-level cron job that persists across process restarts.
|
|
14
|
+
*
|
|
15
|
+
* Requires Bun's native cron support (crontab on Linux, launchd on macOS,
|
|
16
|
+
* schtasks on Windows).
|
|
17
|
+
*
|
|
18
|
+
* The target script must export a `scheduled(controller)` handler:
|
|
19
|
+
* ```ts
|
|
20
|
+
* export default {
|
|
21
|
+
* async scheduled(controller) {
|
|
22
|
+
* // controller.cron, controller.scheduledTime
|
|
23
|
+
* await doWork()
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @param path - Path to the script to run
|
|
29
|
+
* @param schedule - Cron expression or nickname (@daily, @hourly, etc.)
|
|
30
|
+
* @param title - Unique job identifier (alphanumeric, hyphens, underscores)
|
|
31
|
+
*/
|
|
32
|
+
export declare function register(path: string, schedule: string, title: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Remove a previously registered OS-level cron job.
|
|
35
|
+
*
|
|
36
|
+
* @param title - The title of the cron job to remove
|
|
37
|
+
*/
|
|
38
|
+
export declare function remove(title: string): Promise<void>;
|
|
39
|
+
/// <reference path="./bun-cron.d.ts" />
|
|
40
|
+
export * from './types';
|
|
41
|
+
export { parseCron } from './parser';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a cron expression and return the next matching UTC Date.
|
|
3
|
+
*
|
|
4
|
+
* @param expression - A 5-field cron expression or nickname (@daily, etc.)
|
|
5
|
+
* @param relativeDate - Starting point for the search (defaults to Date.now())
|
|
6
|
+
* @returns The next Date matching the expression (UTC), or null if no match within ~4 years
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseCron(expression: string, relativeDate?: Date | number): Date | null;
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/cron",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.70.
|
|
4
|
+
"version": "0.70.25",
|
|
5
5
|
"description": "The Stacks cron.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
|
-
"contributors": [
|
|
7
|
+
"contributors": [
|
|
8
|
+
"Chris Breuer <chris@stacksjs.com>"
|
|
9
|
+
],
|
|
8
10
|
"license": "MIT",
|
|
9
11
|
"funding": "https://github.com/sponsors/chrisbbreuer",
|
|
10
12
|
"homepage": "https://github.com/stacksjs/stacks/tree/main/storage/framework/core/cron#readme",
|
|
@@ -16,25 +18,36 @@
|
|
|
16
18
|
"bugs": {
|
|
17
19
|
"url": "https://github.com/stacksjs/stacks/issues"
|
|
18
20
|
},
|
|
19
|
-
"keywords": [
|
|
21
|
+
"keywords": [
|
|
22
|
+
"cron",
|
|
23
|
+
"bun-cron",
|
|
24
|
+
"jobs",
|
|
25
|
+
"bun",
|
|
26
|
+
"stacks"
|
|
27
|
+
],
|
|
20
28
|
"exports": {
|
|
21
29
|
".": {
|
|
30
|
+
"bun": "./src/index.ts",
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
22
32
|
"import": "./dist/index.js"
|
|
23
33
|
},
|
|
24
34
|
"./*": {
|
|
35
|
+
"bun": "./src/*",
|
|
25
36
|
"import": "./dist/*"
|
|
26
37
|
}
|
|
27
38
|
},
|
|
28
39
|
"module": "dist/index.js",
|
|
29
40
|
"types": "dist/index.d.ts",
|
|
30
|
-
"files": [
|
|
41
|
+
"files": [
|
|
42
|
+
"README.md",
|
|
43
|
+
"dist"
|
|
44
|
+
],
|
|
31
45
|
"scripts": {
|
|
32
46
|
"build": "bun build.ts",
|
|
33
47
|
"typecheck": "bun tsc --noEmit",
|
|
34
48
|
"prepublishOnly": "bun run build"
|
|
35
49
|
},
|
|
36
50
|
"devDependencies": {
|
|
37
|
-
"
|
|
38
|
-
"croner": "^9.0.0"
|
|
51
|
+
"better-dx": "^0.2.12"
|
|
39
52
|
}
|
|
40
53
|
}
|
package/dist/index.d.ts
DELETED
package/dist/types.d.ts
DELETED