@cloudsnorkel/cdk-github-runners 0.14.23 → 0.15.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.
Files changed (139) hide show
  1. package/.jsii +5397 -252
  2. package/API.md +1048 -24
  3. package/README.md +52 -0
  4. package/assets/delete-failed-runner.lambda/index.js +105 -9
  5. package/assets/idle-runner-repear.lambda/index.js +136 -14
  6. package/assets/image-builders/aws-image-builder/delete-resources.lambda/index.js +1 -1
  7. package/assets/image-builders/build-image.lambda/index.js +1 -1
  8. package/assets/providers/ami-root-device.lambda/index.js +1 -1
  9. package/assets/setup.lambda/index.html +7 -7
  10. package/assets/setup.lambda/index.js +101 -8
  11. package/assets/status.lambda/index.js +104 -8
  12. package/assets/token-retriever.lambda/index.js +104 -8
  13. package/assets/warm-runner-manager.lambda/index.js +5892 -0
  14. package/assets/webhook-handler.lambda/index.js +109 -11
  15. package/assets/webhook-redelivery.lambda/index.js +122 -24
  16. package/lib/access.js +1 -1
  17. package/lib/delete-failed-runner.lambda.js +2 -2
  18. package/lib/idle-runner-repear.lambda.js +33 -7
  19. package/lib/image-builders/api.js +1 -1
  20. package/lib/image-builders/aws-image-builder/base-image.d.ts +13 -0
  21. package/lib/image-builders/aws-image-builder/base-image.js +36 -3
  22. package/lib/image-builders/aws-image-builder/builder.js +4 -4
  23. package/lib/image-builders/aws-image-builder/delete-resources.lambda.js +2 -2
  24. package/lib/image-builders/aws-image-builder/deprecated/ami.js +1 -1
  25. package/lib/image-builders/aws-image-builder/deprecated/container.js +1 -1
  26. package/lib/image-builders/aws-image-builder/deprecated/linux-components.js +1 -1
  27. package/lib/image-builders/aws-image-builder/deprecated/windows-components.js +1 -1
  28. package/lib/image-builders/build-image.lambda.js +2 -2
  29. package/lib/image-builders/codebuild-deprecated.js +1 -1
  30. package/lib/image-builders/components.js +3 -3
  31. package/lib/image-builders/static.js +1 -1
  32. package/lib/index.d.ts +1 -0
  33. package/lib/index.js +2 -1
  34. package/lib/lambda-github.d.ts +1 -1
  35. package/lib/lambda-github.js +3 -2
  36. package/lib/lambda-helpers.js +4 -4
  37. package/lib/providers/ami-root-device.lambda.js +2 -2
  38. package/lib/providers/codebuild.d.ts +16 -0
  39. package/lib/providers/codebuild.js +16 -5
  40. package/lib/providers/common.js +3 -3
  41. package/lib/providers/composite.js +1 -1
  42. package/lib/providers/ec2.d.ts +5 -0
  43. package/lib/providers/ec2.js +42 -29
  44. package/lib/providers/ecs.d.ts +17 -0
  45. package/lib/providers/ecs.js +43 -38
  46. package/lib/providers/fargate.js +10 -32
  47. package/lib/providers/lambda.js +2 -2
  48. package/lib/runner.d.ts +25 -2
  49. package/lib/runner.js +119 -17
  50. package/lib/secrets.js +1 -1
  51. package/lib/setup.lambda.js +2 -2
  52. package/lib/utils.d.ts +10 -1
  53. package/lib/utils.js +15 -1
  54. package/lib/warm-runner-manager-function.d.ts +18 -0
  55. package/lib/warm-runner-manager-function.js +24 -0
  56. package/lib/warm-runner-manager.lambda.d.ts +41 -0
  57. package/lib/warm-runner-manager.lambda.js +487 -0
  58. package/lib/warm-runner.d.ts +147 -0
  59. package/lib/warm-runner.js +210 -0
  60. package/lib/webhook-handler.lambda.js +5 -3
  61. package/lib/webhook-redelivery.lambda.js +17 -16
  62. package/lib/webhook.d.ts +4 -0
  63. package/lib/webhook.js +2 -1
  64. package/node_modules/cron-parser/LICENSE +21 -0
  65. package/node_modules/cron-parser/README.md +408 -0
  66. package/node_modules/cron-parser/dist/CronDate.js +518 -0
  67. package/node_modules/cron-parser/dist/CronExpression.js +520 -0
  68. package/node_modules/cron-parser/dist/CronExpressionParser.js +382 -0
  69. package/node_modules/cron-parser/dist/CronFieldCollection.js +371 -0
  70. package/node_modules/cron-parser/dist/CronFileParser.js +109 -0
  71. package/node_modules/cron-parser/dist/fields/CronDayOfMonth.js +44 -0
  72. package/node_modules/cron-parser/dist/fields/CronDayOfWeek.js +51 -0
  73. package/node_modules/cron-parser/dist/fields/CronField.js +214 -0
  74. package/node_modules/cron-parser/dist/fields/CronHour.js +40 -0
  75. package/node_modules/cron-parser/dist/fields/CronMinute.js +40 -0
  76. package/node_modules/cron-parser/dist/fields/CronMonth.js +44 -0
  77. package/node_modules/cron-parser/dist/fields/CronSecond.js +40 -0
  78. package/node_modules/cron-parser/dist/fields/index.js +24 -0
  79. package/node_modules/cron-parser/dist/fields/types.js +2 -0
  80. package/node_modules/cron-parser/dist/index.js +31 -0
  81. package/node_modules/cron-parser/dist/types/CronDate.d.ts +288 -0
  82. package/node_modules/cron-parser/dist/types/CronExpression.d.ts +118 -0
  83. package/node_modules/cron-parser/dist/types/CronExpressionParser.d.ts +70 -0
  84. package/node_modules/cron-parser/dist/types/CronFieldCollection.d.ts +153 -0
  85. package/node_modules/cron-parser/dist/types/CronFileParser.d.ts +30 -0
  86. package/node_modules/cron-parser/dist/types/fields/CronDayOfMonth.d.ts +25 -0
  87. package/node_modules/cron-parser/dist/types/fields/CronDayOfWeek.d.ts +30 -0
  88. package/node_modules/cron-parser/dist/types/fields/CronField.d.ts +130 -0
  89. package/node_modules/cron-parser/dist/types/fields/CronHour.d.ts +23 -0
  90. package/node_modules/cron-parser/dist/types/fields/CronMinute.d.ts +23 -0
  91. package/node_modules/cron-parser/dist/types/fields/CronMonth.d.ts +24 -0
  92. package/node_modules/cron-parser/dist/types/fields/CronSecond.d.ts +23 -0
  93. package/node_modules/cron-parser/dist/types/fields/index.d.ts +8 -0
  94. package/node_modules/cron-parser/dist/types/fields/types.d.ts +18 -0
  95. package/node_modules/cron-parser/dist/types/index.d.ts +8 -0
  96. package/node_modules/cron-parser/dist/types/utils/random.d.ts +10 -0
  97. package/node_modules/cron-parser/dist/utils/random.js +38 -0
  98. package/node_modules/cron-parser/package.json +117 -0
  99. package/node_modules/luxon/LICENSE.md +7 -0
  100. package/node_modules/luxon/README.md +55 -0
  101. package/node_modules/luxon/build/amd/luxon.js +8741 -0
  102. package/node_modules/luxon/build/amd/luxon.js.map +1 -0
  103. package/node_modules/luxon/build/cjs-browser/luxon.js +8739 -0
  104. package/node_modules/luxon/build/cjs-browser/luxon.js.map +1 -0
  105. package/node_modules/luxon/build/es6/luxon.mjs +8133 -0
  106. package/node_modules/luxon/build/es6/luxon.mjs.map +1 -0
  107. package/node_modules/luxon/build/global/luxon.js +8744 -0
  108. package/node_modules/luxon/build/global/luxon.js.map +1 -0
  109. package/node_modules/luxon/build/global/luxon.min.js +1 -0
  110. package/node_modules/luxon/build/global/luxon.min.js.map +1 -0
  111. package/node_modules/luxon/build/node/luxon.js +7792 -0
  112. package/node_modules/luxon/build/node/luxon.js.map +1 -0
  113. package/node_modules/luxon/package.json +87 -0
  114. package/node_modules/luxon/src/datetime.js +2603 -0
  115. package/node_modules/luxon/src/duration.js +1009 -0
  116. package/node_modules/luxon/src/errors.js +61 -0
  117. package/node_modules/luxon/src/impl/conversions.js +206 -0
  118. package/node_modules/luxon/src/impl/diff.js +95 -0
  119. package/node_modules/luxon/src/impl/digits.js +94 -0
  120. package/node_modules/luxon/src/impl/english.js +233 -0
  121. package/node_modules/luxon/src/impl/formats.js +176 -0
  122. package/node_modules/luxon/src/impl/formatter.js +434 -0
  123. package/node_modules/luxon/src/impl/invalid.js +14 -0
  124. package/node_modules/luxon/src/impl/locale.js +569 -0
  125. package/node_modules/luxon/src/impl/regexParser.js +335 -0
  126. package/node_modules/luxon/src/impl/tokenParser.js +505 -0
  127. package/node_modules/luxon/src/impl/util.js +330 -0
  128. package/node_modules/luxon/src/impl/zoneUtil.js +34 -0
  129. package/node_modules/luxon/src/info.js +205 -0
  130. package/node_modules/luxon/src/interval.js +669 -0
  131. package/node_modules/luxon/src/luxon.js +26 -0
  132. package/node_modules/luxon/src/package.json +4 -0
  133. package/node_modules/luxon/src/settings.js +180 -0
  134. package/node_modules/luxon/src/zone.js +97 -0
  135. package/node_modules/luxon/src/zones/IANAZone.js +235 -0
  136. package/node_modules/luxon/src/zones/fixedOffsetZone.js +150 -0
  137. package/node_modules/luxon/src/zones/invalidZone.js +53 -0
  138. package/node_modules/luxon/src/zones/systemZone.js +61 -0
  139. package/package.json +33 -24
@@ -0,0 +1,382 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CronExpressionParser = exports.DayOfWeek = exports.Months = exports.CronUnit = exports.PredefinedExpressions = void 0;
4
+ const CronFieldCollection_1 = require("./CronFieldCollection");
5
+ const CronExpression_1 = require("./CronExpression");
6
+ const random_1 = require("./utils/random");
7
+ const fields_1 = require("./fields");
8
+ var PredefinedExpressions;
9
+ (function (PredefinedExpressions) {
10
+ PredefinedExpressions["@yearly"] = "0 0 0 1 1 *";
11
+ PredefinedExpressions["@annually"] = "0 0 0 1 1 *";
12
+ PredefinedExpressions["@monthly"] = "0 0 0 1 * *";
13
+ PredefinedExpressions["@weekly"] = "0 0 0 * * 0";
14
+ PredefinedExpressions["@daily"] = "0 0 0 * * *";
15
+ PredefinedExpressions["@hourly"] = "0 0 * * * *";
16
+ PredefinedExpressions["@minutely"] = "0 * * * * *";
17
+ PredefinedExpressions["@secondly"] = "* * * * * *";
18
+ PredefinedExpressions["@weekdays"] = "0 0 0 * * 1-5";
19
+ PredefinedExpressions["@weekends"] = "0 0 0 * * 0,6";
20
+ })(PredefinedExpressions || (exports.PredefinedExpressions = PredefinedExpressions = {}));
21
+ var CronUnit;
22
+ (function (CronUnit) {
23
+ CronUnit["Second"] = "Second";
24
+ CronUnit["Minute"] = "Minute";
25
+ CronUnit["Hour"] = "Hour";
26
+ CronUnit["DayOfMonth"] = "DayOfMonth";
27
+ CronUnit["Month"] = "Month";
28
+ CronUnit["DayOfWeek"] = "DayOfWeek";
29
+ })(CronUnit || (exports.CronUnit = CronUnit = {}));
30
+ // these need to be lowercase for the parser to work
31
+ var Months;
32
+ (function (Months) {
33
+ Months[Months["jan"] = 1] = "jan";
34
+ Months[Months["feb"] = 2] = "feb";
35
+ Months[Months["mar"] = 3] = "mar";
36
+ Months[Months["apr"] = 4] = "apr";
37
+ Months[Months["may"] = 5] = "may";
38
+ Months[Months["jun"] = 6] = "jun";
39
+ Months[Months["jul"] = 7] = "jul";
40
+ Months[Months["aug"] = 8] = "aug";
41
+ Months[Months["sep"] = 9] = "sep";
42
+ Months[Months["oct"] = 10] = "oct";
43
+ Months[Months["nov"] = 11] = "nov";
44
+ Months[Months["dec"] = 12] = "dec";
45
+ })(Months || (exports.Months = Months = {}));
46
+ // these need to be lowercase for the parser to work
47
+ var DayOfWeek;
48
+ (function (DayOfWeek) {
49
+ DayOfWeek[DayOfWeek["sun"] = 0] = "sun";
50
+ DayOfWeek[DayOfWeek["mon"] = 1] = "mon";
51
+ DayOfWeek[DayOfWeek["tue"] = 2] = "tue";
52
+ DayOfWeek[DayOfWeek["wed"] = 3] = "wed";
53
+ DayOfWeek[DayOfWeek["thu"] = 4] = "thu";
54
+ DayOfWeek[DayOfWeek["fri"] = 5] = "fri";
55
+ DayOfWeek[DayOfWeek["sat"] = 6] = "sat";
56
+ })(DayOfWeek || (exports.DayOfWeek = DayOfWeek = {}));
57
+ /**
58
+ * Static class that parses a cron expression and returns a CronExpression object.
59
+ * @static
60
+ * @class CronExpressionParser
61
+ */
62
+ class CronExpressionParser {
63
+ /**
64
+ * Parses a cron expression and returns a CronExpression object.
65
+ * @param {string} expression - The cron expression to parse.
66
+ * @param {CronExpressionOptions} [options={}] - The options to use when parsing the expression.
67
+ * @param {boolean} [options.strict=false] - If true, will throw an error if the expression contains both dayOfMonth and dayOfWeek.
68
+ * @param {CronDate} [options.currentDate=new CronDate(undefined, 'UTC')] - The date to use when calculating the next/previous occurrence.
69
+ *
70
+ * @returns {CronExpression} A CronExpression object.
71
+ */
72
+ static parse(expression, options = {}) {
73
+ const { strict = false, hashSeed } = options;
74
+ const rand = (0, random_1.seededRandom)(hashSeed);
75
+ expression = PredefinedExpressions[expression] || expression;
76
+ const rawFields = CronExpressionParser.#getRawFields(expression, strict);
77
+ if (!(rawFields.dayOfMonth === '*' || rawFields.dayOfWeek === '*' || !strict)) {
78
+ throw new Error('Cannot use both dayOfMonth and dayOfWeek together in strict mode!');
79
+ }
80
+ const second = CronExpressionParser.#parseField(CronUnit.Second, rawFields.second, fields_1.CronSecond.constraints, rand);
81
+ const minute = CronExpressionParser.#parseField(CronUnit.Minute, rawFields.minute, fields_1.CronMinute.constraints, rand);
82
+ const hour = CronExpressionParser.#parseField(CronUnit.Hour, rawFields.hour, fields_1.CronHour.constraints, rand);
83
+ const month = CronExpressionParser.#parseField(CronUnit.Month, rawFields.month, fields_1.CronMonth.constraints, rand);
84
+ const dayOfMonth = CronExpressionParser.#parseField(CronUnit.DayOfMonth, rawFields.dayOfMonth, fields_1.CronDayOfMonth.constraints, rand);
85
+ const { dayOfWeek: _dayOfWeek, nthDayOfWeek } = CronExpressionParser.#parseNthDay(rawFields.dayOfWeek);
86
+ const dayOfWeek = CronExpressionParser.#parseField(CronUnit.DayOfWeek, _dayOfWeek, fields_1.CronDayOfWeek.constraints, rand);
87
+ const fields = new CronFieldCollection_1.CronFieldCollection({
88
+ second: new fields_1.CronSecond(second, { rawValue: rawFields.second }),
89
+ minute: new fields_1.CronMinute(minute, { rawValue: rawFields.minute }),
90
+ hour: new fields_1.CronHour(hour, { rawValue: rawFields.hour }),
91
+ dayOfMonth: new fields_1.CronDayOfMonth(dayOfMonth, { rawValue: rawFields.dayOfMonth }),
92
+ month: new fields_1.CronMonth(month, { rawValue: rawFields.month }),
93
+ dayOfWeek: new fields_1.CronDayOfWeek(dayOfWeek, { rawValue: rawFields.dayOfWeek, nthDayOfWeek }),
94
+ });
95
+ return new CronExpression_1.CronExpression(fields, { ...options, expression });
96
+ }
97
+ /**
98
+ * Get the raw fields from a cron expression.
99
+ * @param {string} expression - The cron expression to parse.
100
+ * @param {boolean} strict - If true, will throw an error if the expression contains both dayOfMonth and dayOfWeek.
101
+ * @private
102
+ * @returns {RawCronFields} The raw fields.
103
+ */
104
+ static #getRawFields(expression, strict) {
105
+ if (strict && !expression.length) {
106
+ throw new Error('Invalid cron expression');
107
+ }
108
+ expression = expression || '0 * * * * *';
109
+ const atoms = expression.trim().split(/\s+/);
110
+ if (strict && atoms.length < 6) {
111
+ throw new Error('Invalid cron expression, expected 6 fields');
112
+ }
113
+ if (atoms.length > 6) {
114
+ throw new Error('Invalid cron expression, too many fields');
115
+ }
116
+ const defaults = ['*', '*', '*', '*', '*', '0'];
117
+ if (atoms.length < defaults.length) {
118
+ atoms.unshift(...defaults.slice(atoms.length));
119
+ }
120
+ const [second, minute, hour, dayOfMonth, month, dayOfWeek] = atoms;
121
+ return { second, minute, hour, dayOfMonth, month, dayOfWeek };
122
+ }
123
+ /**
124
+ * Parse a field from a cron expression.
125
+ * @param {CronUnit} field - The field to parse.
126
+ * @param {string} value - The value of the field.
127
+ * @param {CronConstraints} constraints - The constraints for the field.
128
+ * @private
129
+ * @returns {(number | string)[]} The parsed field.
130
+ */
131
+ static #parseField(field, value, constraints, rand) {
132
+ // Replace aliases for month and dayOfWeek
133
+ if (field === CronUnit.Month || field === CronUnit.DayOfWeek) {
134
+ value = value.replace(/[a-z]{3}/gi, (match) => {
135
+ match = match.toLowerCase();
136
+ const replacer = Months[match] || DayOfWeek[match];
137
+ if (replacer === undefined) {
138
+ throw new Error(`Validation error, cannot resolve alias "${match}"`);
139
+ }
140
+ return replacer.toString();
141
+ });
142
+ }
143
+ // Check for valid characters
144
+ if (!constraints.validChars.test(value)) {
145
+ throw new Error(`Invalid characters, got value: ${value}`);
146
+ }
147
+ value = this.#parseWildcard(value, constraints);
148
+ value = this.#parseHashed(value, constraints, rand);
149
+ return this.#parseSequence(field, value, constraints);
150
+ }
151
+ /**
152
+ * Parse a wildcard from a cron expression.
153
+ * @param {string} value - The value to parse.
154
+ * @param {CronConstraints} constraints - The constraints for the field.
155
+ * @private
156
+ */
157
+ static #parseWildcard(value, constraints) {
158
+ return value.replace(/[*?]/g, constraints.min + '-' + constraints.max);
159
+ }
160
+ /**
161
+ * Parse a hashed value from a cron expression.
162
+ * @param {string} value - The value to parse.
163
+ * @param {CronConstraints} constraints - The constraints for the field.
164
+ * @param {PRNG} rand - The random number generator to use.
165
+ * @private
166
+ */
167
+ static #parseHashed(value, constraints, rand) {
168
+ const randomValue = rand();
169
+ return value.replace(/H(?:\((\d+)-(\d+)\))?(?:\/(\d+))?/g, (_, min, max, step) => {
170
+ // H(range)/step
171
+ if (min && max && step) {
172
+ const minNum = parseInt(min, 10);
173
+ const maxNum = parseInt(max, 10);
174
+ const stepNum = parseInt(step, 10);
175
+ if (minNum > maxNum) {
176
+ throw new Error(`Invalid range: ${minNum}-${maxNum}, min > max`);
177
+ }
178
+ if (stepNum <= 0) {
179
+ throw new Error(`Invalid step: ${stepNum}, must be positive`);
180
+ }
181
+ const minStart = Math.max(minNum, constraints.min);
182
+ const offset = Math.floor(randomValue * stepNum);
183
+ const values = [];
184
+ for (let i = Math.floor(minStart / stepNum) * stepNum + offset; i <= maxNum; i += stepNum) {
185
+ if (i >= minStart) {
186
+ values.push(i);
187
+ }
188
+ }
189
+ return values.join(',');
190
+ }
191
+ // H(range)
192
+ else if (min && max) {
193
+ const minNum = parseInt(min, 10);
194
+ const maxNum = parseInt(max, 10);
195
+ if (minNum > maxNum) {
196
+ throw new Error(`Invalid range: ${minNum}-${maxNum}, min > max`);
197
+ }
198
+ return String(Math.floor(randomValue * (maxNum - minNum + 1)) + minNum);
199
+ }
200
+ // H/step
201
+ else if (step) {
202
+ const stepNum = parseInt(step, 10);
203
+ // Validate step
204
+ if (stepNum <= 0) {
205
+ throw new Error(`Invalid step: ${stepNum}, must be positive`);
206
+ }
207
+ const offset = Math.floor(randomValue * stepNum);
208
+ const values = [];
209
+ for (let i = Math.floor(constraints.min / stepNum) * stepNum + offset; i <= constraints.max; i += stepNum) {
210
+ if (i >= constraints.min) {
211
+ values.push(i);
212
+ }
213
+ }
214
+ return values.join(',');
215
+ }
216
+ // H
217
+ else {
218
+ return String(Math.floor(randomValue * (constraints.max - constraints.min + 1) + constraints.min));
219
+ }
220
+ });
221
+ }
222
+ /**
223
+ * Parse a sequence from a cron expression.
224
+ * @param {CronUnit} field - The field to parse.
225
+ * @param {string} val - The sequence to parse.
226
+ * @param {CronConstraints} constraints - The constraints for the field.
227
+ * @private
228
+ */
229
+ static #parseSequence(field, val, constraints) {
230
+ const stack = [];
231
+ function handleResult(result, constraints) {
232
+ if (Array.isArray(result)) {
233
+ stack.push(...result);
234
+ }
235
+ else {
236
+ if (CronExpressionParser.#isValidConstraintChar(constraints, result)) {
237
+ stack.push(result);
238
+ }
239
+ else {
240
+ const v = parseInt(result.toString(), 10);
241
+ const isValid = v >= constraints.min && v <= constraints.max;
242
+ if (!isValid) {
243
+ throw new Error(`Constraint error, got value ${result} expected range ${constraints.min}-${constraints.max}`);
244
+ }
245
+ stack.push(field === CronUnit.DayOfWeek ? v % 7 : result);
246
+ }
247
+ }
248
+ }
249
+ const atoms = val.split(',');
250
+ atoms.forEach((atom) => {
251
+ if (!(atom.length > 0)) {
252
+ throw new Error('Invalid list value format');
253
+ }
254
+ handleResult(CronExpressionParser.#parseRepeat(field, atom, constraints), constraints);
255
+ });
256
+ return stack;
257
+ }
258
+ /**
259
+ * Parse repeat from a cron expression.
260
+ * @param {CronUnit} field - The field to parse.
261
+ * @param {string} val - The repeat to parse.
262
+ * @param {CronConstraints} constraints - The constraints for the field.
263
+ * @private
264
+ * @returns {(number | string)[]} The parsed repeat.
265
+ */
266
+ static #parseRepeat(field, val, constraints) {
267
+ const atoms = val.split('/');
268
+ if (atoms.length > 2) {
269
+ throw new Error(`Invalid repeat: ${val}`);
270
+ }
271
+ if (atoms.length === 2) {
272
+ if (!isNaN(parseInt(atoms[0], 10))) {
273
+ atoms[0] = `${atoms[0]}-${constraints.max}`;
274
+ }
275
+ return CronExpressionParser.#parseRange(field, atoms[0], parseInt(atoms[1], 10), constraints);
276
+ }
277
+ return CronExpressionParser.#parseRange(field, val, 1, constraints);
278
+ }
279
+ /**
280
+ * Validate a cron range.
281
+ * @param {number} min - The minimum value of the range.
282
+ * @param {number} max - The maximum value of the range.
283
+ * @param {CronConstraints} constraints - The constraints for the field.
284
+ * @private
285
+ * @returns {void}
286
+ * @throws {Error} Throws an error if the range is invalid.
287
+ */
288
+ static #validateRange(min, max, constraints) {
289
+ const isValid = !isNaN(min) && !isNaN(max) && min >= constraints.min && max <= constraints.max;
290
+ if (!isValid) {
291
+ throw new Error(`Constraint error, got range ${min}-${max} expected range ${constraints.min}-${constraints.max}`);
292
+ }
293
+ if (min > max) {
294
+ throw new Error(`Invalid range: ${min}-${max}, min(${min}) > max(${max})`);
295
+ }
296
+ }
297
+ /**
298
+ * Validate a cron repeat interval.
299
+ * @param {number} repeatInterval - The repeat interval to validate.
300
+ * @private
301
+ * @returns {void}
302
+ * @throws {Error} Throws an error if the repeat interval is invalid.
303
+ */
304
+ static #validateRepeatInterval(repeatInterval) {
305
+ if (!(!isNaN(repeatInterval) && repeatInterval > 0)) {
306
+ throw new Error(`Constraint error, cannot repeat at every ${repeatInterval} time.`);
307
+ }
308
+ }
309
+ /**
310
+ * Create a range from a cron expression.
311
+ * @param {CronUnit} field - The field to parse.
312
+ * @param {number} min - The minimum value of the range.
313
+ * @param {number} max - The maximum value of the range.
314
+ * @param {number} repeatInterval - The repeat interval of the range.
315
+ * @private
316
+ * @returns {number[]} The created range.
317
+ */
318
+ static #createRange(field, min, max, repeatInterval) {
319
+ const stack = [];
320
+ if (field === CronUnit.DayOfWeek && max % 7 === 0) {
321
+ stack.push(0);
322
+ }
323
+ for (let index = min; index <= max; index += repeatInterval) {
324
+ if (stack.indexOf(index) === -1) {
325
+ stack.push(index);
326
+ }
327
+ }
328
+ return stack;
329
+ }
330
+ /**
331
+ * Parse a range from a cron expression.
332
+ * @param {CronUnit} field - The field to parse.
333
+ * @param {string} val - The range to parse.
334
+ * @param {number} repeatInterval - The repeat interval of the range.
335
+ * @param {CronConstraints} constraints - The constraints for the field.
336
+ * @private
337
+ * @returns {number[] | string[] | number | string} The parsed range.
338
+ */
339
+ static #parseRange(field, val, repeatInterval, constraints) {
340
+ const atoms = val.split('-');
341
+ if (atoms.length <= 1) {
342
+ return isNaN(+val) ? val : +val;
343
+ }
344
+ const [min, max] = atoms.map((num) => parseInt(num, 10));
345
+ this.#validateRange(min, max, constraints);
346
+ this.#validateRepeatInterval(repeatInterval);
347
+ // Create range
348
+ return this.#createRange(field, min, max, repeatInterval);
349
+ }
350
+ /**
351
+ * Parse a cron expression.
352
+ * @param {string} val - The cron expression to parse.
353
+ * @private
354
+ * @returns {string} The parsed cron expression.
355
+ */
356
+ static #parseNthDay(val) {
357
+ const atoms = val.split('#');
358
+ if (atoms.length <= 1) {
359
+ return { dayOfWeek: atoms[0] };
360
+ }
361
+ const nthValue = +atoms[atoms.length - 1];
362
+ const matches = val.match(/([,-/])/);
363
+ if (matches !== null) {
364
+ throw new Error(`Constraint error, invalid dayOfWeek \`#\` and \`${matches?.[0]}\` special characters are incompatible`);
365
+ }
366
+ if (!(atoms.length <= 2 && !isNaN(nthValue) && nthValue >= 1 && nthValue <= 5)) {
367
+ throw new Error('Constraint error, invalid dayOfWeek occurrence number (#)');
368
+ }
369
+ return { dayOfWeek: atoms[0], nthDayOfWeek: nthValue };
370
+ }
371
+ /**
372
+ * Checks if a character is valid for a field.
373
+ * @param {CronConstraints} constraints - The constraints for the field.
374
+ * @param {string | number} value - The value to check.
375
+ * @private
376
+ * @returns {boolean} Whether the character is valid for the field.
377
+ */
378
+ static #isValidConstraintChar(constraints, value) {
379
+ return constraints.chars.some((char) => value.toString().includes(char));
380
+ }
381
+ }
382
+ exports.CronExpressionParser = CronExpressionParser;