UNPKG

quartzcron

Version:

version: `0.1.0` [CHANGELOG](https://github.com/fedeghe/quartzcron/blob/master/CHANGELOG.md)

368 lines (347 loc) 11.6 kB
/* quartzcron (v.0.1.0) */ const { defaults, yearNow, removeSpaces, argumentize, daysLabels2Numbers } = require('./utils'), { validators, fieldCorrelationValidators } = require('./validators'), { solve_0_59_ranges, solve_hours_ranges, solve_week_ranges, solve_month_ranges, solve_year_ranges, solve_dom, solve_dow, } = require('./dateutils.js'), nextGen = require('./nextGen'), C = require('./constants'); class Quartzcron { constructor(o) { this.months = { min: 0, max: 11 }; this.elements = argumentize(o); const validity = this.validate(); if(!validity.valid) throw new Error(C.errors.constructorErr); }; // static lang = 'en'; static solvers = { solve_0_59_ranges, solve_hours_ranges, solve_week_ranges, solve_month_ranges, solve_year_ranges, solve_dom, solve_dow, }; static getRanger(max) { return n => { let normN = parseInt(n, 10) % max; while (normN < 0) normN += max; return normN; }; } range24 = Quartzcron.getRanger(24); range12 = Quartzcron.getRanger(12); range60 = Quartzcron.getRanger(60); updateExp(o) { this.elements = argumentize(o); const validity = this.validate(); if(!validity.valid) throw new Error(C.errors.updateExpErr); return this; } over(ov) { this.elements = Object.entries(this.elements).reduce((acc, [k, v]) => { acc[k] = removeSpaces(ov[k] ?? v); return acc; }, {}); return this; } overAdd(ov) { const $ = this, mod = Object.entries(ov).reduce((acc, [k, v]) => { const current = $.elements[k].split(',').filter(Boolean); acc[k] = removeSpaces([...current, v].join(',')); return acc; }, {}); this.elements = {...this.elements, ...mod}; return this; } /* seconds */ everySecond() { return this.over({ s: '*'}); } everyNSeconds(freq, start = 0) { return this.over({ s: `${start}/${freq}` }); } everyNSecondsAdd(freq, start = 0) { return this.overAdd({ s: `${start}/${freq}` }); } atSecond(s, cad) { return this.over({ s: cad ? `${s}/${cad}` : `${s}` }); } atSecondAdd(s, cad) { return this.overAdd({ s: cad ? `${s}/${cad}` : `${s}`}); } betweenSeconds(from, to, every) { return this.over({ s: `${from}-${to}${every ? `/${every}`: ''}` }); } betweenSecondsAdd(from, to, every) { return this.overAdd({ s: `${from}-${to}${every ? `/${every}`: ''}` }); } /* minutes */ everyMinute() { return this.over({ i: '*'}); } everyNMinutes(freq, start = 0) { return this.over({ i: `${start}/${freq}` }); } everyNMinutesAdd(freq, start = 0) { return this.overAdd({ i: `${start}/${freq}` }); } atMinute(i, cad) { return this.over({ i: cad ? `${i}/${cad}` : `${i}` }); } atMinuteAdd(i, cad) { return this.overAdd({i: cad ? `${i}/${cad}` : `${i}`}); } betweenMinutes(from, to, every) { return this.over({ i: `${from}-${to}${every ? `/${every}` : ''}` }); } betweenMinutesAdd(from, to, every) { return this.overAdd({ i: `${from}-${to}${every ? `/${every}` : ''}` }); } /* hours */ everyHour() { return this.over({ h: '*'}); } everyNHours(freq, start = 0) { return this.over({ h: `${start}/${freq}` }); } everyNHoursAdd(freq, start = 0) { return this.overAdd({ h: `${start}/${freq}` }); } atHour(h, cad) { return this.over({ h: cad ? `${h}/${cad}` : `${h}` }); } atHourAdd(h, cad) { return this.overAdd({ h: cad ? `${h}/${cad}` : `${h}`}); } betweenHours(from, to, every) { return this.over({ h: `${from}-${to}${every ? `/${every}`: ''}` }); } betweenHoursAdd(from, to, every) { return this.overAdd({ h: `${from}-${to}${every ? `/${every}`: ''}` }); } /* dom/dow */ everyDay(){ return this.over({ dom: '*', dow:'?'}); } everyNDays(n, start = 1){ return this.over({ dom: `${start}/${n}`, dow: '?'}); } everyNDaysAdd(n, start = 1){ return this.overAdd({ dom: `${start}/${n}`, dow: '?'}); } everyWeekEnd() { return this.over({ dom: '?', dow: '7,1' }); } everyWeekDay() { return this.over({ dom: '?', dow: '2-6' }); } atWeekDay(d, cad){ // transform d to n const nd = daysLabels2Numbers(d); return this.over({ dom: '?', dow: cad ? `${nd}/${cad}` : `${nd}` }); } atWeekDayAdd(d, cad) { // transform d to n const nd = daysLabels2Numbers(d); return this.elements.dow === defaults.dow ? this.over({ dom: '?', dow: cad ? `${nd}/${cad}` : `${nd}` }) : this.overAdd({ dow: cad ? `${nd}/${cad}` : `${nd}` }); } // the relative validator should check it betweenWeekDays(from, to, every) { if(from>=to) return this; return this.over({ dom: '?', dow: `${from}-${to}${every ? `/${every}`: ''}`}); } betweenWeekDaysAdd(from, to, every) { if (from>=to) return this; return this.over({dom: '?'}) .overAdd({ dom: '?', dow: `${from}-${to}${every ? `/${every}`: ''}`}); } atMonthDay(dom, cad) { return this.over({ dom: cad ? `${dom}/${cad}` : `${dom}`, dow: '?' }); } atMonthDayAdd(dom, cad) { return this.elements.dom === defaults.dom ? this.over({dom: cad ? `${dom}/${cad}` : `${dom}`, dow: '?'}) : this.overAdd({dom: cad ? `${dom}/${cad}` : `${dom}`}); } betweenMonthDays(from, to, every) { return this.over({ dom: `${from}-${to}${every ? `/${every}`: ''}`, dow: '?' }); } betweenMonthDaysAdd(from, to, every) { return this.overAdd({ dom: `${from}-${to}${every ? `/${every}`: ''}`}); } onLastMonthDay(){ return this.over({ dom: 'L', dow: '?' }); } onFirstMonthWeekDay(){ return this.over({ dom:`1W`, dow: '?' }); } onLastMonthWeekDay(){ return this.over({ dom: 'LW', dow: '?' }); } onLastMonthNWeekDay(x){ return this.over({ dom: '?', dow: `${x}L` }); } onNDayBeforeTheEndOfTheMonth(x){ return this.over({ dom:`L-${x}`, dow: '?' }); } onClosestWorkingDayToTheNMonthDay(x) { return this.over({ dom:`${x}W`, dow: '?' }); } onNWeekDayOfTheMonth(n,wd) { return this.over({ dom:'?', dow: `${wd}#${n}` }); } /* month */ everyMonth() { return this.over({ m: '*'}); } everyNMonths(freq, start = 1) { return this.over({ m: `${start}/${freq}` }); } everyNMonthsAdd(freq, start = 1) { return this.elements.m === defaults.m ? this.over({ m: `${start}/${freq}` }) : this.overAdd({ m: `${start}/${freq}` }); } atMonth(m, cad) { return this.over({ m: cad ? `${m}/${cad}` : `${m}` }); } atMonthAdd(m, cad) { return this.elements.m === defaults.m ? this.over({ m: cad ? `${m}/${cad}` : `${m}`}) : this.overAdd({ m: cad ? `${m}/${cad}` : `${m}`}); } betweenMonths(from, to, every) { return this.over({ m: `${from}-${to}${every ? `/${every}` : ''}` }); } betweenMonthsAdd(from, to, every) { return this.elements.m === defaults.m ? this.over({ m: `${from}-${to}${every ? `/${every}` : ''}` }) : this.overAdd({ m: `${from}-${to}${every ? `/${every}` : ''}` }); } /* year */ everyYear() { return this.over({ y: '*'}); } everyNYears(freq, start = yearNow) { return this.over({ y: `${start}/${freq}` }); } everyNYearsAdd(freq, start = yearNow) { return this.elements.y === defaults.y ? this.over({ y: `${start}/${freq}` }) : this.overAdd({ y: `${start}/${freq}` }); } atYear(y, cad) { return this.over({ y: cad ? `${y}/${cad}` : `${y}` }); } atYearAdd(y, cad) { return this.elements.y === defaults.y ? this.over({ y: cad ? `${y}/${cad}` : `${y}`}) : this.overAdd({ y: cad ? `${y}/${cad}` : `${y}`}); } betweenYears(from, to, every) { return this.over({ y: `${from}-${to}${every ? `/${every}` : ''}` }); } betweenYearsAdd(from, to, every) { return this.elements.y === defaults.y ? this.over({ y: `${from}-${to}${every ? `/${every}` : ''}` }) : this.overAdd({ y: `${from}-${to}${every ? `/${every}` : ''}` }); } /***********/ next({n = 1, date = null} = {}){ const base = date || new Date(), elements = this.elements; if (base == 'Invalid Date') { throw new Error(C.errors.invalidDate); } const y = base.getUTCFullYear(), allgen = nextGen.generateDates( base, solve_year_ranges(elements.y).filter(ye => ye >= y), // remove past years solve_month_ranges(elements.m), elements.dom, elements.dow, solve_hours_ranges(elements.h), solve_0_59_ranges(elements.i), solve_0_59_ranges(elements.s), ); return Array.from( { length: n }, () => allgen.next().value ).filter(Boolean); } validate(exp){ return Quartzcron.validate(exp || this.out()); } static validate(exp){ const errors = [], local = exp ? `${exp}`.split(/\s/) : false, elements = local && { s : local[0], i : local[1], h : local[2], dom : local[3], m : local[4], dow : local[5], y : local[6], }; if(!local)return { valid: local, errors:[C.errors.staticValidationParamMissing] }; fieldCorrelationValidators.forEach(({ validator, message }) => { if(!validator(elements)){ errors.push(message); } }); validators.second(elements.s) || errors.push(C.errors.malformed.seconds); validators.minute(elements.i) || errors.push(C.errors.malformed.minutes); validators.hour(elements.h) || errors.push(C.errors.malformed.hours); validators.dayOfMonth(elements.dom) || errors.push(C.errors.malformed.dom); validators.month(elements.m) || errors.push(C.errors.malformed.months); validators.dayOfWeek(elements.dow) || errors.push(C.errors.malformed.dow); elements.y && ( validators.year(elements.y) || errors.push(C.errors.malformed.years) ); return { valid: errors.length === 0, errors }; } out() { return [ this.elements.s, this.elements.i, this.elements.h, this.elements.dom, this.elements.m, this.elements.dow, this.elements.y, ] .filter(e => e !== undefined && e !== null) .join(' '); } toString = this.out; } module.exports = Quartzcron;