@lunora/scheduler 0.0.0 → 1.0.0-alpha.10
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/LICENSE.md +111 -0
- package/README.md +140 -9
- package/__assets__/package-og.svg +14 -0
- package/dist/index.d.mts +853 -0
- package/dist/index.d.ts +853 -0
- package/dist/index.mjs +8 -0
- package/dist/packem_shared/CRON_SCHEDULE_KINDS-C2FflEnq.mjs +140 -0
- package/dist/packem_shared/SchedulerDO-DeJHI379.mjs +705 -0
- package/dist/packem_shared/assertValidCronExpression-B9m75qU0.mjs +24 -0
- package/dist/packem_shared/createCronTrigger-Dh4VLxD9.mjs +28 -0
- package/dist/packem_shared/createQueueConsumer-Cy-Mp-El.mjs +61 -0
- package/dist/packem_shared/createScheduler-Df9JUjQb.mjs +52 -0
- package/dist/packem_shared/createWorkpool-Ce0kNM2p.mjs +37 -0
- package/dist/packem_shared/do-client-CMJtLoHO.mjs +42 -0
- package/dist/packem_shared/isWorkflowReference-C9mQkMXt.mjs +3 -0
- package/package.json +41 -17
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { default as createScheduler } from './packem_shared/createScheduler-Df9JUjQb.mjs';
|
|
2
|
+
export { default as createWorkpool } from './packem_shared/createWorkpool-Ce0kNM2p.mjs';
|
|
3
|
+
export { createCronTrigger } from './packem_shared/createCronTrigger-Dh4VLxD9.mjs';
|
|
4
|
+
export { CRON_SCHEDULE_KINDS, compileCronSchedule, cronJobs } from './packem_shared/CRON_SCHEDULE_KINDS-C2FflEnq.mjs';
|
|
5
|
+
export { createQueueConsumer, createQueueWorkpool, httpDispatcher } from './packem_shared/createQueueConsumer-Cy-Mp-El.mjs';
|
|
6
|
+
export { SchedulerDO } from './packem_shared/SchedulerDO-DeJHI379.mjs';
|
|
7
|
+
export { isWorkflowReference } from './packem_shared/isWorkflowReference-C9mQkMXt.mjs';
|
|
8
|
+
export { assertValidCronExpression, isValidCronExpression } from './packem_shared/assertValidCronExpression-B9m75qU0.mjs';
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
import { isWorkflowReference } from './isWorkflowReference-C9mQkMXt.mjs';
|
|
3
|
+
import { assertValidCronExpression } from './assertValidCronExpression-B9m75qU0.mjs';
|
|
4
|
+
|
|
5
|
+
const WEEKDAY_INDEX = {
|
|
6
|
+
friday: 5,
|
|
7
|
+
monday: 1,
|
|
8
|
+
saturday: 6,
|
|
9
|
+
sunday: 0,
|
|
10
|
+
thursday: 4,
|
|
11
|
+
tuesday: 2,
|
|
12
|
+
wednesday: 3
|
|
13
|
+
};
|
|
14
|
+
const field = (value, label, min, max) => {
|
|
15
|
+
if (!Number.isInteger(value) || value < min || value > max) {
|
|
16
|
+
throw new LunoraError(
|
|
17
|
+
"INTERNAL",
|
|
18
|
+
`@lunora/scheduler: cronJobs ${label} must be an integer in [${min.toFixed(0)}, ${max.toFixed(0)}], got ${String(value)}`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
return value.toFixed(0);
|
|
22
|
+
};
|
|
23
|
+
const stepField = (value, label, period) => {
|
|
24
|
+
const rendered = field(value, label, 1, period - 1);
|
|
25
|
+
if (period % value !== 0) {
|
|
26
|
+
throw new LunoraError(
|
|
27
|
+
"INTERNAL",
|
|
28
|
+
`@lunora/scheduler: ${label} must evenly divide ${period.toFixed(0)} for a fixed "every ${value.toFixed(0)}" interval — cron "*/${value.toFixed(0)}" means "at values divisible by ${value.toFixed(0)}", which wraps unevenly; pick a divisor of ${period.toFixed(0)}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return rendered;
|
|
32
|
+
};
|
|
33
|
+
const compileInterval = (schedule) => {
|
|
34
|
+
const units = ["seconds", "minutes", "hours"].filter((unit2) => schedule[unit2] !== void 0);
|
|
35
|
+
if (units.length !== 1) {
|
|
36
|
+
throw new LunoraError("INTERNAL", `@lunora/scheduler: interval schedule must specify exactly one of { seconds, minutes, hours }`);
|
|
37
|
+
}
|
|
38
|
+
const unit = units[0];
|
|
39
|
+
const value = schedule[unit];
|
|
40
|
+
if (unit === "seconds") {
|
|
41
|
+
return `*/${stepField(value, "interval.seconds", 60)} * * * * *`;
|
|
42
|
+
}
|
|
43
|
+
if (unit === "minutes") {
|
|
44
|
+
return `*/${stepField(value, "interval.minutes", 60)} * * * *`;
|
|
45
|
+
}
|
|
46
|
+
return `0 */${stepField(value, "interval.hours", 24)} * * *`;
|
|
47
|
+
};
|
|
48
|
+
const compileDaily = (schedule) => {
|
|
49
|
+
const minute = field(schedule.minuteUTC, "daily.minuteUTC", 0, 59);
|
|
50
|
+
const hour = field(schedule.hourUTC, "daily.hourUTC", 0, 23);
|
|
51
|
+
return `${minute} ${hour} * * *`;
|
|
52
|
+
};
|
|
53
|
+
const compileWeekly = (schedule) => {
|
|
54
|
+
const index = WEEKDAY_INDEX[schedule.dayOfWeek];
|
|
55
|
+
if (index === void 0) {
|
|
56
|
+
throw new LunoraError("INTERNAL", `@lunora/scheduler: weekly schedule has invalid dayOfWeek "${schedule.dayOfWeek}"`);
|
|
57
|
+
}
|
|
58
|
+
const minute = field(schedule.minuteUTC, "weekly.minuteUTC", 0, 59);
|
|
59
|
+
const hour = field(schedule.hourUTC, "weekly.hourUTC", 0, 23);
|
|
60
|
+
return `${minute} ${hour} * * ${index.toFixed(0)}`;
|
|
61
|
+
};
|
|
62
|
+
const compileMonthly = (schedule) => {
|
|
63
|
+
const day = field(schedule.day, "monthly.day", 1, 31);
|
|
64
|
+
const minute = field(schedule.minuteUTC, "monthly.minuteUTC", 0, 59);
|
|
65
|
+
const hour = field(schedule.hourUTC, "monthly.hourUTC", 0, 23);
|
|
66
|
+
return `${minute} ${hour} ${day} * *`;
|
|
67
|
+
};
|
|
68
|
+
const CRON_SCHEDULE_KINDS = /* @__PURE__ */ new Set(["daily", "interval", "monthly", "weekly"]);
|
|
69
|
+
const compileCronSchedule = (kind, schedule) => {
|
|
70
|
+
switch (kind) {
|
|
71
|
+
case "daily": {
|
|
72
|
+
return compileDaily(schedule);
|
|
73
|
+
}
|
|
74
|
+
case "interval": {
|
|
75
|
+
return compileInterval(schedule);
|
|
76
|
+
}
|
|
77
|
+
case "monthly": {
|
|
78
|
+
return compileMonthly(schedule);
|
|
79
|
+
}
|
|
80
|
+
case "weekly": {
|
|
81
|
+
return compileWeekly(schedule);
|
|
82
|
+
}
|
|
83
|
+
default: {
|
|
84
|
+
throw new LunoraError("INTERNAL", `@lunora/scheduler: unknown cron schedule kind "${String(kind)}"`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const cronJobs = () => {
|
|
89
|
+
const jobs = [];
|
|
90
|
+
const seen = /* @__PURE__ */ new Set();
|
|
91
|
+
const register = (name, cron, target, args) => {
|
|
92
|
+
if (typeof name !== "string" || name.trim() === "") {
|
|
93
|
+
throw new LunoraError("INTERNAL", `@lunora/scheduler: cron job name must be a non-empty string`);
|
|
94
|
+
}
|
|
95
|
+
if (seen.has(name)) {
|
|
96
|
+
throw new LunoraError("INTERNAL", `@lunora/scheduler: duplicate cron job name "${name}" — names must be unique within one cronJobs()`);
|
|
97
|
+
}
|
|
98
|
+
if (isWorkflowReference(target)) {
|
|
99
|
+
assertValidCronExpression(cron, `cron expression for job "${name}"`);
|
|
100
|
+
seen.add(name);
|
|
101
|
+
jobs.push({ args: args ?? {}, cron, name, workflow: typeof target.name === "string" ? target.name : "" });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (!target || typeof target.__lunoraRef !== "string") {
|
|
105
|
+
throw new LunoraError(
|
|
106
|
+
"INTERNAL",
|
|
107
|
+
`@lunora/scheduler: cron job "${name}" requires a function reference (e.g. internal.email.digest) or a workflow reference`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
assertValidCronExpression(cron, `cron expression for job "${name}"`);
|
|
111
|
+
seen.add(name);
|
|
112
|
+
jobs.push({ args: args ?? {}, cron, functionPath: target.__lunoraRef, name });
|
|
113
|
+
};
|
|
114
|
+
const builder = {
|
|
115
|
+
cron(name, cronExpr, function_, args) {
|
|
116
|
+
register(name, cronExpr, function_, args);
|
|
117
|
+
return builder;
|
|
118
|
+
},
|
|
119
|
+
daily(name, schedule, function_, args) {
|
|
120
|
+
register(name, compileCronSchedule("daily", schedule), function_, args);
|
|
121
|
+
return builder;
|
|
122
|
+
},
|
|
123
|
+
interval(name, schedule, function_, args) {
|
|
124
|
+
register(name, compileCronSchedule("interval", schedule), function_, args);
|
|
125
|
+
return builder;
|
|
126
|
+
},
|
|
127
|
+
jobs: () => [...jobs],
|
|
128
|
+
monthly(name, schedule, function_, args) {
|
|
129
|
+
register(name, compileCronSchedule("monthly", schedule), function_, args);
|
|
130
|
+
return builder;
|
|
131
|
+
},
|
|
132
|
+
weekly(name, schedule, function_, args) {
|
|
133
|
+
register(name, compileCronSchedule("weekly", schedule), function_, args);
|
|
134
|
+
return builder;
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
return builder;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
export { CRON_SCHEDULE_KINDS, compileCronSchedule, cronJobs };
|