croner 5.7.0 → 6.0.0-dev.0

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.
@@ -0,0 +1 @@
1
+ (function(global,factory){typeof exports==="object"&&typeof module!=="undefined"?module.exports=factory():typeof define==="function"&&define.amd?define(factory):(global=typeof globalThis!=="undefined"?globalThis:global||self,global.Cron=factory())})(this,function(){"use strict";function minitz(y,m,d,h,i,s,tz,throwOnInvalid){return minitz.fromTZ(minitz.tp(y,m,d,h,i,s,tz),throwOnInvalid)}minitz.fromTZISO=(localTimeStr,tz,throwOnInvalid)=>{return minitz.fromTZ(parseISOLocal(localTimeStr,tz),throwOnInvalid)};minitz.fromTZ=function(tp,throwOnInvalid){const inDate=new Date(Date.UTC(tp.y,tp.m-1,tp.d,tp.h,tp.i,tp.s)),offset=getTimezoneOffset(tp.tz,inDate),dateGuess=new Date(inDate.getTime()-offset),dateOffsGuess=getTimezoneOffset(tp.tz,dateGuess);if(dateOffsGuess-offset===0){return dateGuess}else{const dateGuess2=new Date(inDate.getTime()-dateOffsGuess),dateOffsGuess2=getTimezoneOffset(tp.tz,dateGuess2);if(dateOffsGuess2-dateOffsGuess===0){return dateGuess2}else if(!throwOnInvalid&&dateOffsGuess2-dateOffsGuess>0){return dateGuess2}else if(!throwOnInvalid){return dateGuess}else{throw new Error("Invalid date passed to fromTZ()")}}};minitz.toTZ=function(d,tzStr){const td=new Date(d.toLocaleString("sv-SE",{timeZone:tzStr}));return{y:td.getFullYear(),m:td.getMonth()+1,d:td.getDate(),h:td.getHours(),i:td.getMinutes(),s:td.getSeconds(),tz:tzStr}};minitz.tp=(y,m,d,h,i,s,tz)=>{return{y:y,m:m,d:d,h:h,i:i,s:s,tz:tz}};function getTimezoneOffset(timeZone,date=new Date){const tz=date.toLocaleString("en",{timeZone:timeZone,timeStyle:"long"}).split(" ").slice(-1)[0];const dateString=date.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${dateString} GMT`)-Date.parse(`${dateString} ${tz}`)}function parseISOLocal(dtStr,tz){const pd=new Date(Date.parse(dtStr));if(isNaN(pd)){throw new Error("minitz: Invalid ISO8601 passed to parser.")}const stringEnd=dtStr.substring(9);if(dtStr.includes("Z")||stringEnd.includes("-")||stringEnd.includes("+")){return minitz.tp(pd.getUTCFullYear(),pd.getUTCMonth()+1,pd.getUTCDate(),pd.getUTCHours(),pd.getUTCMinutes(),pd.getUTCSeconds(),"Etc/UTC")}else{return minitz.tp(pd.getFullYear(),pd.getMonth()+1,pd.getDate(),pd.getHours(),pd.getMinutes(),pd.getSeconds(),tz)}}minitz.minitz=minitz;function CronOptions(options){if(options===void 0){options={}}delete options.name;options.legacyMode=options.legacyMode===void 0?true:options.legacyMode;options.paused=options.paused===void 0?false:options.paused;options.maxRuns=options.maxRuns===void 0?Infinity:options.maxRuns;options.catch=options.catch===void 0?false:options.catch;options.interval=options.interval===void 0?0:parseInt(options.interval,10);options.utcOffset=options.utcOffset===void 0?void 0:parseInt(options.utcOffset,10);options.unref=options.unref===void 0?false:options.unref;if(options.startAt){options.startAt=new CronDate(options.startAt,options.timezone)}if(options.stopAt){options.stopAt=new CronDate(options.stopAt,options.timezone)}if(options.interval!==null){if(isNaN(options.interval)){throw new Error("CronOptions: Supplied value for interval is not a number")}else if(options.interval<0){throw new Error("CronOptions: Supplied value for interval can not be negative")}}if(options.utcOffset!==void 0){if(isNaN(options.utcOffset)){throw new Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.")}else if(options.utcOffset<-870||options.utcOffset>870){throw new Error("CronOptions: utcOffset out of bounds.")}if(options.utcOffset!==void 0&&options.timezone){throw new Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}}if(options.unref!==true&&options.unref!==false){throw new Error("CronOptions: Unref should be either true, false or undefined(false).")}return options}const DaysOfMonth=[31,28,31,30,31,30,31,31,30,31,30,31];const RecursionSteps=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]];function CronDate(d,tz){this.tz=tz;if(d&&d instanceof Date){if(!isNaN(d)){this.fromDate(d)}else{throw new TypeError("CronDate: Invalid date passed to CronDate constructor")}}else if(d===void 0){this.fromDate(new Date)}else if(d&&typeof d==="string"){this.fromString(d)}else if(d instanceof CronDate){this.fromCronDate(d)}else{throw new TypeError("CronDate: Invalid type ("+typeof d+") passed to CronDate constructor")}}CronDate.prototype.fromDate=function(inDate){if(this.tz!==void 0){if(typeof this.tz==="number"){this.ms=inDate.getUTCMilliseconds();this.second=inDate.getUTCSeconds();this.minute=inDate.getUTCMinutes()+this.tz;this.hour=inDate.getUTCHours();this.day=inDate.getUTCDate();this.month=inDate.getUTCMonth();this.year=inDate.getUTCFullYear();this.apply()}else{const d=minitz.toTZ(inDate,this.tz);this.ms=inDate.getMilliseconds();this.second=d.s;this.minute=d.i;this.hour=d.h;this.day=d.d;this.month=d.m-1;this.year=d.y}}else{this.ms=inDate.getMilliseconds();this.second=inDate.getSeconds();this.minute=inDate.getMinutes();this.hour=inDate.getHours();this.day=inDate.getDate();this.month=inDate.getMonth();this.year=inDate.getFullYear()}};CronDate.prototype.fromCronDate=function(d){this.tz=d.tz;this.year=d.year;this.month=d.month;this.day=d.day;this.hour=d.hour;this.minute=d.minute;this.second=d.second;this.ms=d.ms};CronDate.prototype.apply=function(){if(this.month>11||this.day>DaysOfMonth[this.month]||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){const d=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));this.ms=d.getUTCMilliseconds();this.second=d.getUTCSeconds();this.minute=d.getUTCMinutes();this.hour=d.getUTCHours();this.day=d.getUTCDate();this.month=d.getUTCMonth();this.year=d.getUTCFullYear();return true}else{return false}};CronDate.prototype.fromString=function(str){return this.fromDate(minitz.fromTZISO(str,this.tz))};CronDate.prototype.findNext=function(options,target,pattern,offset){const originalTarget=this[target];let lastDayOfMonth;if(pattern.lastDayOfMonth||pattern.lastWeekdayOfMonth){if(this.month!==1){lastDayOfMonth=DaysOfMonth[this.month]}else{lastDayOfMonth=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate()}}const fDomWeekDay=!pattern.starDOW&&target=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():undefined;for(let i=this[target]+offset;i<pattern[target].length;i++){let match=pattern[target][i];if(target==="day"&&pattern.lastDayOfMonth&&i-offset==lastDayOfMonth){match=true}if(target==="day"&&!pattern.starDOW){let dowMatch=pattern.dayOfWeek[(fDomWeekDay+(i-offset-1))%7];if(dowMatch&&pattern.lastWeekdayOfMonth){dowMatch=dowMatch&&i-offset>lastDayOfMonth-7}if(options.legacyMode&&!pattern.starDOM){match=match||dowMatch}else{match=match&&dowMatch}}if(match){this[target]=i-offset;return originalTarget!==this[target]?2:1}}return 3};CronDate.prototype.recurse=function(pattern,options,doing){const res=this.findNext(options,RecursionSteps[doing][0],pattern,RecursionSteps[doing][2]);if(res>1){let resetLevel=doing+1;while(resetLevel<RecursionSteps.length){this[RecursionSteps[resetLevel][0]]=-RecursionSteps[resetLevel][2];resetLevel++}if(res===3){this[RecursionSteps[doing][1]]++;this[RecursionSteps[doing][0]]=-RecursionSteps[doing][2];this.apply();return this.recurse(pattern,options,0)}else if(this.apply()){return this.recurse(pattern,options,doing-1)}}doing+=1;if(doing>=RecursionSteps.length){return this}else if(this.year>=3e3){return null}else{return this.recurse(pattern,options,doing)}};CronDate.prototype.increment=function(pattern,options,hasPreviousRun){this.second+=options.interval>1&&hasPreviousRun?options.interval:1;this.ms=0;this.apply();return this.recurse(pattern,options,0)};CronDate.prototype.getDate=function(internal){if(internal||this.tz===void 0){return new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms)}else{if(typeof this.tz==="number"){return new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms))}else{return minitz(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz)}}};CronDate.prototype.getTime=function(){return this.getDate().getTime()};function CronPattern(pattern,timezone){this.pattern=pattern;this.timezone=timezone;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(8).fill(0);this.lastDayOfMonth=false;this.lastWeekdayOfMonth=false;this.starDOM=false;this.starDOW=false;this.parse()}CronPattern.prototype.parse=function(){if(!(typeof this.pattern==="string"||this.pattern.constructor===String)){throw new TypeError("CronPattern: Pattern has to be of type string.")}if(this.pattern.indexOf("@")>=0)this.pattern=this.handleNicknames(this.pattern).trim();const parts=this.pattern.replace(/\s+/g," ").split(" ");if(parts.length<5||parts.length>6){throw new TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exacly five or six space separated parts required.")}if(parts.length===5){parts.unshift("0")}if(parts[3].indexOf("L")>=0){parts[3]=parts[3].replace("L","");this.lastDayOfMonth=true}if(parts[5].indexOf("L")>=0){parts[5]=parts[5].replace("L","");this.lastWeekdayOfMonth=true}if(parts[3]=="*"){this.starDOM=true}if(parts[4].length>=3)parts[4]=this.replaceAlphaMonths(parts[4]);if(parts[5].length>=3)parts[5]=this.replaceAlphaDays(parts[5]);if(parts[5]=="*"){this.starDOW=true}if(this.pattern.indexOf("?")>=0){const initDate=new CronDate(new Date,this.timezone).getDate(true);parts[0]=parts[0].replace("?",initDate.getSeconds());parts[1]=parts[1].replace("?",initDate.getMinutes());parts[2]=parts[2].replace("?",initDate.getHours());if(!this.starDOM)parts[3]=parts[3].replace("?",initDate.getDate());parts[4]=parts[4].replace("?",initDate.getMonth()+1);if(!this.starDOW)parts[5]=parts[5].replace("?",initDate.getDay())}this.throwAtIllegalCharacters(parts);this.partToArray("second",parts[0],0);this.partToArray("minute",parts[1],0);this.partToArray("hour",parts[2],0);this.partToArray("day",parts[3],-1);this.partToArray("month",parts[4],-1);this.partToArray("dayOfWeek",parts[5],0);if(this.dayOfWeek[7]){this.dayOfWeek[0]=1}};CronPattern.prototype.partToArray=function(type,conf,valueIndexOffset){const arr=this[type];if(conf==="*")return arr.fill(1);const split=conf.split(",");if(split.length>1){for(let i=0;i<split.length;i++){this.partToArray(type,split[i],valueIndexOffset)}}else if(conf.indexOf("-")!==-1&&conf.indexOf("/")!==-1){this.handleRangeWithStepping(conf,type,valueIndexOffset)}else if(conf.indexOf("-")!==-1){this.handleRange(conf,type,valueIndexOffset)}else if(conf.indexOf("/")!==-1){this.handleStepping(conf,type,valueIndexOffset)}else if(conf!==""){this.handleNumber(conf,type,valueIndexOffset)}};CronPattern.prototype.throwAtIllegalCharacters=function(parts){const reValidCron=/[^/*0-9,-]+/;for(let i=0;i<parts.length;i++){if(reValidCron.test(parts[i])){throw new TypeError("CronPattern: configuration entry "+i+" ("+parts[i]+") contains illegal characters.")}}};CronPattern.prototype.handleNumber=function(conf,type,valueIndexOffset){const i=parseInt(conf,10)+valueIndexOffset;if(isNaN(i)){throw new TypeError("CronPattern: "+type+" is not a number: '"+conf+"'")}if(i<0||i>=this[type].length){throw new TypeError("CronPattern: "+type+" value out of range: '"+conf+"'")}this[type][i]=1};CronPattern.prototype.handleRangeWithStepping=function(conf,type,valueIndexOffset){const matches=conf.match(/^(\d+)-(\d+)\/(\d+)$/);if(matches===null)throw new TypeError("CronPattern: Syntax error, illegal range with stepping: '"+conf+"'");let[,lower,upper,steps]=matches;lower=parseInt(lower,10)+valueIndexOffset;upper=parseInt(upper,10)+valueIndexOffset;steps=parseInt(steps,10);if(isNaN(lower))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(upper))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(isNaN(steps))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(steps===0)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(steps>this[type].length)throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[type].length+")");if(lower<0||upper>=this[type].length)throw new TypeError("CronPattern: Value out of range: '"+conf+"'");if(lower>upper)throw new TypeError("CronPattern: From value is larger than to value: '"+conf+"'");for(let i=lower;i<=upper;i+=steps){this[type][i]=1}};CronPattern.prototype.handleRange=function(conf,type,valueIndexOffset){const split=conf.split("-");if(split.length!==2){throw new TypeError("CronPattern: Syntax error, illegal range: '"+conf+"'")}const lower=parseInt(split[0],10)+valueIndexOffset,upper=parseInt(split[1],10)+valueIndexOffset;if(isNaN(lower)){throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)")}else if(isNaN(upper)){throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)")}if(lower<0||upper>=this[type].length){throw new TypeError("CronPattern: Value out of range: '"+conf+"'")}if(lower>upper){throw new TypeError("CronPattern: From value is larger than to value: '"+conf+"'")}for(let i=lower;i<=upper;i++){this[type][i]=1}};CronPattern.prototype.handleStepping=function(conf,type){const split=conf.split("/");if(split.length!==2){throw new TypeError("CronPattern: Syntax error, illegal stepping: '"+conf+"'")}let start=0;if(split[0]!=="*"){start=parseInt(split[0],10)}const steps=parseInt(split[1],10);if(isNaN(steps))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(steps===0)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(steps>this[type].length)throw new TypeError("CronPattern: Syntax error, max steps for part is ("+this[type].length+")");for(let i=start;i<this[type].length;i+=steps){this[type][i]=1}};CronPattern.prototype.replaceAlphaDays=function(conf){return conf.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")};CronPattern.prototype.replaceAlphaMonths=function(conf){return conf.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")};CronPattern.prototype.handleNicknames=function(pattern){const cleanPattern=pattern.trim().toLowerCase();if(cleanPattern==="@yearly"||cleanPattern==="@annually"){return"0 0 1 1 *"}else if(cleanPattern==="@monthly"){return"0 0 1 * *"}else if(cleanPattern==="@weekly"){return"0 0 * * 0"}else if(cleanPattern==="@daily"){return"0 0 * * *"}else if(cleanPattern==="@hourly"){return"0 * * * *"}else{return pattern}};function isFunction(v){return Object.prototype.toString.call(v)==="[object Function]"||"function"===typeof v||v instanceof Function}function unrefTimer(timer){if(typeof Deno!=="undefined"&&typeof Deno.unrefTimer!=="undefined"){Deno.unrefTimer(timer)}else if(timer&&typeof timer.unref!=="undefined"){timer.unref()}}const maxDelay=Math.pow(2,32-1)-1;const scheduledJobs=[];function Cron(pattern,fnOrOptions1,fnOrOptions2){if(!(this instanceof Cron)){return new Cron(pattern,fnOrOptions1,fnOrOptions2)}let options,func;if(isFunction(fnOrOptions1)){func=fnOrOptions1}else if(typeof fnOrOptions1==="object"){options=fnOrOptions1}else if(fnOrOptions1!==void 0){throw new Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).")}if(isFunction(fnOrOptions2)){func=fnOrOptions2}else if(typeof fnOrOptions2==="object"){options=fnOrOptions2}else if(fnOrOptions2!==void 0){throw new Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).")}this.name=options?options.name:void 0;this.options=CronOptions(options);this._states={kill:false,blocking:false,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:options?options.maxRuns:void 0,paused:options?options.paused:false};this.pattern=void 0;if(pattern&&(pattern instanceof Date||typeof pattern==="string"&&pattern.indexOf(":")>0)){this._states.once=new CronDate(pattern,this.options.timezone||this.options.utcOffset)}else{this.pattern=new CronPattern(pattern,this.options.timezone)}if(func!==void 0){this.fn=func;this.schedule()}if(this.name){const existing=scheduledJobs.find(j=>j.name===this.name);if(existing){throw new Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.")}else{scheduledJobs.push(this)}}return this}Cron.prototype.next=function(prev){const next=this._next(prev);return next?next.getDate():null};Cron.prototype.enumerate=function(n,previous){if(n>this._states.maxRuns){n=this._states.maxRuns}const enumeration=[];let prev=previous||this._states.previousRun;while(n--&&(prev=this.next(prev))){enumeration.push(prev)}return enumeration};Cron.prototype.running=function(){const msLeft=this.msToNext(this._states.previousRun);const running=!this._states.paused&&this.fn!==void 0;return msLeft!==null&&running};Cron.prototype.busy=function(){return this._states.blocking};Cron.prototype.started=function(){return this._states.currentRun?this._states.currentRun.getDate():null};Cron.prototype.previous=function(){return this._states.previousRun?this._states.previousRun.getDate():null};Cron.prototype.msToNext=function(prev){const next=this._next(prev);prev=new CronDate(prev,this.options.timezone||this.options.utcOffset);if(next){return next.getTime(true)-prev.getTime(true)}else{return null}};Cron.prototype.stop=function(){this._states.kill=true;if(this._states.currentTimeout){clearTimeout(this._states.currentTimeout)}};Cron.prototype.pause=function(){this._states.paused=true;return!this._states.kill};Cron.prototype.resume=function(){this._states.paused=false;return!this._states.kill};Cron.prototype.schedule=function(func,partial){if(func&&this.fn){throw new Error("Cron: It is not allowed to schedule two functions using the same Croner instance.")}else if(func){this.fn=func}let waitMs=this.msToNext(partial?partial:this._states.previousRun);const target=this.next(partial?partial:this._states.previousRun);if(waitMs===null||target===null)return this;if(waitMs>maxDelay){waitMs=maxDelay}this._states.currentTimeout=setTimeout(()=>this._checkTrigger(target),waitMs);if(this._states.currentTimeout&&this.options.unref){unrefTimer(this._states.currentTimeout)}return this};Cron.prototype._trigger=async function(initiationDate){this._states.blocking=true;this._states.currentRun=new CronDate(initiationDate,this.options.timezone||this.options.utcOffset);if(this.options.catch){try{await this.fn(this,this.options.context)}catch(_e){if(isFunction(this.options.catch)){setTimeout(()=>this.options.catch(_e,this),0)}}}else{await this.fn(this,this.options.context)}this._states.previousRun=new CronDate(initiationDate,this.options.timezone||this.options.utcOffset);this._states.blocking=false};Cron.prototype.trigger=async function(){await this._trigger()};Cron.prototype._checkTrigger=function(target){const now=new Date,shouldRun=!this._states.paused&&now.getTime()>=target,isBlocked=this.blocking&&this.options.protect;if(shouldRun&&!isBlocked){this._states.maxRuns--;this._trigger()}else{if(shouldRun&&isBlocked&&isFunction(this.options.protect)){setTimeout(()=>this.options.protect(this),0)}}this.schedule(undefined,now)};Cron.prototype._next=function(prev){const hasPreviousRun=prev||this._states.previousRun?true:false;prev=new CronDate(prev,this.options.timezone||this.options.utcOffset);if(this.options.startAt&&prev&&prev.getTime()<this.options.startAt.getTime()){prev=this.options.startAt}const nextRun=this._states.once||new CronDate(prev,this.options.timezone||this.options.utcOffset).increment(this.pattern,this.options,hasPreviousRun);if(this._states.once&&this._states.once.getTime()<=prev.getTime()){return null}else if(nextRun===null||this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&nextRun.getTime()>=this.options.stopAt.getTime()){return null}else{return nextRun}};Cron.Cron=Cron;Cron.scheduledJobs=scheduledJobs;return Cron});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "croner",
3
- "version": "5.7.0",
3
+ "version": "6.0.0-dev.0",
4
4
  "description": "Trigger functions and/or evaluate cron expressions in JavaScript. No dependencies. Most features. All environments.",
5
5
  "author": "Hexagon <github.com/hexagon>",
6
6
  "homepage": "https://hexagon.github.io/croner",
@@ -46,38 +46,40 @@
46
46
  "test:lint": "eslint ./**/*.js ./**/*.cjs",
47
47
  "test:lint:fix": "eslint --fix ./**/*.js ./**/*.cjs",
48
48
  "test:ts": "tsc --strict --noEmit ./test/node/ts/basics.ts",
49
- "build": "npm update && npm run build:precleanup && npm run test:lint && npm run build:typings && npm run build:dist && npm run build:minify && npm run build:cleanup && npm run test:coverage && npm run test:dist",
50
- "build:ci": "npm run test:lint && npm run build:typings && npm run build:dist && npm run build:minify && npm run build:cleanup && npm run test:coverage && npm run test:dist",
49
+ "build": "npm update && npm run build:precleanup && npm run test:lint && npm run build:dist && npm run build:typings && npm run build:minify && npm run test:coverage && npm run test:dist",
50
+ "build:ci": "npm run test:lint && npm run build:dist && npm run build:typings && npm run test:coverage && npm run test:dist",
51
51
  "build:precleanup": "(rm -rf types/* || del /Q types\\*) && (rm -rf dist/* || del /Q dist\\*)",
52
52
  "build:dist": "rollup -c ./rollup.config.js",
53
- "build:minify": "uglifyjs dist/croner.cjs --source-map -o dist/croner.min.js && uglifyjs dist/croner.cjs --source-map -o dist/croner.min.cjs && uglifyjs dist/croner.mjs --source-map -o dist/croner.min.mjs",
54
- "build:typings": "tsc",
55
- "build:cleanup": "(rm dist/croner.mjs || del dist\\croner.mjs) || (rm dist/croner.cjs || del dist\\croner.cjs)",
56
- "build:docs": "((rm -rf dist-docs/* || rd /S /Q dist-docs) && jsdoc -c .jsdoc.json) || jsdoc -c .jsdoc.json"
53
+ "build:minify": "uglifyjs dist/croner.umd.js --source-map -o dist/croner.umd.min.js && uglifyjs dist/croner.js --source-map -o dist/croner.min.js",
54
+ "build:typings": "tsc && tsc --build tsconfig.cjs.json",
55
+ "build:docs": "((rm -rf docs/* || rd /S /Q docs) && jsdoc -c .jsdoc.json) || jsdoc -c .jsdoc.json"
57
56
  },
58
57
  "type": "module",
59
- "main": "./dist/croner.min.cjs",
60
- "browser": "./dist/croner.min.js",
61
- "module": "./dist/croner.min.mjs",
58
+ "main": "./dist/croner.cjs",
59
+ "browser": "./dist/croner.umd.js",
60
+ "module": "./dist/croner.js",
62
61
  "types": "./types/croner.d.ts",
63
62
  "exports": {
64
63
  "./package.json": "./package.json",
65
64
  ".": {
66
65
  "import": {
67
66
  "types": "./types/croner.d.ts",
68
- "default": "./dist/croner.min.mjs"
67
+ "default": "./dist/croner.js"
69
68
  },
70
- "require": "./dist/croner.min.cjs",
71
- "browser": "./dist/croner.min.js"
69
+ "require": {
70
+ "types": "./types/croner.d.cts",
71
+ "default": "./dist/croner.cjs"
72
+ },
73
+ "browser": "./dist/croner.umd.js"
72
74
  }
73
75
  },
74
76
  "devDependencies": {
75
77
  "c8": "^7.11.3",
76
- "eslint": "^8.19.0",
78
+ "eslint": "8.34.0",
77
79
  "jsdoc": "^4.0.0",
78
80
  "jsdoc-chameleon-template": "^1.0.2",
79
81
  "minitz": "^4.0.0",
80
- "rollup": "^3.2.3",
82
+ "rollup": "3.17.1",
81
83
  "typescript": "^4.7.4",
82
84
  "uglify-js": "^3.17.1",
83
85
  "uvu": "^0.5.6"
@@ -0,0 +1,402 @@
1
+ export = Cron;
2
+ /**
3
+ * Cron entrypoint
4
+ *
5
+ * @constructor
6
+ * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string
7
+ * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern
8
+ * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern
9
+ * @returns {Cron}
10
+ */
11
+ declare function Cron(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function): Cron;
12
+ declare class Cron {
13
+ /**
14
+ * Cron entrypoint
15
+ *
16
+ * @constructor
17
+ * @param {string|Date} pattern - Input pattern, input date, or input ISO 8601 time string
18
+ * @param {CronOptions|Function} [fnOrOptions1] - Options or function to be run each iteration of pattern
19
+ * @param {CronOptions|Function} [fnOrOptions2] - Options or function to be run each iteration of pattern
20
+ * @returns {Cron}
21
+ */
22
+ constructor(pattern: string | Date, fnOrOptions1?: CronOptions | Function, fnOrOptions2?: CronOptions | Function);
23
+ /**
24
+ * @public
25
+ * @type {string|undefined} */
26
+ public name: string | undefined;
27
+ /**
28
+ * @public
29
+ * @type {CronOptions} */
30
+ public options: CronOptions;
31
+ /**
32
+ * Encapsulate all internal states in an object.
33
+ * Duplicate all options that can change to internal states, for example maxRuns and paused.
34
+ * @private
35
+ */
36
+ private _states;
37
+ pattern: CronPattern;
38
+ fn: Function | CronOptions;
39
+ /**
40
+ * Find next runtime, based on supplied date. Strips milliseconds.
41
+ *
42
+ * @param {CronDate|Date|string} [prev] - Date to start from
43
+ * @returns {Date | null} - Next run time
44
+ */
45
+ next(prev?: CronDate | Date | string): Date | null;
46
+ /**
47
+ * Find next n runs, based on supplied date. Strips milliseconds.
48
+ *
49
+ * @param {number} n - Number of runs to enumerate
50
+ * @param {Date|string} [previous] - Date to start from
51
+ * @returns {Date[]} - Next n run times
52
+ */
53
+ enumerate(n: number, previous?: Date | string): Date[];
54
+ /**
55
+ * Indicates wether or not the cron job is active, e.g. awaiting next trigger
56
+ * @public
57
+ *
58
+ * @returns {boolean} - Running or not
59
+ */
60
+ public running(): boolean;
61
+ /**
62
+ * Indicates wether or not the cron job is currently working
63
+ * @public
64
+ *
65
+ * @returns {boolean} - Running or not
66
+ */
67
+ public busy(): boolean;
68
+ /**
69
+ * Return current/previous run start time
70
+ * @public
71
+ *
72
+ * @returns {Date | null} - Previous run time
73
+ */
74
+ public started(): Date | null;
75
+ /**
76
+ * Return previous run start time
77
+ * @public
78
+ *
79
+ * @returns {Date | null} - Previous run time
80
+ */
81
+ public previous(): Date | null;
82
+ /**
83
+ * Returns number of milliseconds to next run
84
+ * @public
85
+ *
86
+ * @param {CronDate|Date|string} [prev] - Starting date, defaults to now - minimum interval
87
+ * @returns {number | null}
88
+ */
89
+ public msToNext(prev?: CronDate | Date | string): number | null;
90
+ /**
91
+ * Stop execution
92
+ *
93
+ * Running this will forcefully stop the job, and prevent furter exection. `.resume()` will not work after stopping.
94
+ *
95
+ * @public
96
+ */
97
+ public stop(): void;
98
+ /**
99
+ * Pause execution
100
+ * @public
101
+ *
102
+ * @returns {boolean} - Wether pause was successful
103
+ */
104
+ public pause(): boolean;
105
+ /**
106
+ * Resume execution
107
+ * @public
108
+ *
109
+ * @returns {boolean} - Wether resume was successful
110
+ */
111
+ public resume(): boolean;
112
+ /**
113
+ * Schedule a new job
114
+ * @public
115
+ *
116
+ * @param {Function} func - Function to be run each iteration of pattern
117
+ * @param {Date} [partial] - Internal function indicating a partial run
118
+ * @returns {Cron}
119
+ */
120
+ public schedule(func: Function, partial?: Date): Cron;
121
+ private _trigger;
122
+ /**
123
+ * Trigger a run manually
124
+ * @public
125
+ */
126
+ public trigger(): Promise<void>;
127
+ private _checkTrigger;
128
+ private _next;
129
+ }
130
+ declare namespace Cron {
131
+ export { Cron, scheduledJobs, TimePoint, CatchCallbackFn, ProtectCallbackFn, CronOptions, CronPatternPart, CronIndexOffset };
132
+ }
133
+ /**
134
+ * @callback CatchCallbackFn
135
+ * @param {unknown} e
136
+ * @param {Cron} job
137
+ */
138
+ /**
139
+ * @callback ProtectCallbackFn
140
+ * @param {Cron} job
141
+ */
142
+ /**
143
+ * @typedef {Object} CronOptions - Cron scheduler options
144
+ * @property {string} [name] - Name of a job
145
+ * @property {boolean} [paused] - Job is paused
146
+ * @property {boolean} [kill] - Job is about to be killed or killed
147
+ * @property {boolean | CatchCallbackFn} [catch] - Continue exection even if a unhandled error is thrown by triggered function
148
+ * - If set to a function, execute function on catching the error.
149
+ * @property {boolean} [unref] - Abort job instantly if nothing else keeps the event loop running.
150
+ * @property {number} [maxRuns] - Maximum nuber of executions
151
+ * @property {number} [interval] - Minimum interval between executions, in seconds
152
+ * @property {boolean | ProtectCallbackFn} [protect] - Skip current run if job is already running
153
+ * @property {string | Date} [startAt] - When to start running
154
+ * @property {string | Date} [stopAt] - When to stop running
155
+ * @property {string} [timezone] - Time zone in Europe/Stockholm format
156
+ * @property {number} [utcOffset] - Offset from UTC in minutes
157
+ * @property {boolean} [legacyMode] - Combine day-of-month and day-of-week using true = OR, false = AND. Default is true = OR.
158
+ * @property {?} [context] - Used to pass any object to scheduled function
159
+ */
160
+ /**
161
+ * Internal function that validates options, and sets defaults
162
+ * @private
163
+ *
164
+ * @param {CronOptions} options
165
+ * @returns {CronOptions}
166
+ */
167
+ declare function CronOptions(options: CronOptions): CronOptions;
168
+ /**
169
+ * Name for each part of the cron pattern
170
+ * @typedef {("second" | "minute" | "hour" | "day" | "month" | "dayOfWeek")} CronPatternPart
171
+ */
172
+ /**
173
+ * Offset, 0 or -1.
174
+ *
175
+ * 0 offset is used for seconds,minutes and hours as they start on 1.
176
+ * -1 on days and months, as they start on 0
177
+ *
178
+ * @typedef {Number} CronIndexOffset
179
+ */
180
+ /**
181
+ * Create a CronPattern instance from pattern string ('* * * * * *')
182
+ * @constructor
183
+ * @param {string} pattern - Input pattern
184
+ * @param {string} timezone - Input timezone, used for '?'-substitution
185
+ */
186
+ declare function CronPattern(pattern: string, timezone: string): void;
187
+ declare class CronPattern {
188
+ /**
189
+ * Name for each part of the cron pattern
190
+ * @typedef {("second" | "minute" | "hour" | "day" | "month" | "dayOfWeek")} CronPatternPart
191
+ */
192
+ /**
193
+ * Offset, 0 or -1.
194
+ *
195
+ * 0 offset is used for seconds,minutes and hours as they start on 1.
196
+ * -1 on days and months, as they start on 0
197
+ *
198
+ * @typedef {Number} CronIndexOffset
199
+ */
200
+ /**
201
+ * Create a CronPattern instance from pattern string ('* * * * * *')
202
+ * @constructor
203
+ * @param {string} pattern - Input pattern
204
+ * @param {string} timezone - Input timezone, used for '?'-substitution
205
+ */
206
+ constructor(pattern: string, timezone: string);
207
+ pattern: string;
208
+ timezone: string;
209
+ second: any[];
210
+ minute: any[];
211
+ hour: any[];
212
+ day: any[];
213
+ month: any[];
214
+ dayOfWeek: any[];
215
+ lastDayOfMonth: boolean;
216
+ lastWeekdayOfMonth: boolean;
217
+ starDOM: boolean;
218
+ starDOW: boolean;
219
+ private parse;
220
+ private partToArray;
221
+ private throwAtIllegalCharacters;
222
+ private handleNumber;
223
+ private handleRangeWithStepping;
224
+ private handleRange;
225
+ private handleStepping;
226
+ private replaceAlphaDays;
227
+ private replaceAlphaMonths;
228
+ private handleNicknames;
229
+ }
230
+ /**
231
+ * - Cron scheduler options
232
+ */
233
+ type CronOptions = {
234
+ /**
235
+ * - Name of a job
236
+ */
237
+ name?: string;
238
+ /**
239
+ * - Job is paused
240
+ */
241
+ paused?: boolean;
242
+ /**
243
+ * - Job is about to be killed or killed
244
+ */
245
+ kill?: boolean;
246
+ /**
247
+ * - Continue exection even if a unhandled error is thrown by triggered function
248
+ * - If set to a function, execute function on catching the error.
249
+ */
250
+ catch?: boolean | CatchCallbackFn;
251
+ /**
252
+ * - Abort job instantly if nothing else keeps the event loop running.
253
+ */
254
+ unref?: boolean;
255
+ /**
256
+ * - Maximum nuber of executions
257
+ */
258
+ maxRuns?: number;
259
+ /**
260
+ * - Minimum interval between executions, in seconds
261
+ */
262
+ interval?: number;
263
+ /**
264
+ * - Skip current run if job is already running
265
+ */
266
+ protect?: boolean | ProtectCallbackFn;
267
+ /**
268
+ * - When to start running
269
+ */
270
+ startAt?: string | Date;
271
+ /**
272
+ * - When to stop running
273
+ */
274
+ stopAt?: string | Date;
275
+ /**
276
+ * - Time zone in Europe/Stockholm format
277
+ */
278
+ timezone?: string;
279
+ /**
280
+ * - Offset from UTC in minutes
281
+ */
282
+ utcOffset?: number;
283
+ /**
284
+ * - Combine day-of-month and day-of-week using true = OR, false = AND. Default is true = OR.
285
+ */
286
+ legacyMode?: boolean;
287
+ /**
288
+ * - Used to pass any object to scheduled function
289
+ */
290
+ context?: unknown;
291
+ };
292
+ /**
293
+ * Converts date to CronDate
294
+ * @constructor
295
+ *
296
+ * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected
297
+ * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.
298
+ */
299
+ declare function CronDate(d?: CronDate | Date | string, tz?: string | number): void;
300
+ declare class CronDate {
301
+ /**
302
+ * Converts date to CronDate
303
+ * @constructor
304
+ *
305
+ * @param {CronDate|Date|string} [d] - Input date, if using string representation ISO 8001 (2015-11-24T19:40:00) local timezone is expected
306
+ * @param {string|number} [tz] - String representation of target timezone in Europe/Stockholm format, or a number representing offset in minutes.
307
+ */
308
+ constructor(d?: CronDate | Date | string, tz?: string | number);
309
+ /**
310
+ * TimeZone
311
+ * @type {string|number|undefined}
312
+ */
313
+ tz: string | number | undefined;
314
+ private fromDate;
315
+ ms: number;
316
+ second: number;
317
+ minute: number;
318
+ hour: number;
319
+ day: number;
320
+ month: number;
321
+ year: number;
322
+ private fromCronDate;
323
+ private apply;
324
+ private fromString;
325
+ private findNext;
326
+ private recurse;
327
+ /**
328
+ * Increment to next run time
329
+ * @public
330
+ *
331
+ * @param {string} pattern - The pattern used to increment current state
332
+ * @param {CronOptions} options - Cron options used for incrementing
333
+ * @param {boolean} [hasPreviousRun] - If this run should adhere to minimum interval
334
+ * @return {CronDate|null} - Returns itthis for chaining, or null if increment wasnt possible
335
+ */
336
+ public increment(pattern: string, options: CronOptions, hasPreviousRun?: boolean): CronDate | null;
337
+ /**
338
+ * Convert current state back to a javascript Date()
339
+ * @public
340
+ *
341
+ * @param {boolean} internal - If this is an internal call
342
+ * @returns {Date}
343
+ */
344
+ public getDate(internal: boolean): Date;
345
+ /**
346
+ * Convert current state back to a javascript Date() and return UTC milliseconds
347
+ * @public
348
+ *
349
+ * @returns {Date}
350
+ */
351
+ public getTime(): Date;
352
+ }
353
+ /**
354
+ * An array containing all named cron jobs.
355
+ *
356
+ * @constant
357
+ * @type {Cron[]}
358
+ */
359
+ declare const scheduledJobs: Cron[];
360
+ type TimePoint = {
361
+ /**
362
+ * - 1970--
363
+ */
364
+ y: number;
365
+ /**
366
+ * - 1-12
367
+ */
368
+ m: number;
369
+ /**
370
+ * - 1-31
371
+ */
372
+ d: number;
373
+ /**
374
+ * - 0-24
375
+ */
376
+ h: number;
377
+ /**
378
+ * - 0-60 Minute
379
+ */
380
+ i: number;
381
+ /**
382
+ * - 0-60
383
+ */
384
+ s: number;
385
+ /**
386
+ * - Time zone in IANA database format 'Europe/Stockholm'
387
+ */
388
+ tz: string;
389
+ };
390
+ type CatchCallbackFn = (e: unknown, job: Cron) => any;
391
+ type ProtectCallbackFn = (job: Cron) => any;
392
+ /**
393
+ * Name for each part of the cron pattern
394
+ */
395
+ type CronPatternPart = ("second" | "minute" | "hour" | "day" | "month" | "dayOfWeek");
396
+ /**
397
+ * Offset, 0 or -1.
398
+ *
399
+ * 0 offset is used for seconds,minutes and hours as they start on 1.
400
+ * -1 on days and months, as they start on 0
401
+ */
402
+ type CronIndexOffset = number;