@geekmidas/manifest 9.2.1 → 9.3.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.
- package/CHANGELOG.md +20 -0
- package/dist/cron-CjhmidCo.d.cts +104 -0
- package/dist/cron-CjhmidCo.d.cts.map +1 -0
- package/dist/cron-DC4hQ1oa.mjs +396 -0
- package/dist/cron-DC4hQ1oa.mjs.map +1 -0
- package/dist/cron-DXiVSeD6.cjs +438 -0
- package/dist/cron-DXiVSeD6.cjs.map +1 -0
- package/dist/cron-DlCX5PWN.d.mts +104 -0
- package/dist/cron-DlCX5PWN.d.mts.map +1 -0
- package/dist/cron.cjs +9 -0
- package/dist/cron.d.cts +2 -0
- package/dist/cron.d.mts +2 -0
- package/dist/cron.mjs +3 -0
- package/dist/index.cjs +8 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +4 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/cron.spec.ts +253 -0
- package/src/cron.ts +502 -0
- package/src/index.ts +2 -0
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/cron.ts
|
|
3
|
+
/**
|
|
4
|
+
* The expression is not valid in its own dialect. `field` is absent when the
|
|
5
|
+
* expression isn't `cron(…)` with five or six fields at all.
|
|
6
|
+
*/
|
|
7
|
+
var InvalidCronExpressionError = class extends Error {
|
|
8
|
+
constructor(expression, token, field) {
|
|
9
|
+
super("Invalid cron expression", { cause: {
|
|
10
|
+
expression,
|
|
11
|
+
field,
|
|
12
|
+
token
|
|
13
|
+
} });
|
|
14
|
+
this.expression = expression;
|
|
15
|
+
this.token = token;
|
|
16
|
+
this.field = field;
|
|
17
|
+
this.name = "InvalidCronExpressionError";
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
/** The expression is valid, but has no equivalent in the target dialect. */
|
|
21
|
+
var UnconvertibleCronExpressionError = class extends Error {
|
|
22
|
+
constructor(expression, field, token) {
|
|
23
|
+
super("Cron expression cannot be converted", { cause: {
|
|
24
|
+
expression,
|
|
25
|
+
field,
|
|
26
|
+
token
|
|
27
|
+
} });
|
|
28
|
+
this.expression = expression;
|
|
29
|
+
this.field = field;
|
|
30
|
+
this.token = token;
|
|
31
|
+
this.name = "UnconvertibleCronExpressionError";
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const MONTHS = [
|
|
35
|
+
"JAN",
|
|
36
|
+
"FEB",
|
|
37
|
+
"MAR",
|
|
38
|
+
"APR",
|
|
39
|
+
"MAY",
|
|
40
|
+
"JUN",
|
|
41
|
+
"JUL",
|
|
42
|
+
"AUG",
|
|
43
|
+
"SEP",
|
|
44
|
+
"OCT",
|
|
45
|
+
"NOV",
|
|
46
|
+
"DEC"
|
|
47
|
+
];
|
|
48
|
+
const DAYS = [
|
|
49
|
+
"SUN",
|
|
50
|
+
"MON",
|
|
51
|
+
"TUE",
|
|
52
|
+
"WED",
|
|
53
|
+
"THU",
|
|
54
|
+
"FRI",
|
|
55
|
+
"SAT"
|
|
56
|
+
];
|
|
57
|
+
const RULES = {
|
|
58
|
+
minute: {
|
|
59
|
+
min: 0,
|
|
60
|
+
max: 59
|
|
61
|
+
},
|
|
62
|
+
hour: {
|
|
63
|
+
min: 0,
|
|
64
|
+
max: 23
|
|
65
|
+
},
|
|
66
|
+
dayOfMonth: {
|
|
67
|
+
min: 1,
|
|
68
|
+
max: 31
|
|
69
|
+
},
|
|
70
|
+
month: {
|
|
71
|
+
min: 1,
|
|
72
|
+
max: 12,
|
|
73
|
+
names: MONTHS
|
|
74
|
+
},
|
|
75
|
+
unixDayOfWeek: {
|
|
76
|
+
min: 0,
|
|
77
|
+
max: 7,
|
|
78
|
+
names: DAYS
|
|
79
|
+
},
|
|
80
|
+
awsDayOfWeek: {
|
|
81
|
+
min: 1,
|
|
82
|
+
max: 7,
|
|
83
|
+
names: DAYS
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
/** A number in range (one or two digits), or one of the field's names. */
|
|
87
|
+
const toValue = (token, rule) => {
|
|
88
|
+
const named = rule.names?.indexOf(token) ?? -1;
|
|
89
|
+
if (named >= 0) return rule.min + named;
|
|
90
|
+
if (!/^\d{1,2}$/.test(token)) return void 0;
|
|
91
|
+
const value = Number(token);
|
|
92
|
+
return value >= rule.min && value <= rule.max ? value : void 0;
|
|
93
|
+
};
|
|
94
|
+
/** `*`, `v` or `a-b`, with an optional `/step`. */
|
|
95
|
+
const isAtom = (atom, rule) => {
|
|
96
|
+
const [base = "", step, ...rest] = atom.split("/");
|
|
97
|
+
if (rest.length > 0) return false;
|
|
98
|
+
if (step !== void 0 && !/^\d{1,2}$/.test(step)) return false;
|
|
99
|
+
if (base === "*") return true;
|
|
100
|
+
const [from = "", to, ...more] = base.split("-");
|
|
101
|
+
if (more.length > 0 || toValue(from, rule) === void 0) return false;
|
|
102
|
+
return to === void 0 || toValue(to, rule) !== void 0;
|
|
103
|
+
};
|
|
104
|
+
/** The first atom of a comma-separated field that is invalid. */
|
|
105
|
+
const invalidAtom = (field, isValid) => field.split(",").find((atom) => !isValid(atom));
|
|
106
|
+
const isYear = (token) => /^\d{4}$/.test(token) && Number(token) >= 1970 && Number(token) <= 2199;
|
|
107
|
+
const isYearAtom = (atom) => {
|
|
108
|
+
const [base = "", step, ...rest] = atom.split("/");
|
|
109
|
+
if (rest.length > 0) return false;
|
|
110
|
+
if (step !== void 0 && !/^\d{1,2}$/.test(step)) return false;
|
|
111
|
+
if (base === "*") return true;
|
|
112
|
+
const [from = "", to, ...more] = base.split("-");
|
|
113
|
+
return more.length === 0 && isYear(from) && (to === void 0 || isYear(to));
|
|
114
|
+
};
|
|
115
|
+
/** `L`, `L-n`, `LW` and `nW`, AWS day-of-month only, alone in the field. */
|
|
116
|
+
const isAwsDayOfMonthSpecial = (field) => field === "L" || field === "LW" || /^L-\d{1,2}$/.test(field) || field.endsWith("W") && toValue(field.slice(0, -1), RULES.dayOfMonth) !== void 0;
|
|
117
|
+
/** `nL` and `n#k`, AWS day-of-week only, alone in the field. */
|
|
118
|
+
const isAwsDayOfWeekSpecial = (field) => {
|
|
119
|
+
if (field.endsWith("L")) return toValue(field.slice(0, -1), RULES.awsDayOfWeek) !== void 0;
|
|
120
|
+
const [day = "", nth, ...rest] = field.split("#");
|
|
121
|
+
return nth !== void 0 && rest.length === 0 && toValue(day, RULES.awsDayOfWeek) !== void 0 && /^[1-5]$/.test(nth);
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Splits and validates a `cron(…)` expression in either dialect.
|
|
125
|
+
*
|
|
126
|
+
* @throws {InvalidCronExpressionError} naming the field and token that failed.
|
|
127
|
+
*/
|
|
128
|
+
function parseCron(expression) {
|
|
129
|
+
const inner = /^cron\((.*)\)$/.exec(expression)?.[1];
|
|
130
|
+
const fields = inner?.split(" ") ?? [];
|
|
131
|
+
if (fields.length !== 5 && fields.length !== 6) throw new InvalidCronExpressionError(expression, inner ?? expression);
|
|
132
|
+
const [minute = "", hour = "", dayOfMonth = "", month = "", dayOfWeek = ""] = fields;
|
|
133
|
+
const year = fields[5];
|
|
134
|
+
const dialect = year === void 0 ? "unix" : "aws";
|
|
135
|
+
const fail = (field, token) => {
|
|
136
|
+
throw new InvalidCronExpressionError(expression, token, field);
|
|
137
|
+
};
|
|
138
|
+
const check = (field, value, rule) => {
|
|
139
|
+
const atom = invalidAtom(value, (a) => isAtom(a, rule));
|
|
140
|
+
if (atom !== void 0) fail(field, atom);
|
|
141
|
+
};
|
|
142
|
+
check("minute", minute, RULES.minute);
|
|
143
|
+
check("hour", hour, RULES.hour);
|
|
144
|
+
check("month", month, RULES.month);
|
|
145
|
+
if (year === void 0) {
|
|
146
|
+
check("dayOfMonth", dayOfMonth, RULES.dayOfMonth);
|
|
147
|
+
check("dayOfWeek", dayOfWeek, RULES.unixDayOfWeek);
|
|
148
|
+
return {
|
|
149
|
+
dialect,
|
|
150
|
+
minute,
|
|
151
|
+
hour,
|
|
152
|
+
dayOfMonth,
|
|
153
|
+
month,
|
|
154
|
+
dayOfWeek
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (dayOfMonth === "?" && dayOfWeek === "?") fail("dayOfWeek", "?");
|
|
158
|
+
if (dayOfMonth !== "?" && dayOfWeek !== "?") fail("dayOfWeek", dayOfWeek);
|
|
159
|
+
if (dayOfMonth !== "?" && !isAwsDayOfMonthSpecial(dayOfMonth)) check("dayOfMonth", dayOfMonth, RULES.dayOfMonth);
|
|
160
|
+
if (dayOfWeek !== "?" && !isAwsDayOfWeekSpecial(dayOfWeek)) check("dayOfWeek", dayOfWeek, RULES.awsDayOfWeek);
|
|
161
|
+
const yearAtom = invalidAtom(year, isYearAtom);
|
|
162
|
+
if (yearAtom !== void 0) fail("year", yearAtom);
|
|
163
|
+
return {
|
|
164
|
+
dialect,
|
|
165
|
+
minute,
|
|
166
|
+
hour,
|
|
167
|
+
dayOfMonth,
|
|
168
|
+
month,
|
|
169
|
+
dayOfWeek,
|
|
170
|
+
year
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
/** The values a plain field allows: values, ranges, steps and lists. */
|
|
174
|
+
const fieldValues = (field, rule) => {
|
|
175
|
+
const values = /* @__PURE__ */ new Set();
|
|
176
|
+
for (const atom of field.split(",")) {
|
|
177
|
+
const [base = "", step] = atom.split("/");
|
|
178
|
+
const [from = "", to] = base.split("-");
|
|
179
|
+
const start = base === "*" ? rule.min : toValue(from, rule);
|
|
180
|
+
const end = to !== void 0 ? toValue(to, rule) : base === "*" || step !== void 0 ? rule.max : start;
|
|
181
|
+
for (let value = start; value <= end; value += Number(step ?? 1)) values.add(value);
|
|
182
|
+
}
|
|
183
|
+
return values;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* The days a day-of-week field runs on, as Unix numbers 0–6 (SUN = 0).
|
|
187
|
+
* Only for plain fields: values, ranges, steps and lists.
|
|
188
|
+
*/
|
|
189
|
+
const unixDays = (field, dialect) => {
|
|
190
|
+
const rule = dialect === "unix" ? RULES.unixDayOfWeek : RULES.awsDayOfWeek;
|
|
191
|
+
const days = /* @__PURE__ */ new Set();
|
|
192
|
+
for (const day of fieldValues(field, rule)) days.add(dialect === "unix" ? day % 7 : day - 1);
|
|
193
|
+
return days;
|
|
194
|
+
};
|
|
195
|
+
/** Days as a list, with runs of three or more written as ranges. */
|
|
196
|
+
const formatDays = (days) => {
|
|
197
|
+
const parts = [];
|
|
198
|
+
let i = 0;
|
|
199
|
+
while (i < days.length) {
|
|
200
|
+
let j = i;
|
|
201
|
+
while (j + 1 < days.length && days[j + 1] === days[j] + 1) j++;
|
|
202
|
+
parts.push(j - i >= 2 ? `${days[i]}-${days[j]}` : days.slice(i, j + 1).join(","));
|
|
203
|
+
i = j + 1;
|
|
204
|
+
}
|
|
205
|
+
return parts.join(",");
|
|
206
|
+
};
|
|
207
|
+
/**
|
|
208
|
+
* Rewrites a day-of-week field's numbers into the target dialect. Fields
|
|
209
|
+
* written only with names and `*` mean the same in both and pass through.
|
|
210
|
+
*/
|
|
211
|
+
const convertDayOfWeek = (field, from) => {
|
|
212
|
+
if (!/\d/.test(field)) return field;
|
|
213
|
+
const days = unixDays(field, from);
|
|
214
|
+
if (days.size === 7) return "*";
|
|
215
|
+
if (from === "aws") return formatDays([...days].sort((a, b) => a - b));
|
|
216
|
+
return formatDays([...days].map((day) => day + 1).sort((a, b) => a - b));
|
|
217
|
+
};
|
|
218
|
+
const format = (fields) => `cron(${fields.join(" ")})`;
|
|
219
|
+
/**
|
|
220
|
+
* Converts a cron expression to the six-field AWS form EventBridge reads. An
|
|
221
|
+
* AWS expression is returned unchanged.
|
|
222
|
+
*
|
|
223
|
+
* Unix runs on either day field when both are restricted, and AWS can't
|
|
224
|
+
* express that, so day-of-week is kept and day-of-month dropped with a
|
|
225
|
+
* warning.
|
|
226
|
+
*
|
|
227
|
+
* @throws {InvalidCronExpressionError} when the expression is invalid.
|
|
228
|
+
*/
|
|
229
|
+
function toAwsCron(expression) {
|
|
230
|
+
const cron = parseCron(expression);
|
|
231
|
+
if (cron.dialect === "aws") return {
|
|
232
|
+
expression,
|
|
233
|
+
warnings: []
|
|
234
|
+
};
|
|
235
|
+
const { minute, hour, dayOfMonth, month, dayOfWeek } = cron;
|
|
236
|
+
const warnings = [];
|
|
237
|
+
if (dayOfMonth !== "*" && dayOfWeek !== "*") warnings.push({
|
|
238
|
+
code: "dayOfMonthDropped",
|
|
239
|
+
message: "Both day fields are restricted, so day-of-month was dropped and the cron runs on fewer days",
|
|
240
|
+
token: dayOfMonth
|
|
241
|
+
});
|
|
242
|
+
const [awsDayOfMonth, awsDayOfWeek] = dayOfWeek === "*" ? [dayOfMonth, "?"] : ["?", convertDayOfWeek(dayOfWeek, "unix")];
|
|
243
|
+
return {
|
|
244
|
+
expression: format([
|
|
245
|
+
minute,
|
|
246
|
+
hour,
|
|
247
|
+
awsDayOfMonth,
|
|
248
|
+
month,
|
|
249
|
+
awsDayOfWeek,
|
|
250
|
+
"*"
|
|
251
|
+
]),
|
|
252
|
+
warnings
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Converts a cron expression to the five-field Unix form `cron-parser` reads.
|
|
257
|
+
* A Unix expression is returned unchanged.
|
|
258
|
+
*
|
|
259
|
+
* A specific year is dropped with a warning, so the cron runs every year.
|
|
260
|
+
*
|
|
261
|
+
* @throws {InvalidCronExpressionError} when the expression is invalid.
|
|
262
|
+
* @throws {UnconvertibleCronExpressionError} for `W` and `L-n`, which Unix
|
|
263
|
+
* has no equivalent for.
|
|
264
|
+
*/
|
|
265
|
+
function toUnixCron(expression) {
|
|
266
|
+
const cron = parseCron(expression);
|
|
267
|
+
if (cron.dialect === "unix") return {
|
|
268
|
+
expression,
|
|
269
|
+
warnings: []
|
|
270
|
+
};
|
|
271
|
+
const { minute, hour, dayOfMonth, month, dayOfWeek, year = "*" } = cron;
|
|
272
|
+
const warnings = [];
|
|
273
|
+
if (year !== "*") warnings.push({
|
|
274
|
+
code: "yearDropped",
|
|
275
|
+
message: "The year was dropped, so the cron runs every year",
|
|
276
|
+
token: year
|
|
277
|
+
});
|
|
278
|
+
if (dayOfMonth.includes("W") || dayOfMonth.startsWith("L-")) throw new UnconvertibleCronExpressionError(expression, "dayOfMonth", dayOfMonth);
|
|
279
|
+
return {
|
|
280
|
+
expression: format([
|
|
281
|
+
minute,
|
|
282
|
+
hour,
|
|
283
|
+
dayOfMonth === "?" ? "*" : dayOfMonth,
|
|
284
|
+
month,
|
|
285
|
+
convertAwsDayOfWeek(dayOfWeek)
|
|
286
|
+
]),
|
|
287
|
+
warnings
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/** `?` becomes `*`; `nL` and `n#k` keep their suffix with `n` shifted. */
|
|
291
|
+
const convertAwsDayOfWeek = (field) => {
|
|
292
|
+
if (field === "?") return "*";
|
|
293
|
+
const special = /^(\w+?)(L|#[1-5])$/.exec(field);
|
|
294
|
+
if (special) {
|
|
295
|
+
const [, day = "", suffix = ""] = special;
|
|
296
|
+
return `${convertDayOfWeek(day, "aws")}${suffix}`;
|
|
297
|
+
}
|
|
298
|
+
return convertDayOfWeek(field, "aws");
|
|
299
|
+
};
|
|
300
|
+
/** The expression runs less than twice in the window, so has no period. */
|
|
301
|
+
var CronPeriodError = class extends Error {
|
|
302
|
+
constructor(expression) {
|
|
303
|
+
super("Cron expression runs less than twice in eight years", { cause: { expression } });
|
|
304
|
+
this.expression = expression;
|
|
305
|
+
this.name = "CronPeriodError";
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
const MINUTE = 60;
|
|
309
|
+
const DAY = 24 * 60 * MINUTE;
|
|
310
|
+
/** 2024 to 2031: every weekday and month combination, and two leap years. */
|
|
311
|
+
const PERIOD_START = Date.UTC(2024, 0, 1);
|
|
312
|
+
const PERIOD_DAYS = 2922;
|
|
313
|
+
/**
|
|
314
|
+
* Whether a date in UTC matches an AWS day-of-month field, including `L`,
|
|
315
|
+
* `L-n`, `LW` and `nW`.
|
|
316
|
+
*/
|
|
317
|
+
const dayOfMonthMatcher = (field) => {
|
|
318
|
+
if (field === "?") return () => true;
|
|
319
|
+
const lastDay = (date) => new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0)).getUTCDate();
|
|
320
|
+
const nearestWeekday = (date, day) => {
|
|
321
|
+
const last = lastDay(date);
|
|
322
|
+
const weekday = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), day)).getUTCDay();
|
|
323
|
+
if (weekday === 6) return day === 1 ? 3 : day - 1;
|
|
324
|
+
if (weekday === 0) return day === last ? day - 2 : day + 1;
|
|
325
|
+
return day;
|
|
326
|
+
};
|
|
327
|
+
if (field === "L") return (date) => date.getUTCDate() === lastDay(date);
|
|
328
|
+
if (field.startsWith("L-")) {
|
|
329
|
+
const offset = Number(field.slice(2));
|
|
330
|
+
return (date) => date.getUTCDate() === lastDay(date) - offset;
|
|
331
|
+
}
|
|
332
|
+
if (field === "LW") return (date) => date.getUTCDate() === nearestWeekday(date, lastDay(date));
|
|
333
|
+
if (field.endsWith("W")) {
|
|
334
|
+
const day = Number(field.slice(0, -1));
|
|
335
|
+
return (date) => day <= lastDay(date) && date.getUTCDate() === nearestWeekday(date, day);
|
|
336
|
+
}
|
|
337
|
+
const days = fieldValues(field, RULES.dayOfMonth);
|
|
338
|
+
return (date) => days.has(date.getUTCDate());
|
|
339
|
+
};
|
|
340
|
+
/** Whether a date in UTC matches an AWS day-of-week field, including `nL` and `n#k`. */
|
|
341
|
+
const dayOfWeekMatcher = (field) => {
|
|
342
|
+
if (field === "?") return () => true;
|
|
343
|
+
const special = /^(\w+?)(L|#([1-5]))$/.exec(field);
|
|
344
|
+
if (special) {
|
|
345
|
+
const [, day = "", , nth] = special;
|
|
346
|
+
const weekday = toValue(day, RULES.awsDayOfWeek) - 1;
|
|
347
|
+
return (date) => {
|
|
348
|
+
if (date.getUTCDay() !== weekday) return false;
|
|
349
|
+
if (nth !== void 0) return Math.ceil(date.getUTCDate() / 7) === Number(nth);
|
|
350
|
+
return new Date(date.getTime() + 7 * DAY * 1e3).getUTCDate() <= 7;
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
const days = unixDays(field, "aws");
|
|
354
|
+
return (date) => days.has(date.getUTCDay());
|
|
355
|
+
};
|
|
356
|
+
/**
|
|
357
|
+
* The longest gap between two runs of a cron expression, in seconds: the
|
|
358
|
+
* period a heartbeat should expect. A weekdays-only cron has the Friday to
|
|
359
|
+
* Monday gap, so its heartbeat doesn't alert at the weekend.
|
|
360
|
+
*
|
|
361
|
+
* The expression is first converted to the AWS form, so the period is of
|
|
362
|
+
* what EventBridge runs. Runs are worked out in UTC over 2024–2031, and the
|
|
363
|
+
* year field is ignored.
|
|
364
|
+
*
|
|
365
|
+
* @throws {InvalidCronExpressionError} when the expression is invalid.
|
|
366
|
+
* @throws {CronPeriodError} when it runs less than twice in that time.
|
|
367
|
+
*/
|
|
368
|
+
function cronPeriod(expression) {
|
|
369
|
+
const cron = parseCron(toAwsCron(expression).expression);
|
|
370
|
+
const minutes = [...fieldValues(cron.minute, RULES.minute)];
|
|
371
|
+
const hours = [...fieldValues(cron.hour, RULES.hour)];
|
|
372
|
+
const months = fieldValues(cron.month, RULES.month);
|
|
373
|
+
const matchesDayOfMonth = dayOfMonthMatcher(cron.dayOfMonth);
|
|
374
|
+
const matchesDayOfWeek = dayOfWeekMatcher(cron.dayOfWeek);
|
|
375
|
+
const times = hours.flatMap((hour) => minutes.map((minute) => (hour * 60 + minute) * MINUTE)).sort((a, b) => a - b);
|
|
376
|
+
const first = times[0];
|
|
377
|
+
const last = times[times.length - 1];
|
|
378
|
+
let longest = 0;
|
|
379
|
+
for (let i = 1; i < times.length; i++) longest = Math.max(longest, times[i] - times[i - 1]);
|
|
380
|
+
let runs = 0;
|
|
381
|
+
let previousLast;
|
|
382
|
+
for (let day = 0; day < PERIOD_DAYS; day++) {
|
|
383
|
+
const date = new Date(PERIOD_START + day * DAY * 1e3);
|
|
384
|
+
if (!months.has(date.getUTCMonth() + 1)) continue;
|
|
385
|
+
if (!matchesDayOfMonth(date) || !matchesDayOfWeek(date)) continue;
|
|
386
|
+
const start = date.getTime() / 1e3;
|
|
387
|
+
if (previousLast !== void 0) longest = Math.max(longest, start + first - previousLast);
|
|
388
|
+
previousLast = start + last;
|
|
389
|
+
runs += times.length;
|
|
390
|
+
}
|
|
391
|
+
if (runs < 2) throw new CronPeriodError(expression);
|
|
392
|
+
return longest;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
//#endregion
|
|
396
|
+
Object.defineProperty(exports, 'CronPeriodError', {
|
|
397
|
+
enumerable: true,
|
|
398
|
+
get: function () {
|
|
399
|
+
return CronPeriodError;
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
Object.defineProperty(exports, 'InvalidCronExpressionError', {
|
|
403
|
+
enumerable: true,
|
|
404
|
+
get: function () {
|
|
405
|
+
return InvalidCronExpressionError;
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
Object.defineProperty(exports, 'UnconvertibleCronExpressionError', {
|
|
409
|
+
enumerable: true,
|
|
410
|
+
get: function () {
|
|
411
|
+
return UnconvertibleCronExpressionError;
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
Object.defineProperty(exports, 'cronPeriod', {
|
|
415
|
+
enumerable: true,
|
|
416
|
+
get: function () {
|
|
417
|
+
return cronPeriod;
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
Object.defineProperty(exports, 'parseCron', {
|
|
421
|
+
enumerable: true,
|
|
422
|
+
get: function () {
|
|
423
|
+
return parseCron;
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
Object.defineProperty(exports, 'toAwsCron', {
|
|
427
|
+
enumerable: true,
|
|
428
|
+
get: function () {
|
|
429
|
+
return toAwsCron;
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
Object.defineProperty(exports, 'toUnixCron', {
|
|
433
|
+
enumerable: true,
|
|
434
|
+
get: function () {
|
|
435
|
+
return toUnixCron;
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
//# sourceMappingURL=cron-DXiVSeD6.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-DXiVSeD6.cjs","names":["expression: string","token: string","field?: CronField","field: CronField","rule: FieldRule","atom: string","field: string","isValid: (atom: string) => boolean","dialect: CronDialect","value: string","days: number[]","parts: string[]","from: CronDialect","fields: string[]","warnings: CronConversionWarning[]","date: Date","day: number","previousLast: number | undefined"],"sources":["../src/cron.ts"],"sourcesContent":["/**\n * Cron expressions in the two dialects a schedule runs under:\n *\n * - **Unix**, five fields: `cron(min hour day-of-month month day-of-week)`,\n * day-of-week 0–7 with SUN as 0 or 7. What `cron-parser` and pg-boss read.\n * - **AWS**, six fields: `cron(min hour day-of-month month day-of-week year)`,\n * day-of-week 1–7 with SUN as 1, `?` in exactly one day field, and `L`, `W`\n * and `#`. What EventBridge reads.\n *\n * The field count tells them apart. A seconds field is never accepted, so a\n * six-field expression is always AWS.\n */\n\nexport type CronDialect = 'unix' | 'aws';\n\nexport type CronField =\n\t| 'minute'\n\t| 'hour'\n\t| 'dayOfMonth'\n\t| 'month'\n\t| 'dayOfWeek'\n\t| 'year';\n\n/** A validated cron expression, split into its fields. */\nexport interface ParsedCron {\n\tdialect: CronDialect;\n\tminute: string;\n\thour: string;\n\tdayOfMonth: string;\n\tmonth: string;\n\tdayOfWeek: string;\n\t/** AWS only. */\n\tyear?: string;\n}\n\n/** A best-effort conversion that changed when the cron runs. */\nexport interface CronConversionWarning {\n\tcode: 'dayOfMonthDropped' | 'yearDropped';\n\tmessage: string;\n\t/** The token that was dropped. */\n\ttoken: string;\n}\n\nexport interface CronConversion {\n\texpression: string;\n\twarnings: CronConversionWarning[];\n}\n\n/**\n * The expression is not valid in its own dialect. `field` is absent when the\n * expression isn't `cron(…)` with five or six fields at all.\n */\nexport class InvalidCronExpressionError extends Error {\n\tconstructor(\n\t\treadonly expression: string,\n\t\treadonly token: string,\n\t\treadonly field?: CronField,\n\t) {\n\t\tsuper('Invalid cron expression', { cause: { expression, field, token } });\n\t\tthis.name = 'InvalidCronExpressionError';\n\t}\n}\n\n/** The expression is valid, but has no equivalent in the target dialect. */\nexport class UnconvertibleCronExpressionError extends Error {\n\tconstructor(\n\t\treadonly expression: string,\n\t\treadonly field: CronField,\n\t\treadonly token: string,\n\t) {\n\t\tsuper('Cron expression cannot be converted', {\n\t\t\tcause: { expression, field, token },\n\t\t});\n\t\tthis.name = 'UnconvertibleCronExpressionError';\n\t}\n}\n\nconst MONTHS = [\n\t'JAN',\n\t'FEB',\n\t'MAR',\n\t'APR',\n\t'MAY',\n\t'JUN',\n\t'JUL',\n\t'AUG',\n\t'SEP',\n\t'OCT',\n\t'NOV',\n\t'DEC',\n];\nconst DAYS = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'];\n\ninterface FieldRule {\n\tmin: number;\n\tmax: number;\n\t/** Names in order, the first being `min`. */\n\tnames?: readonly string[];\n}\n\nconst RULES = {\n\tminute: { min: 0, max: 59 },\n\thour: { min: 0, max: 23 },\n\tdayOfMonth: { min: 1, max: 31 },\n\tmonth: { min: 1, max: 12, names: MONTHS },\n\tunixDayOfWeek: { min: 0, max: 7, names: DAYS },\n\tawsDayOfWeek: { min: 1, max: 7, names: DAYS },\n} satisfies Record<string, FieldRule>;\n\n/** A number in range (one or two digits), or one of the field's names. */\nconst toValue = (token: string, rule: FieldRule): number | undefined => {\n\tconst named = rule.names?.indexOf(token) ?? -1;\n\tif (named >= 0) return rule.min + named;\n\tif (!/^\\d{1,2}$/.test(token)) return undefined;\n\tconst value = Number(token);\n\treturn value >= rule.min && value <= rule.max ? value : undefined;\n};\n\n/** `*`, `v` or `a-b`, with an optional `/step`. */\nconst isAtom = (atom: string, rule: FieldRule): boolean => {\n\tconst [base = '', step, ...rest] = atom.split('/');\n\tif (rest.length > 0) return false;\n\tif (step !== undefined && !/^\\d{1,2}$/.test(step)) return false;\n\tif (base === '*') return true;\n\tconst [from = '', to, ...more] = base.split('-');\n\tif (more.length > 0 || toValue(from, rule) === undefined) return false;\n\treturn to === undefined || toValue(to, rule) !== undefined;\n};\n\n/** The first atom of a comma-separated field that is invalid. */\nconst invalidAtom = (\n\tfield: string,\n\tisValid: (atom: string) => boolean,\n): string | undefined => field.split(',').find((atom) => !isValid(atom));\n\nconst isYear = (token: string) =>\n\t/^\\d{4}$/.test(token) && Number(token) >= 1970 && Number(token) <= 2199;\n\nconst isYearAtom = (atom: string): boolean => {\n\tconst [base = '', step, ...rest] = atom.split('/');\n\tif (rest.length > 0) return false;\n\tif (step !== undefined && !/^\\d{1,2}$/.test(step)) return false;\n\tif (base === '*') return true;\n\tconst [from = '', to, ...more] = base.split('-');\n\treturn more.length === 0 && isYear(from) && (to === undefined || isYear(to));\n};\n\n/** `L`, `L-n`, `LW` and `nW`, AWS day-of-month only, alone in the field. */\nconst isAwsDayOfMonthSpecial = (field: string) =>\n\tfield === 'L' ||\n\tfield === 'LW' ||\n\t/^L-\\d{1,2}$/.test(field) ||\n\t(field.endsWith('W') &&\n\t\ttoValue(field.slice(0, -1), RULES.dayOfMonth) !== undefined);\n\n/** `nL` and `n#k`, AWS day-of-week only, alone in the field. */\nconst isAwsDayOfWeekSpecial = (field: string) => {\n\tif (field.endsWith('L')) {\n\t\treturn toValue(field.slice(0, -1), RULES.awsDayOfWeek) !== undefined;\n\t}\n\tconst [day = '', nth, ...rest] = field.split('#');\n\treturn (\n\t\tnth !== undefined &&\n\t\trest.length === 0 &&\n\t\ttoValue(day, RULES.awsDayOfWeek) !== undefined &&\n\t\t/^[1-5]$/.test(nth)\n\t);\n};\n\n/**\n * Splits and validates a `cron(…)` expression in either dialect.\n *\n * @throws {InvalidCronExpressionError} naming the field and token that failed.\n */\nexport function parseCron(expression: string): ParsedCron {\n\tconst inner = /^cron\\((.*)\\)$/.exec(expression)?.[1];\n\tconst fields = inner?.split(' ') ?? [];\n\tif (fields.length !== 5 && fields.length !== 6) {\n\t\tthrow new InvalidCronExpressionError(expression, inner ?? expression);\n\t}\n\n\tconst [minute = '', hour = '', dayOfMonth = '', month = '', dayOfWeek = ''] =\n\t\tfields;\n\tconst year = fields[5];\n\tconst dialect: CronDialect = year === undefined ? 'unix' : 'aws';\n\tconst fail = (field: CronField, token: string): never => {\n\t\tthrow new InvalidCronExpressionError(expression, token, field);\n\t};\n\tconst check = (field: CronField, value: string, rule: FieldRule) => {\n\t\tconst atom = invalidAtom(value, (a) => isAtom(a, rule));\n\t\tif (atom !== undefined) fail(field, atom);\n\t};\n\n\tcheck('minute', minute, RULES.minute);\n\tcheck('hour', hour, RULES.hour);\n\tcheck('month', month, RULES.month);\n\n\tif (year === undefined) {\n\t\tcheck('dayOfMonth', dayOfMonth, RULES.dayOfMonth);\n\t\tcheck('dayOfWeek', dayOfWeek, RULES.unixDayOfWeek);\n\t\treturn { dialect, minute, hour, dayOfMonth, month, dayOfWeek };\n\t}\n\n\tif (dayOfMonth === '?' && dayOfWeek === '?') fail('dayOfWeek', '?');\n\tif (dayOfMonth !== '?' && dayOfWeek !== '?') fail('dayOfWeek', dayOfWeek);\n\tif (dayOfMonth !== '?' && !isAwsDayOfMonthSpecial(dayOfMonth)) {\n\t\tcheck('dayOfMonth', dayOfMonth, RULES.dayOfMonth);\n\t}\n\tif (dayOfWeek !== '?' && !isAwsDayOfWeekSpecial(dayOfWeek)) {\n\t\tcheck('dayOfWeek', dayOfWeek, RULES.awsDayOfWeek);\n\t}\n\tconst yearAtom = invalidAtom(year, isYearAtom);\n\tif (yearAtom !== undefined) fail('year', yearAtom);\n\n\treturn { dialect, minute, hour, dayOfMonth, month, dayOfWeek, year };\n}\n\n/** The values a plain field allows: values, ranges, steps and lists. */\nconst fieldValues = (field: string, rule: FieldRule): Set<number> => {\n\tconst values = new Set<number>();\n\tfor (const atom of field.split(',')) {\n\t\tconst [base = '', step] = atom.split('/');\n\t\tconst [from = '', to] = base.split('-');\n\t\tconst start = base === '*' ? rule.min : (toValue(from, rule) as number);\n\t\tconst end =\n\t\t\tto !== undefined\n\t\t\t\t? (toValue(to, rule) as number)\n\t\t\t\t: base === '*' || step !== undefined\n\t\t\t\t\t? rule.max\n\t\t\t\t\t: start;\n\t\tfor (let value = start; value <= end; value += Number(step ?? 1)) {\n\t\t\tvalues.add(value);\n\t\t}\n\t}\n\treturn values;\n};\n\n/**\n * The days a day-of-week field runs on, as Unix numbers 0–6 (SUN = 0).\n * Only for plain fields: values, ranges, steps and lists.\n */\nconst unixDays = (field: string, dialect: CronDialect): Set<number> => {\n\tconst rule = dialect === 'unix' ? RULES.unixDayOfWeek : RULES.awsDayOfWeek;\n\tconst days = new Set<number>();\n\tfor (const day of fieldValues(field, rule)) {\n\t\tdays.add(dialect === 'unix' ? day % 7 : day - 1);\n\t}\n\treturn days;\n};\n\n/** Days as a list, with runs of three or more written as ranges. */\nconst formatDays = (days: number[]): string => {\n\tconst parts: string[] = [];\n\tlet i = 0;\n\twhile (i < days.length) {\n\t\tlet j = i;\n\t\twhile (j + 1 < days.length && days[j + 1] === (days[j] as number) + 1) {\n\t\t\tj++;\n\t\t}\n\t\tparts.push(\n\t\t\tj - i >= 2 ? `${days[i]}-${days[j]}` : days.slice(i, j + 1).join(','),\n\t\t);\n\t\ti = j + 1;\n\t}\n\treturn parts.join(',');\n};\n\n/**\n * Rewrites a day-of-week field's numbers into the target dialect. Fields\n * written only with names and `*` mean the same in both and pass through.\n */\nconst convertDayOfWeek = (field: string, from: CronDialect): string => {\n\tif (!/\\d/.test(field)) return field;\n\tconst days = unixDays(field, from);\n\tif (days.size === 7) return '*';\n\tif (from === 'aws') return formatDays([...days].sort((a, b) => a - b));\n\t// SUN goes from first to last, so a week from MON reads in order.\n\treturn formatDays([...days].map((day) => day + 1).sort((a, b) => a - b));\n};\n\nconst format = (fields: string[]) => `cron(${fields.join(' ')})`;\n\n/**\n * Converts a cron expression to the six-field AWS form EventBridge reads. An\n * AWS expression is returned unchanged.\n *\n * Unix runs on either day field when both are restricted, and AWS can't\n * express that, so day-of-week is kept and day-of-month dropped with a\n * warning.\n *\n * @throws {InvalidCronExpressionError} when the expression is invalid.\n */\nexport function toAwsCron(expression: string): CronConversion {\n\tconst cron = parseCron(expression);\n\tif (cron.dialect === 'aws') return { expression, warnings: [] };\n\n\tconst { minute, hour, dayOfMonth, month, dayOfWeek } = cron;\n\tconst warnings: CronConversionWarning[] = [];\n\tif (dayOfMonth !== '*' && dayOfWeek !== '*') {\n\t\twarnings.push({\n\t\t\tcode: 'dayOfMonthDropped',\n\t\t\tmessage:\n\t\t\t\t'Both day fields are restricted, so day-of-month was dropped and the cron runs on fewer days',\n\t\t\ttoken: dayOfMonth,\n\t\t});\n\t}\n\n\tconst [awsDayOfMonth, awsDayOfWeek] =\n\t\tdayOfWeek === '*'\n\t\t\t? [dayOfMonth, '?']\n\t\t\t: ['?', convertDayOfWeek(dayOfWeek, 'unix')];\n\n\treturn {\n\t\texpression: format([minute, hour, awsDayOfMonth, month, awsDayOfWeek, '*']),\n\t\twarnings,\n\t};\n}\n\n/**\n * Converts a cron expression to the five-field Unix form `cron-parser` reads.\n * A Unix expression is returned unchanged.\n *\n * A specific year is dropped with a warning, so the cron runs every year.\n *\n * @throws {InvalidCronExpressionError} when the expression is invalid.\n * @throws {UnconvertibleCronExpressionError} for `W` and `L-n`, which Unix\n * has no equivalent for.\n */\nexport function toUnixCron(expression: string): CronConversion {\n\tconst cron = parseCron(expression);\n\tif (cron.dialect === 'unix') return { expression, warnings: [] };\n\n\tconst { minute, hour, dayOfMonth, month, dayOfWeek, year = '*' } = cron;\n\tconst warnings: CronConversionWarning[] = [];\n\tif (year !== '*') {\n\t\twarnings.push({\n\t\t\tcode: 'yearDropped',\n\t\t\tmessage: 'The year was dropped, so the cron runs every year',\n\t\t\ttoken: year,\n\t\t});\n\t}\n\n\tif (dayOfMonth.includes('W') || dayOfMonth.startsWith('L-')) {\n\t\tthrow new UnconvertibleCronExpressionError(\n\t\t\texpression,\n\t\t\t'dayOfMonth',\n\t\t\tdayOfMonth,\n\t\t);\n\t}\n\n\treturn {\n\t\texpression: format([\n\t\t\tminute,\n\t\t\thour,\n\t\t\tdayOfMonth === '?' ? '*' : dayOfMonth,\n\t\t\tmonth,\n\t\t\tconvertAwsDayOfWeek(dayOfWeek),\n\t\t]),\n\t\twarnings,\n\t};\n}\n\n/** `?` becomes `*`; `nL` and `n#k` keep their suffix with `n` shifted. */\nconst convertAwsDayOfWeek = (field: string): string => {\n\tif (field === '?') return '*';\n\tconst special = /^(\\w+?)(L|#[1-5])$/.exec(field);\n\tif (special) {\n\t\tconst [, day = '', suffix = ''] = special;\n\t\treturn `${convertDayOfWeek(day, 'aws')}${suffix}`;\n\t}\n\treturn convertDayOfWeek(field, 'aws');\n};\n\n/** The expression runs less than twice in the window, so has no period. */\nexport class CronPeriodError extends Error {\n\tconstructor(readonly expression: string) {\n\t\tsuper('Cron expression runs less than twice in eight years', {\n\t\t\tcause: { expression },\n\t\t});\n\t\tthis.name = 'CronPeriodError';\n\t}\n}\n\nconst MINUTE = 60;\nconst DAY = 24 * 60 * MINUTE;\n\n/** 2024 to 2031: every weekday and month combination, and two leap years. */\nconst PERIOD_START = Date.UTC(2024, 0, 1);\nconst PERIOD_DAYS = 8 * 365 + 2;\n\n/**\n * Whether a date in UTC matches an AWS day-of-month field, including `L`,\n * `L-n`, `LW` and `nW`.\n */\nconst dayOfMonthMatcher = (field: string): ((date: Date) => boolean) => {\n\tif (field === '?') return () => true;\n\tconst lastDay = (date: Date) =>\n\t\tnew Date(\n\t\t\tDate.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0),\n\t\t).getUTCDate();\n\t// The weekday nearest `day`, without leaving the month.\n\tconst nearestWeekday = (date: Date, day: number) => {\n\t\tconst last = lastDay(date);\n\t\tconst weekday = new Date(\n\t\t\tDate.UTC(date.getUTCFullYear(), date.getUTCMonth(), day),\n\t\t).getUTCDay();\n\t\tif (weekday === 6) return day === 1 ? 3 : day - 1;\n\t\tif (weekday === 0) return day === last ? day - 2 : day + 1;\n\t\treturn day;\n\t};\n\n\tif (field === 'L') return (date) => date.getUTCDate() === lastDay(date);\n\tif (field.startsWith('L-')) {\n\t\tconst offset = Number(field.slice(2));\n\t\treturn (date) => date.getUTCDate() === lastDay(date) - offset;\n\t}\n\tif (field === 'LW') {\n\t\treturn (date) => date.getUTCDate() === nearestWeekday(date, lastDay(date));\n\t}\n\tif (field.endsWith('W')) {\n\t\tconst day = Number(field.slice(0, -1));\n\t\treturn (date) =>\n\t\t\tday <= lastDay(date) && date.getUTCDate() === nearestWeekday(date, day);\n\t}\n\tconst days = fieldValues(field, RULES.dayOfMonth);\n\treturn (date) => days.has(date.getUTCDate());\n};\n\n/** Whether a date in UTC matches an AWS day-of-week field, including `nL` and `n#k`. */\nconst dayOfWeekMatcher = (field: string): ((date: Date) => boolean) => {\n\tif (field === '?') return () => true;\n\tconst special = /^(\\w+?)(L|#([1-5]))$/.exec(field);\n\tif (special) {\n\t\tconst [, day = '', , nth] = special;\n\t\tconst weekday = (toValue(day, RULES.awsDayOfWeek) as number) - 1;\n\t\treturn (date) => {\n\t\t\tif (date.getUTCDay() !== weekday) return false;\n\t\t\tif (nth !== undefined) {\n\t\t\t\treturn Math.ceil(date.getUTCDate() / 7) === Number(nth);\n\t\t\t}\n\t\t\t// The last one: a week later is next month.\n\t\t\treturn new Date(date.getTime() + 7 * DAY * 1000).getUTCDate() <= 7;\n\t\t};\n\t}\n\tconst days = unixDays(field, 'aws');\n\treturn (date) => days.has(date.getUTCDay());\n};\n\n/**\n * The longest gap between two runs of a cron expression, in seconds: the\n * period a heartbeat should expect. A weekdays-only cron has the Friday to\n * Monday gap, so its heartbeat doesn't alert at the weekend.\n *\n * The expression is first converted to the AWS form, so the period is of\n * what EventBridge runs. Runs are worked out in UTC over 2024–2031, and the\n * year field is ignored.\n *\n * @throws {InvalidCronExpressionError} when the expression is invalid.\n * @throws {CronPeriodError} when it runs less than twice in that time.\n */\nexport function cronPeriod(expression: string): number {\n\tconst cron = parseCron(toAwsCron(expression).expression);\n\tconst minutes = [...fieldValues(cron.minute, RULES.minute)];\n\tconst hours = [...fieldValues(cron.hour, RULES.hour)];\n\tconst months = fieldValues(cron.month, RULES.month);\n\tconst matchesDayOfMonth = dayOfMonthMatcher(cron.dayOfMonth);\n\tconst matchesDayOfWeek = dayOfWeekMatcher(cron.dayOfWeek);\n\n\t// Every matching day runs at the same times, so only the gaps within a\n\t// day and from one day's last run to the next day's first can differ.\n\tconst times = hours\n\t\t.flatMap((hour) => minutes.map((minute) => (hour * 60 + minute) * MINUTE))\n\t\t.sort((a, b) => a - b);\n\tconst first = times[0] as number;\n\tconst last = times[times.length - 1] as number;\n\n\tlet longest = 0;\n\tfor (let i = 1; i < times.length; i++) {\n\t\tlongest = Math.max(\n\t\t\tlongest,\n\t\t\t(times[i] as number) - (times[i - 1] as number),\n\t\t);\n\t}\n\n\tlet runs = 0;\n\tlet previousLast: number | undefined;\n\tfor (let day = 0; day < PERIOD_DAYS; day++) {\n\t\tconst date = new Date(PERIOD_START + day * DAY * 1000);\n\t\tif (!months.has(date.getUTCMonth() + 1)) continue;\n\t\tif (!matchesDayOfMonth(date) || !matchesDayOfWeek(date)) continue;\n\n\t\tconst start = date.getTime() / 1000;\n\t\tif (previousLast !== undefined) {\n\t\t\tlongest = Math.max(longest, start + first - previousLast);\n\t\t}\n\t\tpreviousLast = start + last;\n\t\truns += times.length;\n\t}\n\n\tif (runs < 2) throw new CronPeriodError(expression);\n\treturn longest;\n}\n"],"mappings":";;;;;;AAoDA,IAAa,6BAAb,cAAgD,MAAM;CACrD,YACUA,YACAC,OACAC,OACR;AACD,QAAM,2BAA2B,EAAE,OAAO;GAAE;GAAY;GAAO;EAAO,EAAE,EAAC;EAJhE;EACA;EACA;AAGT,OAAK,OAAO;CACZ;AACD;;AAGD,IAAa,mCAAb,cAAsD,MAAM;CAC3D,YACUF,YACAG,OACAF,OACR;AACD,QAAM,uCAAuC,EAC5C,OAAO;GAAE;GAAY;GAAO;EAAO,EACnC,EAAC;EANO;EACA;EACA;AAKT,OAAK,OAAO;CACZ;AACD;AAED,MAAM,SAAS;CACd;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACA;AACD,MAAM,OAAO;CAAC;CAAO;CAAO;CAAO;CAAO;CAAO;CAAO;AAAM;AAS9D,MAAM,QAAQ;CACb,QAAQ;EAAE,KAAK;EAAG,KAAK;CAAI;CAC3B,MAAM;EAAE,KAAK;EAAG,KAAK;CAAI;CACzB,YAAY;EAAE,KAAK;EAAG,KAAK;CAAI;CAC/B,OAAO;EAAE,KAAK;EAAG,KAAK;EAAI,OAAO;CAAQ;CACzC,eAAe;EAAE,KAAK;EAAG,KAAK;EAAG,OAAO;CAAM;CAC9C,cAAc;EAAE,KAAK;EAAG,KAAK;EAAG,OAAO;CAAM;AAC7C;;AAGD,MAAM,UAAU,CAACA,OAAeG,SAAwC;CACvE,MAAM,QAAQ,KAAK,OAAO,QAAQ,MAAM,IAAI;AAC5C,KAAI,SAAS,EAAG,QAAO,KAAK,MAAM;AAClC,MAAK,YAAY,KAAK,MAAM,CAAE;CAC9B,MAAM,QAAQ,OAAO,MAAM;AAC3B,QAAO,SAAS,KAAK,OAAO,SAAS,KAAK,MAAM;AAChD;;AAGD,MAAM,SAAS,CAACC,MAAcD,SAA6B;CAC1D,MAAM,CAAC,OAAO,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK,MAAM,IAAI;AAClD,KAAI,KAAK,SAAS,EAAG,QAAO;AAC5B,KAAI,oBAAuB,YAAY,KAAK,KAAK,CAAE,QAAO;AAC1D,KAAI,SAAS,IAAK,QAAO;CACzB,MAAM,CAAC,OAAO,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK,MAAM,IAAI;AAChD,KAAI,KAAK,SAAS,KAAK,QAAQ,MAAM,KAAK,YAAgB,QAAO;AACjE,QAAO,iBAAoB,QAAQ,IAAI,KAAK;AAC5C;;AAGD,MAAM,cAAc,CACnBE,OACAC,YACwB,MAAM,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,QAAQ,KAAK,CAAC;AAExE,MAAM,SAAS,CAACN,UACf,UAAU,KAAK,MAAM,IAAI,OAAO,MAAM,IAAI,QAAQ,OAAO,MAAM,IAAI;AAEpE,MAAM,aAAa,CAACI,SAA0B;CAC7C,MAAM,CAAC,OAAO,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK,MAAM,IAAI;AAClD,KAAI,KAAK,SAAS,EAAG,QAAO;AAC5B,KAAI,oBAAuB,YAAY,KAAK,KAAK,CAAE,QAAO;AAC1D,KAAI,SAAS,IAAK,QAAO;CACzB,MAAM,CAAC,OAAO,IAAI,IAAI,GAAG,KAAK,GAAG,KAAK,MAAM,IAAI;AAChD,QAAO,KAAK,WAAW,KAAK,OAAO,KAAK,KAAK,iBAAoB,OAAO,GAAG;AAC3E;;AAGD,MAAM,yBAAyB,CAACC,UAC/B,UAAU,OACV,UAAU,QACV,cAAc,KAAK,MAAM,IACxB,MAAM,SAAS,IAAI,IACnB,QAAQ,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,WAAW;;AAG/C,MAAM,wBAAwB,CAACA,UAAkB;AAChD,KAAI,MAAM,SAAS,IAAI,CACtB,QAAO,QAAQ,MAAM,MAAM,GAAG,GAAG,EAAE,MAAM,aAAa;CAEvD,MAAM,CAAC,MAAM,IAAI,KAAK,GAAG,KAAK,GAAG,MAAM,MAAM,IAAI;AACjD,QACC,kBACA,KAAK,WAAW,KAChB,QAAQ,KAAK,MAAM,aAAa,eAChC,UAAU,KAAK,IAAI;AAEpB;;;;;;AAOD,SAAgB,UAAUN,YAAgC;CACzD,MAAM,QAAQ,iBAAiB,KAAK,WAAW,GAAG;CAClD,MAAM,SAAS,OAAO,MAAM,IAAI,IAAI,CAAE;AACtC,KAAI,OAAO,WAAW,KAAK,OAAO,WAAW,EAC5C,OAAM,IAAI,2BAA2B,YAAY,SAAS;CAG3D,MAAM,CAAC,SAAS,IAAI,OAAO,IAAI,aAAa,IAAI,QAAQ,IAAI,YAAY,GAAG,GAC1E;CACD,MAAM,OAAO,OAAO;CACpB,MAAMQ,UAAuB,kBAAqB,SAAS;CAC3D,MAAM,OAAO,CAACL,OAAkBF,UAAyB;AACxD,QAAM,IAAI,2BAA2B,YAAY,OAAO;CACxD;CACD,MAAM,QAAQ,CAACE,OAAkBM,OAAeL,SAAoB;EACnE,MAAM,OAAO,YAAY,OAAO,CAAC,MAAM,OAAO,GAAG,KAAK,CAAC;AACvD,MAAI,gBAAoB,MAAK,OAAO,KAAK;CACzC;AAED,OAAM,UAAU,QAAQ,MAAM,OAAO;AACrC,OAAM,QAAQ,MAAM,MAAM,KAAK;AAC/B,OAAM,SAAS,OAAO,MAAM,MAAM;AAElC,KAAI,iBAAoB;AACvB,QAAM,cAAc,YAAY,MAAM,WAAW;AACjD,QAAM,aAAa,WAAW,MAAM,cAAc;AAClD,SAAO;GAAE;GAAS;GAAQ;GAAM;GAAY;GAAO;EAAW;CAC9D;AAED,KAAI,eAAe,OAAO,cAAc,IAAK,MAAK,aAAa,IAAI;AACnE,KAAI,eAAe,OAAO,cAAc,IAAK,MAAK,aAAa,UAAU;AACzE,KAAI,eAAe,QAAQ,uBAAuB,WAAW,CAC5D,OAAM,cAAc,YAAY,MAAM,WAAW;AAElD,KAAI,cAAc,QAAQ,sBAAsB,UAAU,CACzD,OAAM,aAAa,WAAW,MAAM,aAAa;CAElD,MAAM,WAAW,YAAY,MAAM,WAAW;AAC9C,KAAI,oBAAwB,MAAK,QAAQ,SAAS;AAElD,QAAO;EAAE;EAAS;EAAQ;EAAM;EAAY;EAAO;EAAW;CAAM;AACpE;;AAGD,MAAM,cAAc,CAACE,OAAeF,SAAiC;CACpE,MAAM,yBAAS,IAAI;AACnB,MAAK,MAAM,QAAQ,MAAM,MAAM,IAAI,EAAE;EACpC,MAAM,CAAC,OAAO,IAAI,KAAK,GAAG,KAAK,MAAM,IAAI;EACzC,MAAM,CAAC,OAAO,IAAI,GAAG,GAAG,KAAK,MAAM,IAAI;EACvC,MAAM,QAAQ,SAAS,MAAM,KAAK,MAAO,QAAQ,MAAM,KAAK;EAC5D,MAAM,MACL,gBACI,QAAQ,IAAI,KAAK,GAClB,SAAS,OAAO,kBACf,KAAK,MACL;AACL,OAAK,IAAI,QAAQ,OAAO,SAAS,KAAK,SAAS,OAAO,QAAQ,EAAE,CAC/D,QAAO,IAAI,MAAM;CAElB;AACD,QAAO;AACP;;;;;AAMD,MAAM,WAAW,CAACE,OAAeE,YAAsC;CACtE,MAAM,OAAO,YAAY,SAAS,MAAM,gBAAgB,MAAM;CAC9D,MAAM,uBAAO,IAAI;AACjB,MAAK,MAAM,OAAO,YAAY,OAAO,KAAK,CACzC,MAAK,IAAI,YAAY,SAAS,MAAM,IAAI,MAAM,EAAE;AAEjD,QAAO;AACP;;AAGD,MAAM,aAAa,CAACE,SAA2B;CAC9C,MAAMC,QAAkB,CAAE;CAC1B,IAAI,IAAI;AACR,QAAO,IAAI,KAAK,QAAQ;EACvB,IAAI,IAAI;AACR,SAAO,IAAI,IAAI,KAAK,UAAU,KAAK,IAAI,OAAQ,KAAK,KAAgB,EACnE;AAED,QAAM,KACL,IAAI,KAAK,KAAK,EAAE,KAAK,GAAG,GAAG,KAAK,GAAG,IAAI,KAAK,MAAM,GAAG,IAAI,EAAE,CAAC,KAAK,IAAI,CACrE;AACD,MAAI,IAAI;CACR;AACD,QAAO,MAAM,KAAK,IAAI;AACtB;;;;;AAMD,MAAM,mBAAmB,CAACL,OAAeM,SAA8B;AACtE,MAAK,KAAK,KAAK,MAAM,CAAE,QAAO;CAC9B,MAAM,OAAO,SAAS,OAAO,KAAK;AAClC,KAAI,KAAK,SAAS,EAAG,QAAO;AAC5B,KAAI,SAAS,MAAO,QAAO,WAAW,CAAC,GAAG,IAAK,EAAC,KAAK,CAAC,GAAG,MAAM,IAAI,EAAE,CAAC;AAEtE,QAAO,WAAW,CAAC,GAAG,IAAK,EAAC,IAAI,CAAC,QAAQ,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,EAAE,CAAC;AACxE;AAED,MAAM,SAAS,CAACC,YAAsB,OAAO,OAAO,KAAK,IAAI,CAAC;;;;;;;;;;;AAY9D,SAAgB,UAAUb,YAAoC;CAC7D,MAAM,OAAO,UAAU,WAAW;AAClC,KAAI,KAAK,YAAY,MAAO,QAAO;EAAE;EAAY,UAAU,CAAE;CAAE;CAE/D,MAAM,EAAE,QAAQ,MAAM,YAAY,OAAO,WAAW,GAAG;CACvD,MAAMc,WAAoC,CAAE;AAC5C,KAAI,eAAe,OAAO,cAAc,IACvC,UAAS,KAAK;EACb,MAAM;EACN,SACC;EACD,OAAO;CACP,EAAC;CAGH,MAAM,CAAC,eAAe,aAAa,GAClC,cAAc,MACX,CAAC,YAAY,GAAI,IACjB,CAAC,KAAK,iBAAiB,WAAW,OAAO,AAAC;AAE9C,QAAO;EACN,YAAY,OAAO;GAAC;GAAQ;GAAM;GAAe;GAAO;GAAc;EAAI,EAAC;EAC3E;CACA;AACD;;;;;;;;;;;AAYD,SAAgB,WAAWd,YAAoC;CAC9D,MAAM,OAAO,UAAU,WAAW;AAClC,KAAI,KAAK,YAAY,OAAQ,QAAO;EAAE;EAAY,UAAU,CAAE;CAAE;CAEhE,MAAM,EAAE,QAAQ,MAAM,YAAY,OAAO,WAAW,OAAO,KAAK,GAAG;CACnE,MAAMc,WAAoC,CAAE;AAC5C,KAAI,SAAS,IACZ,UAAS,KAAK;EACb,MAAM;EACN,SAAS;EACT,OAAO;CACP,EAAC;AAGH,KAAI,WAAW,SAAS,IAAI,IAAI,WAAW,WAAW,KAAK,CAC1D,OAAM,IAAI,iCACT,YACA,cACA;AAIF,QAAO;EACN,YAAY,OAAO;GAClB;GACA;GACA,eAAe,MAAM,MAAM;GAC3B;GACA,oBAAoB,UAAU;EAC9B,EAAC;EACF;CACA;AACD;;AAGD,MAAM,sBAAsB,CAACR,UAA0B;AACtD,KAAI,UAAU,IAAK,QAAO;CAC1B,MAAM,UAAU,qBAAqB,KAAK,MAAM;AAChD,KAAI,SAAS;EACZ,MAAM,GAAG,MAAM,IAAI,SAAS,GAAG,GAAG;AAClC,UAAQ,EAAE,iBAAiB,KAAK,MAAM,CAAC,EAAE,OAAO;CAChD;AACD,QAAO,iBAAiB,OAAO,MAAM;AACrC;;AAGD,IAAa,kBAAb,cAAqC,MAAM;CAC1C,YAAqBN,YAAoB;AACxC,QAAM,uDAAuD,EAC5D,OAAO,EAAE,WAAY,EACrB,EAAC;EAHkB;AAIpB,OAAK,OAAO;CACZ;AACD;AAED,MAAM,SAAS;AACf,MAAM,MAAM,KAAK,KAAK;;AAGtB,MAAM,eAAe,KAAK,IAAI,MAAM,GAAG,EAAE;AACzC,MAAM,cAAc;;;;;AAMpB,MAAM,oBAAoB,CAACM,UAA6C;AACvE,KAAI,UAAU,IAAK,QAAO,MAAM;CAChC,MAAM,UAAU,CAACS,SAChB,IAAI,KACH,KAAK,IAAI,KAAK,gBAAgB,EAAE,KAAK,aAAa,GAAG,GAAG,EAAE,EACzD,YAAY;CAEf,MAAM,iBAAiB,CAACA,MAAYC,QAAgB;EACnD,MAAM,OAAO,QAAQ,KAAK;EAC1B,MAAM,UAAU,IAAI,KACnB,KAAK,IAAI,KAAK,gBAAgB,EAAE,KAAK,aAAa,EAAE,IAAI,EACvD,WAAW;AACb,MAAI,YAAY,EAAG,QAAO,QAAQ,IAAI,IAAI,MAAM;AAChD,MAAI,YAAY,EAAG,QAAO,QAAQ,OAAO,MAAM,IAAI,MAAM;AACzD,SAAO;CACP;AAED,KAAI,UAAU,IAAK,QAAO,CAAC,SAAS,KAAK,YAAY,KAAK,QAAQ,KAAK;AACvE,KAAI,MAAM,WAAW,KAAK,EAAE;EAC3B,MAAM,SAAS,OAAO,MAAM,MAAM,EAAE,CAAC;AACrC,SAAO,CAAC,SAAS,KAAK,YAAY,KAAK,QAAQ,KAAK,GAAG;CACvD;AACD,KAAI,UAAU,KACb,QAAO,CAAC,SAAS,KAAK,YAAY,KAAK,eAAe,MAAM,QAAQ,KAAK,CAAC;AAE3E,KAAI,MAAM,SAAS,IAAI,EAAE;EACxB,MAAM,MAAM,OAAO,MAAM,MAAM,GAAG,GAAG,CAAC;AACtC,SAAO,CAAC,SACP,OAAO,QAAQ,KAAK,IAAI,KAAK,YAAY,KAAK,eAAe,MAAM,IAAI;CACxE;CACD,MAAM,OAAO,YAAY,OAAO,MAAM,WAAW;AACjD,QAAO,CAAC,SAAS,KAAK,IAAI,KAAK,YAAY,CAAC;AAC5C;;AAGD,MAAM,mBAAmB,CAACV,UAA6C;AACtE,KAAI,UAAU,IAAK,QAAO,MAAM;CAChC,MAAM,UAAU,uBAAuB,KAAK,MAAM;AAClD,KAAI,SAAS;EACZ,MAAM,GAAG,MAAM,MAAM,IAAI,GAAG;EAC5B,MAAM,UAAW,QAAQ,KAAK,MAAM,aAAa,GAAc;AAC/D,SAAO,CAAC,SAAS;AAChB,OAAI,KAAK,WAAW,KAAK,QAAS,QAAO;AACzC,OAAI,eACH,QAAO,KAAK,KAAK,KAAK,YAAY,GAAG,EAAE,KAAK,OAAO,IAAI;AAGxD,UAAO,IAAI,KAAK,KAAK,SAAS,GAAG,IAAI,MAAM,KAAM,YAAY,IAAI;EACjE;CACD;CACD,MAAM,OAAO,SAAS,OAAO,MAAM;AACnC,QAAO,CAAC,SAAS,KAAK,IAAI,KAAK,WAAW,CAAC;AAC3C;;;;;;;;;;;;;AAcD,SAAgB,WAAWN,YAA4B;CACtD,MAAM,OAAO,UAAU,UAAU,WAAW,CAAC,WAAW;CACxD,MAAM,UAAU,CAAC,GAAG,YAAY,KAAK,QAAQ,MAAM,OAAO,AAAC;CAC3D,MAAM,QAAQ,CAAC,GAAG,YAAY,KAAK,MAAM,MAAM,KAAK,AAAC;CACrD,MAAM,SAAS,YAAY,KAAK,OAAO,MAAM,MAAM;CACnD,MAAM,oBAAoB,kBAAkB,KAAK,WAAW;CAC5D,MAAM,mBAAmB,iBAAiB,KAAK,UAAU;CAIzD,MAAM,QAAQ,MACZ,QAAQ,CAAC,SAAS,QAAQ,IAAI,CAAC,YAAY,OAAO,KAAK,UAAU,OAAO,CAAC,CACzE,KAAK,CAAC,GAAG,MAAM,IAAI,EAAE;CACvB,MAAM,QAAQ,MAAM;CACpB,MAAM,OAAO,MAAM,MAAM,SAAS;CAElC,IAAI,UAAU;AACd,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,IACjC,WAAU,KAAK,IACd,SACC,MAAM,KAAiB,MAAM,IAAI,GAClC;CAGF,IAAI,OAAO;CACX,IAAIiB;AACJ,MAAK,IAAI,MAAM,GAAG,MAAM,aAAa,OAAO;EAC3C,MAAM,OAAO,IAAI,KAAK,eAAe,MAAM,MAAM;AACjD,OAAK,OAAO,IAAI,KAAK,aAAa,GAAG,EAAE,CAAE;AACzC,OAAK,kBAAkB,KAAK,KAAK,iBAAiB,KAAK,CAAE;EAEzD,MAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,MAAI,wBACH,WAAU,KAAK,IAAI,SAAS,QAAQ,QAAQ,aAAa;AAE1D,iBAAe,QAAQ;AACvB,UAAQ,MAAM;CACd;AAED,KAAI,OAAO,EAAG,OAAM,IAAI,gBAAgB;AACxC,QAAO;AACP"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
//#region src/cron.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Cron expressions in the two dialects a schedule runs under:
|
|
4
|
+
*
|
|
5
|
+
* - **Unix**, five fields: `cron(min hour day-of-month month day-of-week)`,
|
|
6
|
+
* day-of-week 0–7 with SUN as 0 or 7. What `cron-parser` and pg-boss read.
|
|
7
|
+
* - **AWS**, six fields: `cron(min hour day-of-month month day-of-week year)`,
|
|
8
|
+
* day-of-week 1–7 with SUN as 1, `?` in exactly one day field, and `L`, `W`
|
|
9
|
+
* and `#`. What EventBridge reads.
|
|
10
|
+
*
|
|
11
|
+
* The field count tells them apart. A seconds field is never accepted, so a
|
|
12
|
+
* six-field expression is always AWS.
|
|
13
|
+
*/
|
|
14
|
+
type CronDialect = 'unix' | 'aws';
|
|
15
|
+
type CronField = 'minute' | 'hour' | 'dayOfMonth' | 'month' | 'dayOfWeek' | 'year';
|
|
16
|
+
/** A validated cron expression, split into its fields. */
|
|
17
|
+
interface ParsedCron {
|
|
18
|
+
dialect: CronDialect;
|
|
19
|
+
minute: string;
|
|
20
|
+
hour: string;
|
|
21
|
+
dayOfMonth: string;
|
|
22
|
+
month: string;
|
|
23
|
+
dayOfWeek: string;
|
|
24
|
+
/** AWS only. */
|
|
25
|
+
year?: string;
|
|
26
|
+
}
|
|
27
|
+
/** A best-effort conversion that changed when the cron runs. */
|
|
28
|
+
interface CronConversionWarning {
|
|
29
|
+
code: 'dayOfMonthDropped' | 'yearDropped';
|
|
30
|
+
message: string;
|
|
31
|
+
/** The token that was dropped. */
|
|
32
|
+
token: string;
|
|
33
|
+
}
|
|
34
|
+
interface CronConversion {
|
|
35
|
+
expression: string;
|
|
36
|
+
warnings: CronConversionWarning[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The expression is not valid in its own dialect. `field` is absent when the
|
|
40
|
+
* expression isn't `cron(…)` with five or six fields at all.
|
|
41
|
+
*/
|
|
42
|
+
declare class InvalidCronExpressionError extends Error {
|
|
43
|
+
readonly expression: string;
|
|
44
|
+
readonly token: string;
|
|
45
|
+
readonly field?: CronField | undefined;
|
|
46
|
+
constructor(expression: string, token: string, field?: CronField | undefined);
|
|
47
|
+
}
|
|
48
|
+
/** The expression is valid, but has no equivalent in the target dialect. */
|
|
49
|
+
declare class UnconvertibleCronExpressionError extends Error {
|
|
50
|
+
readonly expression: string;
|
|
51
|
+
readonly field: CronField;
|
|
52
|
+
readonly token: string;
|
|
53
|
+
constructor(expression: string, field: CronField, token: string);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Splits and validates a `cron(…)` expression in either dialect.
|
|
57
|
+
*
|
|
58
|
+
* @throws {InvalidCronExpressionError} naming the field and token that failed.
|
|
59
|
+
*/
|
|
60
|
+
declare function parseCron(expression: string): ParsedCron;
|
|
61
|
+
/**
|
|
62
|
+
* Converts a cron expression to the six-field AWS form EventBridge reads. An
|
|
63
|
+
* AWS expression is returned unchanged.
|
|
64
|
+
*
|
|
65
|
+
* Unix runs on either day field when both are restricted, and AWS can't
|
|
66
|
+
* express that, so day-of-week is kept and day-of-month dropped with a
|
|
67
|
+
* warning.
|
|
68
|
+
*
|
|
69
|
+
* @throws {InvalidCronExpressionError} when the expression is invalid.
|
|
70
|
+
*/
|
|
71
|
+
declare function toAwsCron(expression: string): CronConversion;
|
|
72
|
+
/**
|
|
73
|
+
* Converts a cron expression to the five-field Unix form `cron-parser` reads.
|
|
74
|
+
* A Unix expression is returned unchanged.
|
|
75
|
+
*
|
|
76
|
+
* A specific year is dropped with a warning, so the cron runs every year.
|
|
77
|
+
*
|
|
78
|
+
* @throws {InvalidCronExpressionError} when the expression is invalid.
|
|
79
|
+
* @throws {UnconvertibleCronExpressionError} for `W` and `L-n`, which Unix
|
|
80
|
+
* has no equivalent for.
|
|
81
|
+
*/
|
|
82
|
+
declare function toUnixCron(expression: string): CronConversion;
|
|
83
|
+
/** The expression runs less than twice in the window, so has no period. */
|
|
84
|
+
declare class CronPeriodError extends Error {
|
|
85
|
+
readonly expression: string;
|
|
86
|
+
constructor(expression: string);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The longest gap between two runs of a cron expression, in seconds: the
|
|
90
|
+
* period a heartbeat should expect. A weekdays-only cron has the Friday to
|
|
91
|
+
* Monday gap, so its heartbeat doesn't alert at the weekend.
|
|
92
|
+
*
|
|
93
|
+
* The expression is first converted to the AWS form, so the period is of
|
|
94
|
+
* what EventBridge runs. Runs are worked out in UTC over 2024–2031, and the
|
|
95
|
+
* year field is ignored.
|
|
96
|
+
*
|
|
97
|
+
* @throws {InvalidCronExpressionError} when the expression is invalid.
|
|
98
|
+
* @throws {CronPeriodError} when it runs less than twice in that time.
|
|
99
|
+
*/
|
|
100
|
+
declare function cronPeriod(expression: string): number;
|
|
101
|
+
//# sourceMappingURL=cron.d.ts.map
|
|
102
|
+
//#endregion
|
|
103
|
+
export { CronConversion, CronConversionWarning, CronDialect, CronField, CronPeriodError, InvalidCronExpressionError, ParsedCron, UnconvertibleCronExpressionError, cronPeriod, parseCron, toAwsCron, toUnixCron };
|
|
104
|
+
//# sourceMappingURL=cron-DlCX5PWN.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-DlCX5PWN.d.mts","names":[],"sources":["../src/cron.ts"],"sourcesContent":[],"mappings":";;AAaA;AAEA;AASA;AAYA;AAOA;AASA;;;;;AAAqD;AAYxC,KAnDD,WAAA,GAmDC,MAAA,GAAA,KAAiC;AAAA,KAjDlC,SAAA,GAiDkC,QAAA,GAAA,MAAA,GAAA,YAAA,GAAA,OAAA,GAAA,WAAA,GAAA,MAAA;;AAG5B,UA3CD,UAAA,CA2CC;EAAS,OAH2B,EAvC5C,WAuC4C;EAAK,MAAA,EAAA,MAAA;EA8G3C,IAAA,EAAA,MAAS;EAsHT,UAAA,EAAS,MAAA;EAoCT,KAAA,EAAA,MAAU;EA8Cb,SAAA,EAAA,MAAA;EAsFG;;;;UAxaC,qBAAA;;;;;;UAOA,cAAA;;YAEN;;;;;;cAOE,0BAAA,SAAmC,KAAA;;;mBAI7B;yDAAA;;;cAQN,gCAAA,SAAyC,KAAA;;kBAGpC;;yCAAA;;;;;;;iBA2GF,SAAA,sBAA+B;;;;;;;;;;;iBAsH/B,SAAA,sBAA+B;;;;;;;;;;;iBAoC/B,UAAA,sBAAgC;;cA8CnC,eAAA,SAAwB,KAAK;;;;;;;;;;;;;;;;iBAsF1B,UAAA"}
|
package/dist/cron.cjs
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const require_cron = require('./cron-DXiVSeD6.cjs');
|
|
2
|
+
|
|
3
|
+
exports.CronPeriodError = require_cron.CronPeriodError;
|
|
4
|
+
exports.InvalidCronExpressionError = require_cron.InvalidCronExpressionError;
|
|
5
|
+
exports.UnconvertibleCronExpressionError = require_cron.UnconvertibleCronExpressionError;
|
|
6
|
+
exports.cronPeriod = require_cron.cronPeriod;
|
|
7
|
+
exports.parseCron = require_cron.parseCron;
|
|
8
|
+
exports.toAwsCron = require_cron.toAwsCron;
|
|
9
|
+
exports.toUnixCron = require_cron.toUnixCron;
|
package/dist/cron.d.cts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { CronConversion, CronConversionWarning, CronDialect, CronField, CronPeriodError, InvalidCronExpressionError, ParsedCron, UnconvertibleCronExpressionError, cronPeriod, parseCron, toAwsCron, toUnixCron } from "./cron-CjhmidCo.cjs";
|
|
2
|
+
export { CronConversion, CronConversionWarning, CronDialect, CronField, CronPeriodError, InvalidCronExpressionError, ParsedCron, UnconvertibleCronExpressionError, cronPeriod, parseCron, toAwsCron, toUnixCron };
|
package/dist/cron.d.mts
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { CronConversion, CronConversionWarning, CronDialect, CronField, CronPeriodError, InvalidCronExpressionError, ParsedCron, UnconvertibleCronExpressionError, cronPeriod, parseCron, toAwsCron, toUnixCron } from "./cron-DlCX5PWN.mjs";
|
|
2
|
+
export { CronConversion, CronConversionWarning, CronDialect, CronField, CronPeriodError, InvalidCronExpressionError, ParsedCron, UnconvertibleCronExpressionError, cronPeriod, parseCron, toAwsCron, toUnixCron };
|
package/dist/cron.mjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { CronPeriodError, InvalidCronExpressionError, UnconvertibleCronExpressionError, cronPeriod, parseCron, toAwsCron, toUnixCron } from "./cron-DC4hQ1oa.mjs";
|
|
2
|
+
|
|
3
|
+
export { CronPeriodError, InvalidCronExpressionError, UnconvertibleCronExpressionError, cronPeriod, parseCron, toAwsCron, toUnixCron };
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const require_cron = require('./cron-DXiVSeD6.cjs');
|
|
1
2
|
|
|
2
3
|
//#region src/index.ts
|
|
3
4
|
/** Flatten a manifest field (array or partitioned) into a plain array. */
|
|
@@ -7,5 +8,12 @@ function flattenManifestField(field) {
|
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
//#endregion
|
|
11
|
+
exports.CronPeriodError = require_cron.CronPeriodError;
|
|
12
|
+
exports.InvalidCronExpressionError = require_cron.InvalidCronExpressionError;
|
|
13
|
+
exports.UnconvertibleCronExpressionError = require_cron.UnconvertibleCronExpressionError;
|
|
14
|
+
exports.cronPeriod = require_cron.cronPeriod;
|
|
10
15
|
exports.flattenManifestField = flattenManifestField;
|
|
16
|
+
exports.parseCron = require_cron.parseCron;
|
|
17
|
+
exports.toAwsCron = require_cron.toAwsCron;
|
|
18
|
+
exports.toUnixCron = require_cron.toUnixCron;
|
|
11
19
|
//# sourceMappingURL=index.cjs.map
|