@reventlessdev/reventless-core 3.0.0-alpha.294 → 3.0.0-alpha.296
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 +39 -0
- package/package.json +8 -8
- package/src/admin/Platform_ComponentDefinitionsApi.res +3 -1
- package/src/admin/Platform_ComponentDefinitionsApi.res.mjs +5 -1
- package/src/components/AutomationSlice/AutomationSlice.res +2 -0
- package/src/components/AutomationSlice/AutomationSlice_Builder.res +133 -8
- package/src/components/AutomationSlice/AutomationSlice_Builder.res.mjs +89 -7
- package/src/components/AutomationSlice/AutomationSlice_Callback.res +136 -3
- package/src/components/AutomationSlice/AutomationSlice_Callback.res.mjs +122 -4
- package/src/components/AutomationSlice/AutomationSlice_Route.res +3 -1
- package/src/components/AutomationSlice/AutomationSlice_Route.res.mjs +2 -1
- package/src/components/AutomationSlice/AutomationSlice_Schedules.res +149 -0
- package/src/components/AutomationSlice/AutomationSlice_Schedules.res.mjs +193 -0
- package/src/components/Dcb/Dcb_Builder.res +28 -4
- package/src/components/Dcb/Dcb_Builder.res.mjs +27 -5
- package/src/plugin/component/Plugin_Builder.res +10 -3
- package/src/plugin/component/Plugin_Builder.res.mjs +8 -2
- package/src/plugin/component/Plugin_Structure.res +7 -0
- package/src/plugin/component/Plugin_Structure.res.mjs +5 -2
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res +1 -1
- package/src/plugin/connect/PluginExtensionPoint_Plugin.res.mjs +1 -1
- package/src/util/ScheduleOps.res +1 -55
- package/src/util/ScheduleOps.res.mjs +10 -57
- package/src/util/ScheduleTime.res +266 -0
- package/src/util/ScheduleTime.res.mjs +451 -0
- package/tests/admin/AdminApiSchemaDriftTest.res +1 -0
- package/tests/admin/AdminApiSchemaDriftTest.res.mjs +4 -1
- package/tests/automationslice/AutomationSliceSchedulesTest.res +143 -0
- package/tests/automationslice/AutomationSliceSchedulesTest.res.mjs +247 -0
- package/tests/util/ScheduleTimeTest.res +256 -0
- package/tests/util/ScheduleTimeTest.res.mjs +532 -0
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
// Generated by ReScript, PLEASE EDIT WITH CARE
|
|
2
|
+
|
|
3
|
+
import * as Cron from "effect/Cron";
|
|
4
|
+
import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
|
|
5
|
+
import * as ScheduleTime$ReventlessCore from "../../src/util/ScheduleTime.res.mjs";
|
|
6
|
+
|
|
7
|
+
function at(iso) {
|
|
8
|
+
return new Date(iso).getTime();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function iso(millis) {
|
|
12
|
+
return new Date(millis).toISOString();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function firings(time, from, n) {
|
|
16
|
+
let out = [];
|
|
17
|
+
let loop = _after => {
|
|
18
|
+
while (true) {
|
|
19
|
+
let after = _after;
|
|
20
|
+
let next = out.length < n ? ScheduleTime$ReventlessCore.nextFiring(time, after) : undefined;
|
|
21
|
+
if (next === undefined) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
out.push(new Date(next).toISOString());
|
|
25
|
+
_after = next;
|
|
26
|
+
continue;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
loop(new Date(from).getTime());
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
globalThis.describe("ScheduleTime.nextFiring", () => {
|
|
34
|
+
globalThis.test("Every counts from the previous firing, with no zone", () => {
|
|
35
|
+
globalThis.expect(firings({
|
|
36
|
+
TAG: "Every",
|
|
37
|
+
_0: {
|
|
38
|
+
TAG: "Hours",
|
|
39
|
+
_0: 2
|
|
40
|
+
}
|
|
41
|
+
}, "2026-03-29T00:30:00Z", 2)).toEqual([
|
|
42
|
+
"2026-03-29T02:30:00.000Z",
|
|
43
|
+
"2026-03-29T04:30:00.000Z"
|
|
44
|
+
]);
|
|
45
|
+
});
|
|
46
|
+
globalThis.test("Daily is a wall-clock time in its zone, across both daylight-saving changes", () => {
|
|
47
|
+
let daily = {
|
|
48
|
+
TAG: "Calendar",
|
|
49
|
+
calendar: {
|
|
50
|
+
TAG: "Daily",
|
|
51
|
+
hour: 6,
|
|
52
|
+
minute: 0
|
|
53
|
+
},
|
|
54
|
+
zone: "Europe/Berlin"
|
|
55
|
+
};
|
|
56
|
+
globalThis.expect(firings(daily, "2026-03-28T12:00:00Z", 2)).toEqual([
|
|
57
|
+
"2026-03-29T04:00:00.000Z",
|
|
58
|
+
"2026-03-30T04:00:00.000Z"
|
|
59
|
+
]);
|
|
60
|
+
globalThis.expect(firings(daily, "2026-10-24T12:00:00Z", 2)).toEqual([
|
|
61
|
+
"2026-10-25T05:00:00.000Z",
|
|
62
|
+
"2026-10-26T05:00:00.000Z"
|
|
63
|
+
]);
|
|
64
|
+
});
|
|
65
|
+
globalThis.test("a time in the skipped hour does not fire that day; in the repeated hour, once", () => {
|
|
66
|
+
let night = {
|
|
67
|
+
TAG: "Calendar",
|
|
68
|
+
calendar: {
|
|
69
|
+
TAG: "Daily",
|
|
70
|
+
hour: 2,
|
|
71
|
+
minute: 30
|
|
72
|
+
},
|
|
73
|
+
zone: "Europe/Berlin"
|
|
74
|
+
};
|
|
75
|
+
globalThis.expect(firings(night, "2026-03-27T12:00:00Z", 2)).toEqual([
|
|
76
|
+
"2026-03-28T01:30:00.000Z",
|
|
77
|
+
"2026-03-30T00:30:00.000Z"
|
|
78
|
+
]);
|
|
79
|
+
globalThis.expect(firings(night, "2026-10-24T12:00:00Z", 2)).toEqual([
|
|
80
|
+
"2026-10-25T00:30:00.000Z",
|
|
81
|
+
"2026-10-26T01:30:00.000Z"
|
|
82
|
+
]);
|
|
83
|
+
});
|
|
84
|
+
globalThis.test("Weekly fires on its days only", () => {
|
|
85
|
+
let weekdays_0 = {
|
|
86
|
+
TAG: "Weekly",
|
|
87
|
+
days: [
|
|
88
|
+
"Mon",
|
|
89
|
+
"Fri"
|
|
90
|
+
],
|
|
91
|
+
hour: 7,
|
|
92
|
+
minute: 30
|
|
93
|
+
};
|
|
94
|
+
let weekdays = {
|
|
95
|
+
TAG: "Calendar",
|
|
96
|
+
calendar: weekdays_0
|
|
97
|
+
};
|
|
98
|
+
globalThis.expect(firings(weekdays, "2026-10-16T08:00:00Z", 3)).toEqual([
|
|
99
|
+
"2026-10-19T07:30:00.000Z",
|
|
100
|
+
"2026-10-23T07:30:00.000Z",
|
|
101
|
+
"2026-10-26T07:30:00.000Z"
|
|
102
|
+
]);
|
|
103
|
+
});
|
|
104
|
+
globalThis.test("Monthly on the 29th to 31st skips the months without that day", () => {
|
|
105
|
+
globalThis.expect(firings({
|
|
106
|
+
TAG: "Calendar",
|
|
107
|
+
calendar: {
|
|
108
|
+
TAG: "Monthly",
|
|
109
|
+
day: 29,
|
|
110
|
+
hour: 6,
|
|
111
|
+
minute: 0
|
|
112
|
+
}
|
|
113
|
+
}, "2027-01-30T00:00:00Z", 1)).toEqual(["2027-03-29T06:00:00.000Z"]);
|
|
114
|
+
globalThis.expect(firings({
|
|
115
|
+
TAG: "Calendar",
|
|
116
|
+
calendar: {
|
|
117
|
+
TAG: "Monthly",
|
|
118
|
+
day: 30,
|
|
119
|
+
hour: 6,
|
|
120
|
+
minute: 0
|
|
121
|
+
}
|
|
122
|
+
}, "2027-01-31T00:00:00Z", 1)).toEqual(["2027-03-30T06:00:00.000Z"]);
|
|
123
|
+
globalThis.expect(firings({
|
|
124
|
+
TAG: "Calendar",
|
|
125
|
+
calendar: {
|
|
126
|
+
TAG: "Monthly",
|
|
127
|
+
day: 31,
|
|
128
|
+
hour: 6,
|
|
129
|
+
minute: 0
|
|
130
|
+
}
|
|
131
|
+
}, "2026-04-01T00:00:00Z", 2)).toEqual([
|
|
132
|
+
"2026-05-31T06:00:00.000Z",
|
|
133
|
+
"2026-07-31T06:00:00.000Z"
|
|
134
|
+
]);
|
|
135
|
+
});
|
|
136
|
+
globalThis.test("Monthly with every fires every so many months, from January", () => {
|
|
137
|
+
globalThis.expect(firings({
|
|
138
|
+
TAG: "Calendar",
|
|
139
|
+
calendar: {
|
|
140
|
+
TAG: "Monthly",
|
|
141
|
+
day: 1,
|
|
142
|
+
hour: 6,
|
|
143
|
+
minute: 0,
|
|
144
|
+
every: 3
|
|
145
|
+
}
|
|
146
|
+
}, "2026-02-15T00:00:00Z", 4)).toEqual([
|
|
147
|
+
"2026-04-01T06:00:00.000Z",
|
|
148
|
+
"2026-07-01T06:00:00.000Z",
|
|
149
|
+
"2026-10-01T06:00:00.000Z",
|
|
150
|
+
"2027-01-01T06:00:00.000Z"
|
|
151
|
+
]);
|
|
152
|
+
});
|
|
153
|
+
globalThis.test("Yearly on 29 February fires in leap years", () => {
|
|
154
|
+
globalThis.expect(firings({
|
|
155
|
+
TAG: "Calendar",
|
|
156
|
+
calendar: {
|
|
157
|
+
TAG: "Yearly",
|
|
158
|
+
month: 2,
|
|
159
|
+
day: 29,
|
|
160
|
+
hour: 6,
|
|
161
|
+
minute: 0
|
|
162
|
+
}
|
|
163
|
+
}, "2026-01-01T00:00:00Z", 2)).toEqual([
|
|
164
|
+
"2028-02-29T06:00:00.000Z",
|
|
165
|
+
"2032-02-29T06:00:00.000Z"
|
|
166
|
+
]);
|
|
167
|
+
});
|
|
168
|
+
globalThis.test("Once at a local time fires once, read in its zone; once past, never", () => {
|
|
169
|
+
let newYear = {
|
|
170
|
+
TAG: "Once",
|
|
171
|
+
moment: {
|
|
172
|
+
TAG: "At",
|
|
173
|
+
_0: {
|
|
174
|
+
year: 2026,
|
|
175
|
+
month: 12,
|
|
176
|
+
day: 31,
|
|
177
|
+
hour: 23,
|
|
178
|
+
minute: 59
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
zone: "Europe/Berlin"
|
|
182
|
+
};
|
|
183
|
+
globalThis.expect(firings(newYear, "2026-10-16T00:00:00Z", 3)).toEqual(["2026-12-31T22:59:00.000Z"]);
|
|
184
|
+
globalThis.expect(firings(newYear, "2027-01-01T00:00:00Z", 1)).toEqual([]);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
globalThis.describe("ScheduleTime.resolveOnce", () => {
|
|
189
|
+
let resolved = (period, from, zoneOpt) => {
|
|
190
|
+
let zone = zoneOpt !== undefined ? zoneOpt : "UTC";
|
|
191
|
+
let match = ScheduleTime$ReventlessCore.resolveOnce({
|
|
192
|
+
TAG: "Once",
|
|
193
|
+
moment: {
|
|
194
|
+
TAG: "After",
|
|
195
|
+
_0: period
|
|
196
|
+
},
|
|
197
|
+
zone: zone
|
|
198
|
+
}, new Date(from).getTime());
|
|
199
|
+
switch (match.TAG) {
|
|
200
|
+
case "Every" :
|
|
201
|
+
case "Calendar" :
|
|
202
|
+
return;
|
|
203
|
+
case "Once" :
|
|
204
|
+
let localTime = match.moment;
|
|
205
|
+
if (localTime.TAG === "At") {
|
|
206
|
+
return localTime._0;
|
|
207
|
+
} else {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
globalThis.test("a month from 31 January is the last day of February", () => {
|
|
213
|
+
globalThis.expect(resolved({
|
|
214
|
+
TAG: "Months",
|
|
215
|
+
_0: 1
|
|
216
|
+
}, "2026-01-31T09:00:00Z", undefined)).toEqual({
|
|
217
|
+
year: 2026,
|
|
218
|
+
month: 2,
|
|
219
|
+
day: 28,
|
|
220
|
+
hour: 9,
|
|
221
|
+
minute: 0
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
globalThis.test("a day keeps the wall-clock time across a daylight-saving change", () => {
|
|
225
|
+
globalThis.expect(resolved({
|
|
226
|
+
TAG: "Days",
|
|
227
|
+
_0: 1
|
|
228
|
+
}, "2026-03-28T05:00:00Z", "Europe/Berlin")).toEqual({
|
|
229
|
+
year: 2026,
|
|
230
|
+
month: 3,
|
|
231
|
+
day: 29,
|
|
232
|
+
hour: 6,
|
|
233
|
+
minute: 0
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
globalThis.test("24 hours are elapsed time across the same change", () => {
|
|
237
|
+
globalThis.expect(resolved({
|
|
238
|
+
TAG: "Hours",
|
|
239
|
+
_0: 24
|
|
240
|
+
}, "2026-03-28T05:00:00Z", "Europe/Berlin")).toEqual({
|
|
241
|
+
year: 2026,
|
|
242
|
+
month: 3,
|
|
243
|
+
day: 29,
|
|
244
|
+
hour: 7,
|
|
245
|
+
minute: 0
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
globalThis.test("minutes are counted from the moment it is set, to the minute", () => {
|
|
249
|
+
globalThis.expect(resolved({
|
|
250
|
+
TAG: "Minutes",
|
|
251
|
+
_0: 10
|
|
252
|
+
}, "2026-10-15T14:02:37Z", undefined)).toEqual({
|
|
253
|
+
year: 2026,
|
|
254
|
+
month: 10,
|
|
255
|
+
day: 15,
|
|
256
|
+
hour: 14,
|
|
257
|
+
minute: 12
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
globalThis.describe("ScheduleTime.toAws", () => {
|
|
263
|
+
let setAt = new Date("2026-10-15T14:02:00Z").getTime();
|
|
264
|
+
globalThis.test("an interval is a rate, starting one interval later", () => {
|
|
265
|
+
let aws = ScheduleTime$ReventlessCore.toAws({
|
|
266
|
+
TAG: "Every",
|
|
267
|
+
_0: {
|
|
268
|
+
TAG: "Weeks",
|
|
269
|
+
_0: 2
|
|
270
|
+
}
|
|
271
|
+
}, setAt);
|
|
272
|
+
globalThis.expect(aws.expression).toBe("rate(14 days)");
|
|
273
|
+
globalThis.expect(aws.startDate).toEqual(setAt + 14 * 24 * 60 * 60000);
|
|
274
|
+
globalThis.expect(aws.timezone).toEqual(undefined);
|
|
275
|
+
globalThis.expect(ScheduleTime$ReventlessCore.toAws({
|
|
276
|
+
TAG: "Every",
|
|
277
|
+
_0: {
|
|
278
|
+
TAG: "Minutes",
|
|
279
|
+
_0: 1
|
|
280
|
+
}
|
|
281
|
+
}, setAt).expression).toBe("rate(1 minute)");
|
|
282
|
+
});
|
|
283
|
+
globalThis.test("a calendar time is a cron with its zone, UTC when it has none", () => {
|
|
284
|
+
let daily = ScheduleTime$ReventlessCore.toAws({
|
|
285
|
+
TAG: "Calendar",
|
|
286
|
+
calendar: {
|
|
287
|
+
TAG: "Daily",
|
|
288
|
+
hour: 6,
|
|
289
|
+
minute: 0
|
|
290
|
+
}
|
|
291
|
+
}, setAt);
|
|
292
|
+
globalThis.expect(daily.expression).toBe("cron(0 6 * * ? *)");
|
|
293
|
+
globalThis.expect(daily.timezone).toEqual("UTC");
|
|
294
|
+
let weekly = ScheduleTime$ReventlessCore.toAws({
|
|
295
|
+
TAG: "Calendar",
|
|
296
|
+
calendar: {
|
|
297
|
+
TAG: "Weekly",
|
|
298
|
+
days: [
|
|
299
|
+
"Mon",
|
|
300
|
+
"Tue",
|
|
301
|
+
"Wed",
|
|
302
|
+
"Thu",
|
|
303
|
+
"Fri"
|
|
304
|
+
],
|
|
305
|
+
hour: 7,
|
|
306
|
+
minute: 30
|
|
307
|
+
},
|
|
308
|
+
zone: "Europe/Berlin"
|
|
309
|
+
}, setAt);
|
|
310
|
+
globalThis.expect(weekly.expression).toBe("cron(30 7 ? * MON,TUE,WED,THU,FRI *)");
|
|
311
|
+
globalThis.expect(weekly.timezone).toEqual("Europe/Berlin");
|
|
312
|
+
globalThis.expect(ScheduleTime$ReventlessCore.toAws({
|
|
313
|
+
TAG: "Calendar",
|
|
314
|
+
calendar: {
|
|
315
|
+
TAG: "Monthly",
|
|
316
|
+
day: 1,
|
|
317
|
+
hour: 6,
|
|
318
|
+
minute: 0,
|
|
319
|
+
every: 3
|
|
320
|
+
}
|
|
321
|
+
}, setAt).expression).toBe("cron(0 6 1 1/3 ? *)");
|
|
322
|
+
globalThis.expect(ScheduleTime$ReventlessCore.toAws({
|
|
323
|
+
TAG: "Calendar",
|
|
324
|
+
calendar: {
|
|
325
|
+
TAG: "Yearly",
|
|
326
|
+
month: 12,
|
|
327
|
+
day: 24,
|
|
328
|
+
hour: 18,
|
|
329
|
+
minute: 0
|
|
330
|
+
}
|
|
331
|
+
}, setAt).expression).toBe("cron(0 18 24 12 ? *)");
|
|
332
|
+
});
|
|
333
|
+
globalThis.test("a once-only time is an at in its zone, deleted after it fires", () => {
|
|
334
|
+
let aws = ScheduleTime$ReventlessCore.toAws({
|
|
335
|
+
TAG: "Once",
|
|
336
|
+
moment: {
|
|
337
|
+
TAG: "After",
|
|
338
|
+
_0: {
|
|
339
|
+
TAG: "Days",
|
|
340
|
+
_0: 3
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
zone: "Europe/Berlin"
|
|
344
|
+
}, setAt);
|
|
345
|
+
globalThis.expect(aws.expression).toBe("at(2026-10-18T16:02:00)");
|
|
346
|
+
globalThis.expect(aws.timezone).toEqual("Europe/Berlin");
|
|
347
|
+
globalThis.expect(aws.deleteAfterCompletion).toBe(true);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
globalThis.describe("the two platforms agree", () => {
|
|
352
|
+
let fromAws = (calendar, zone) => {
|
|
353
|
+
let fields = ScheduleTime$ReventlessCore.cronExpressionOf(calendar).slice(5, -1).split(" ").map(f => {
|
|
354
|
+
if (f === "?") {
|
|
355
|
+
return "*";
|
|
356
|
+
} else {
|
|
357
|
+
return f;
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
let expression = fields.slice(0, 5).join(" ");
|
|
361
|
+
let tz = ScheduleTime$ReventlessCore.zoneOrThrow(zone);
|
|
362
|
+
let match = ScheduleTime$ReventlessCore.wallClockOf(calendar);
|
|
363
|
+
let minute = match[1];
|
|
364
|
+
let hour = match[0];
|
|
365
|
+
let cron = Cron.unsafeParse(expression, tz);
|
|
366
|
+
let out = [];
|
|
367
|
+
let loop = _after => {
|
|
368
|
+
while (true) {
|
|
369
|
+
let after = _after;
|
|
370
|
+
if (out.length >= 10) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
let next = ScheduleTime$ReventlessCore.nextOnWallClock(cron, after, hour, minute, tz);
|
|
374
|
+
out.push(new Date(next).toISOString());
|
|
375
|
+
_after = next;
|
|
376
|
+
continue;
|
|
377
|
+
};
|
|
378
|
+
};
|
|
379
|
+
loop(new Date("2026-01-01T00:00:00Z").getTime());
|
|
380
|
+
return out;
|
|
381
|
+
};
|
|
382
|
+
let cases = [
|
|
383
|
+
[
|
|
384
|
+
"daily",
|
|
385
|
+
{
|
|
386
|
+
TAG: "Daily",
|
|
387
|
+
hour: 6,
|
|
388
|
+
minute: 0
|
|
389
|
+
},
|
|
390
|
+
"UTC"
|
|
391
|
+
],
|
|
392
|
+
[
|
|
393
|
+
"daily in the skipped hour",
|
|
394
|
+
{
|
|
395
|
+
TAG: "Daily",
|
|
396
|
+
hour: 2,
|
|
397
|
+
minute: 30
|
|
398
|
+
},
|
|
399
|
+
"Europe/Berlin"
|
|
400
|
+
],
|
|
401
|
+
[
|
|
402
|
+
"weekdays",
|
|
403
|
+
{
|
|
404
|
+
TAG: "Weekly",
|
|
405
|
+
days: [
|
|
406
|
+
"Mon",
|
|
407
|
+
"Tue",
|
|
408
|
+
"Wed",
|
|
409
|
+
"Thu",
|
|
410
|
+
"Fri"
|
|
411
|
+
],
|
|
412
|
+
hour: 7,
|
|
413
|
+
minute: 30
|
|
414
|
+
},
|
|
415
|
+
"America/New_York"
|
|
416
|
+
],
|
|
417
|
+
[
|
|
418
|
+
"weekends",
|
|
419
|
+
{
|
|
420
|
+
TAG: "Weekly",
|
|
421
|
+
days: [
|
|
422
|
+
"Sat",
|
|
423
|
+
"Sun"
|
|
424
|
+
],
|
|
425
|
+
hour: 23,
|
|
426
|
+
minute: 59
|
|
427
|
+
},
|
|
428
|
+
"Australia/Sydney"
|
|
429
|
+
],
|
|
430
|
+
[
|
|
431
|
+
"monthly on the 31st",
|
|
432
|
+
{
|
|
433
|
+
TAG: "Monthly",
|
|
434
|
+
day: 31,
|
|
435
|
+
hour: 6,
|
|
436
|
+
minute: 0
|
|
437
|
+
},
|
|
438
|
+
"Europe/Berlin"
|
|
439
|
+
],
|
|
440
|
+
[
|
|
441
|
+
"quarterly",
|
|
442
|
+
{
|
|
443
|
+
TAG: "Monthly",
|
|
444
|
+
day: 15,
|
|
445
|
+
hour: 9,
|
|
446
|
+
minute: 15,
|
|
447
|
+
every: 3
|
|
448
|
+
},
|
|
449
|
+
"Asia/Kolkata"
|
|
450
|
+
],
|
|
451
|
+
[
|
|
452
|
+
"every five months",
|
|
453
|
+
{
|
|
454
|
+
TAG: "Monthly",
|
|
455
|
+
day: 1,
|
|
456
|
+
hour: 0,
|
|
457
|
+
minute: 0,
|
|
458
|
+
every: 5
|
|
459
|
+
},
|
|
460
|
+
"UTC"
|
|
461
|
+
],
|
|
462
|
+
[
|
|
463
|
+
"yearly",
|
|
464
|
+
{
|
|
465
|
+
TAG: "Yearly",
|
|
466
|
+
month: 3,
|
|
467
|
+
day: 29,
|
|
468
|
+
hour: 2,
|
|
469
|
+
minute: 30
|
|
470
|
+
},
|
|
471
|
+
"Europe/London"
|
|
472
|
+
]
|
|
473
|
+
];
|
|
474
|
+
cases.forEach(param => {
|
|
475
|
+
let zone = param[2];
|
|
476
|
+
let calendar = param[1];
|
|
477
|
+
globalThis.test(param[0], () => {
|
|
478
|
+
globalThis.expect(fromAws(calendar, zone)).toEqual(firings({
|
|
479
|
+
TAG: "Calendar",
|
|
480
|
+
calendar: calendar,
|
|
481
|
+
zone: zone
|
|
482
|
+
}, "2026-01-01T00:00:00Z", 10));
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
globalThis.describe("ScheduleTime.validate", () => {
|
|
488
|
+
globalThis.test("names every problem of a time", () => {
|
|
489
|
+
let message;
|
|
490
|
+
try {
|
|
491
|
+
ScheduleTime$ReventlessCore.validate({
|
|
492
|
+
TAG: "Calendar",
|
|
493
|
+
calendar: {
|
|
494
|
+
TAG: "Weekly",
|
|
495
|
+
days: [],
|
|
496
|
+
hour: 24,
|
|
497
|
+
minute: 0
|
|
498
|
+
},
|
|
499
|
+
zone: "Mars/Base"
|
|
500
|
+
});
|
|
501
|
+
message = "";
|
|
502
|
+
} catch (raw_message) {
|
|
503
|
+
let message$1 = Primitive_exceptions.internalToException(raw_message);
|
|
504
|
+
if (message$1.RE_EXN_ID === ScheduleTime$ReventlessCore.InvalidTime) {
|
|
505
|
+
message = message$1._1;
|
|
506
|
+
} else {
|
|
507
|
+
throw message$1;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
globalThis.expect(message).toBe(`unknown time zone "Mars/Base"; a weekly time needs at least one day; hour must be 0 to 23, got 24`);
|
|
511
|
+
});
|
|
512
|
+
globalThis.test("accepts a time that can fire", () => {
|
|
513
|
+
globalThis.expect(ScheduleTime$ReventlessCore.errors({
|
|
514
|
+
TAG: "Once",
|
|
515
|
+
moment: {
|
|
516
|
+
TAG: "After",
|
|
517
|
+
_0: {
|
|
518
|
+
TAG: "Years",
|
|
519
|
+
_0: 1
|
|
520
|
+
}
|
|
521
|
+
},
|
|
522
|
+
zone: "Pacific/Auckland"
|
|
523
|
+
})).toEqual([]);
|
|
524
|
+
});
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
export {
|
|
528
|
+
at,
|
|
529
|
+
iso,
|
|
530
|
+
firings,
|
|
531
|
+
}
|
|
532
|
+
/* Not a pure module */
|