-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
cron.js
86 lines (70 loc) · 2.55 KB
/
cron.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import { INVALID_CRON } from '../errors';
import ValidationError from '../errors/ValidationError';
import Base from './Base';
import StringRule from './string';
function parse(string) {
const values = [];
const ranges = [];
for (const variant of string.split(',')) {
const [ ranged, step, ...rest ] = variant.split('/');
if (!ranged || rest.length > 0) throw new INVALID_CRON('INVALID_RANGE');
if (step) ranges.push(step);
if (ranged === '*') continue;
values.push(...ranged.split('-'));
}
return { values, ranges };
}
function parseAll([ minute, hour, dayOfMonth, month, dayOfWeek, ...raw ]) {
if (raw.length > 0) throw new INVALID_CRON('EXCESSIVE_PART');
const res = { ranges: [] };
Object.entries({ minute, hour, dayOfMonth, month, dayOfWeek })
.forEach(([ key, value ]) => {
if (!value) throw new INVALID_CRON({ key: 'REQUIRED' });
const { values, ranges } = parse(value);
res[key] = values;
res.ranges.push(...ranges);
});
return res;
}
const monthList = [ 'jan', 'feb', 'mar', 'apr', 'ma', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ];
const dayOfWeekList = [ 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun' ];
const rules = {
ranges : { every: [ 'integer', { min: 1 } ] },
minute : { every: [ 'integer', { min: 0 }, { max: 59 } ] },
hour : { every: [ 'integer', { min: 0 }, { max: 23 } ] },
dayOfMonth : { every: [ 'integer', { min: 1 }, { max: 31 } ] },
month : { every : { or : [
[ 'integer', { min: 1 }, { max: 12 } ],
[ 'to_lower', { enum: monthList } ]
] } },
dayOfWeek : { every : { or : [
[ 'integer', { min: 0 }, { max: 6 } ],
[ 'to_lower', { enum: dayOfWeekList } ]
] } }
};
/**
* Checks string to be valid a cron string.
* @error INVALID_CRON
* @depends string
* @returns {string} valid cron string
* @rule
*/
export default class CronRule extends Base {
static schema = 'cron';
validate(input) {
const parentRule = this.createChildRule(StringRule);
const string = parentRule.validate(input);
const raw = string.trim().split(/\s+/);
const toCheck = parseAll(raw);
const validator = this.createNestedValidator({ attributes: rules });
try {
validator.validate(toCheck);
} catch (error) {
if (error instanceof ValidationError) {
throw new INVALID_CRON(error);
}
throw error;
}
return raw.join(' ');
}
}