0xkobold 0.3.3 → 0.4.2
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/HEARTBEAT.md +100 -40
- package/dist/package.json +1 -1
- package/dist/src/cli/commands/cron.js +352 -0
- package/dist/src/cli/commands/cron.js.map +1 -0
- package/dist/src/cli/program.js +4 -0
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/cron/index.js +38 -0
- package/dist/src/cron/index.js.map +1 -0
- package/dist/src/cron/notifications.js +152 -0
- package/dist/src/cron/notifications.js.map +1 -0
- package/dist/src/cron/parser.js +294 -0
- package/dist/src/cron/parser.js.map +1 -0
- package/dist/src/cron/runner.js +251 -0
- package/dist/src/cron/runner.js.map +1 -0
- package/dist/src/cron/scheduler.js +524 -0
- package/dist/src/cron/scheduler.js.map +1 -0
- package/dist/src/cron/types.js +8 -0
- package/dist/src/cron/types.js.map +1 -0
- package/dist/src/extensions/core/session-manager-extension.js +17 -0
- package/dist/src/extensions/core/session-manager-extension.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron Notifications - 0xKobold
|
|
3
|
+
*
|
|
4
|
+
* Send job results to Telegram, Discord, Slack, WhatsApp
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Send notification based on job result
|
|
8
|
+
*/
|
|
9
|
+
export async function sendNotification(job, result) {
|
|
10
|
+
if (!job.notify)
|
|
11
|
+
return;
|
|
12
|
+
const { channel, recipient, onSuccess = true, onError = true, prefix } = job.notify;
|
|
13
|
+
// Check if we should notify for this result
|
|
14
|
+
if (result.success && !onSuccess)
|
|
15
|
+
return;
|
|
16
|
+
if (!result.success && !onError)
|
|
17
|
+
return;
|
|
18
|
+
const message = formatNotification(job, result, prefix);
|
|
19
|
+
try {
|
|
20
|
+
switch (channel) {
|
|
21
|
+
case 'telegram':
|
|
22
|
+
await sendTelegram(recipient, message);
|
|
23
|
+
break;
|
|
24
|
+
case 'discord':
|
|
25
|
+
await sendDiscord(recipient, message, result.success);
|
|
26
|
+
break;
|
|
27
|
+
case 'slack':
|
|
28
|
+
await sendSlack(recipient, message);
|
|
29
|
+
break;
|
|
30
|
+
case 'whatsapp':
|
|
31
|
+
await sendWhatsApp(recipient, message);
|
|
32
|
+
break;
|
|
33
|
+
default:
|
|
34
|
+
console.warn(`[Notification] Unknown channel: ${channel}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error(`[Notification] Failed to send ${channel} notification:`, error);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Format notification message
|
|
43
|
+
*/
|
|
44
|
+
function formatNotification(job, result, prefix) {
|
|
45
|
+
const icon = result.success ? "✅" : "❌";
|
|
46
|
+
const status = result.success ? "COMPLETED" : "FAILED";
|
|
47
|
+
let message = `${icon} **[${status}]** ${job.name}\n\n`;
|
|
48
|
+
if (prefix) {
|
|
49
|
+
message = `${prefix}\n${message}`;
|
|
50
|
+
}
|
|
51
|
+
if (result.success) {
|
|
52
|
+
// Truncate output if too long
|
|
53
|
+
const output = result.output.substring(0, 2000);
|
|
54
|
+
message += `**Output:**\n\`\`\`\n${output}${result.output.length > 2000 ? '...' : ''}\n\`\`\`\n`;
|
|
55
|
+
message += `\n**Duration:** ${result.duration}ms · **Tokens:** ${result.tokensUsed}`;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
message += `**Error:** ${result.error || 'Unknown error'}\n`;
|
|
59
|
+
message += `**Duration:** ${result.duration}ms`;
|
|
60
|
+
}
|
|
61
|
+
return message;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Send Telegram notification via Bot API
|
|
65
|
+
*/
|
|
66
|
+
async function sendTelegram(chatId, message) {
|
|
67
|
+
const token = process.env.TELEGRAM_BOT_TOKEN;
|
|
68
|
+
if (!token) {
|
|
69
|
+
throw new Error('TELEGRAM_BOT_TOKEN not set');
|
|
70
|
+
}
|
|
71
|
+
const url = `https://api.telegram.org/bot${token}/sendMessage`;
|
|
72
|
+
const response = await fetch(url, {
|
|
73
|
+
method: 'POST',
|
|
74
|
+
headers: { 'Content-Type': 'application/json' },
|
|
75
|
+
body: JSON.stringify({
|
|
76
|
+
chat_id: chatId,
|
|
77
|
+
text: message,
|
|
78
|
+
parse_mode: 'Markdown',
|
|
79
|
+
}),
|
|
80
|
+
});
|
|
81
|
+
if (!response.ok) {
|
|
82
|
+
const error = await response.text();
|
|
83
|
+
throw new Error(`Telegram API error: ${error}`);
|
|
84
|
+
}
|
|
85
|
+
console.log(`[Notification] Telegram sent to ${chatId}`);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Send Discord notification via Webhook or Bot API
|
|
89
|
+
*/
|
|
90
|
+
async function sendDiscord(channelId, message, success) {
|
|
91
|
+
const token = process.env.DISCORD_BOT_TOKEN;
|
|
92
|
+
if (!token) {
|
|
93
|
+
throw new Error('DISCORD_BOT_TOKEN not set');
|
|
94
|
+
}
|
|
95
|
+
// Use Discord API
|
|
96
|
+
const url = `https://discord.com/api/v10/channels/${channelId}/messages`;
|
|
97
|
+
// Build Discord embed
|
|
98
|
+
const embed = {
|
|
99
|
+
title: success ? "✅ Job Completed" : "❌ Job Failed",
|
|
100
|
+
description: message.substring(0, 4096),
|
|
101
|
+
color: success ? 0x00ff00 : 0xff0000,
|
|
102
|
+
timestamp: new Date().toISOString(),
|
|
103
|
+
footer: {
|
|
104
|
+
text: "0xKobold Cron",
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
const response = await fetch(url, {
|
|
108
|
+
method: 'POST',
|
|
109
|
+
headers: {
|
|
110
|
+
'Authorization': `Bot ${token}`,
|
|
111
|
+
'Content-Type': 'application/json',
|
|
112
|
+
},
|
|
113
|
+
body: JSON.stringify({ embeds: [embed] }),
|
|
114
|
+
});
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
const error = await response.text();
|
|
117
|
+
throw new Error(`Discord API error: ${error}`);
|
|
118
|
+
}
|
|
119
|
+
console.log(`[Notification] Discord sent to ${channelId}`);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Send Slack notification via Incoming Webhook
|
|
123
|
+
*/
|
|
124
|
+
async function sendSlack(webhookUrl, message) {
|
|
125
|
+
// Check if it's a webhook URL
|
|
126
|
+
if (!webhookUrl.startsWith('https://hooks.slack.com/')) {
|
|
127
|
+
throw new Error('Invalid Slack webhook URL');
|
|
128
|
+
}
|
|
129
|
+
const response = await fetch(webhookUrl, {
|
|
130
|
+
method: 'POST',
|
|
131
|
+
headers: { 'Content-Type': 'application/json' },
|
|
132
|
+
body: JSON.stringify({
|
|
133
|
+
text: message,
|
|
134
|
+
mrkdwn: true,
|
|
135
|
+
}),
|
|
136
|
+
});
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
const error = await response.text();
|
|
139
|
+
throw new Error(`Slack webhook error: ${error}`);
|
|
140
|
+
}
|
|
141
|
+
console.log(`[Notification] Slack sent`);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Send WhatsApp notification (placeholder - requires Baileys or WhatsApp Business API)
|
|
145
|
+
*/
|
|
146
|
+
async function sendWhatsApp(phoneNumber, message) {
|
|
147
|
+
// TODO: Implement using existing WhatsApp integration
|
|
148
|
+
// For now, log a warning
|
|
149
|
+
console.warn(`[Notification] WhatsApp notifications require Baileys integration (not yet implemented)`);
|
|
150
|
+
console.warn(`[Notification] Would send to ${phoneNumber}: ${message.substring(0, 100)}...`);
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=notifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../../../src/cron/notifications.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron Expression Parser - 0xKobold
|
|
3
|
+
*
|
|
4
|
+
* Parses standard cron expressions and calculates next run times.
|
|
5
|
+
* Supports: standard cron, L (last), W (weekday), # (nth)
|
|
6
|
+
*/
|
|
7
|
+
// Standard cron ranges
|
|
8
|
+
const RANGES = {
|
|
9
|
+
minute: { min: 0, max: 59 },
|
|
10
|
+
hour: { min: 0, max: 23 },
|
|
11
|
+
dayOfMonth: { min: 1, max: 31 },
|
|
12
|
+
month: { min: 1, max: 12 },
|
|
13
|
+
dayOfWeek: { min: 0, max: 6 }, // 0 = Sunday
|
|
14
|
+
};
|
|
15
|
+
const MONTH_NAMES = {
|
|
16
|
+
jan: 1, feb: 2, mar: 3, apr: 4, may: 5, jun: 6,
|
|
17
|
+
jul: 7, aug: 8, sep: 9, oct: 10, nov: 11, dec: 12,
|
|
18
|
+
};
|
|
19
|
+
const DAY_NAMES = {
|
|
20
|
+
sun: 0, mon: 1, tue: 2, wed: 3, thu: 4, fri: 5, sat: 6,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Parse a cron expression into structured components
|
|
24
|
+
*/
|
|
25
|
+
export function parseCron(expression, timezone = 'UTC') {
|
|
26
|
+
const parts = expression.trim().split(/\s+/);
|
|
27
|
+
if (parts.length !== 5 && parts.length !== 6) {
|
|
28
|
+
throw new Error(`Invalid cron expression "${expression}". Expected 5 fields (min hour day month dow) or 6 fields (with seconds).`);
|
|
29
|
+
}
|
|
30
|
+
// Handle 6-field format (with seconds)
|
|
31
|
+
let [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
32
|
+
if (parts.length === 6) {
|
|
33
|
+
// Skip seconds, use rest
|
|
34
|
+
[, minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
minute: parseField(minute, 'minute'),
|
|
38
|
+
hour: parseField(hour, 'hour'),
|
|
39
|
+
dayOfMonth: parseField(dayOfMonth, 'dayOfMonth'),
|
|
40
|
+
month: parseField(month, 'month'),
|
|
41
|
+
dayOfWeek: parseField(dayOfWeek, 'dayOfWeek'),
|
|
42
|
+
timezone,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parse a single cron field
|
|
47
|
+
*/
|
|
48
|
+
function parseField(field, type) {
|
|
49
|
+
const range = RANGES[type];
|
|
50
|
+
// Wildcard
|
|
51
|
+
if (field === '*')
|
|
52
|
+
return '*';
|
|
53
|
+
// Step syntax (*/5 = every 5)
|
|
54
|
+
if (field.startsWith('*/')) {
|
|
55
|
+
const step = parseInt(field.slice(2), 10);
|
|
56
|
+
if (isNaN(step) || step <= 0) {
|
|
57
|
+
throw new Error(`Invalid step value in "${field}"`);
|
|
58
|
+
}
|
|
59
|
+
const values = [];
|
|
60
|
+
for (let i = range.min; i <= range.max; i += step) {
|
|
61
|
+
values.push(i);
|
|
62
|
+
}
|
|
63
|
+
return values;
|
|
64
|
+
}
|
|
65
|
+
// Range with step (1-10/2)
|
|
66
|
+
if (field.includes('/')) {
|
|
67
|
+
const [rangePart, stepStr] = field.split('/');
|
|
68
|
+
const step = parseInt(stepStr, 10);
|
|
69
|
+
if (isNaN(step) || step <= 0) {
|
|
70
|
+
throw new Error(`Invalid step in "${field}"`);
|
|
71
|
+
}
|
|
72
|
+
const [start, end] = parseRange(rangePart, type);
|
|
73
|
+
const values = [];
|
|
74
|
+
for (let i = start; i <= end; i += step) {
|
|
75
|
+
values.push(i);
|
|
76
|
+
}
|
|
77
|
+
return values;
|
|
78
|
+
}
|
|
79
|
+
// Simple range (1-5)
|
|
80
|
+
if (field.includes('-')) {
|
|
81
|
+
const [start, end] = parseRange(field, type);
|
|
82
|
+
const values = [];
|
|
83
|
+
for (let i = start; i <= end; i++) {
|
|
84
|
+
values.push(i);
|
|
85
|
+
}
|
|
86
|
+
return values;
|
|
87
|
+
}
|
|
88
|
+
// List (1,2,3 or MON,WED,FRI)
|
|
89
|
+
if (field.includes(',')) {
|
|
90
|
+
const values = [];
|
|
91
|
+
for (const part of field.split(',')) {
|
|
92
|
+
const val = parseValue(part.trim(), type);
|
|
93
|
+
values.push(val);
|
|
94
|
+
}
|
|
95
|
+
return [...new Set(values)].sort((a, b) => a - b);
|
|
96
|
+
}
|
|
97
|
+
// Single value
|
|
98
|
+
return [parseValue(field, type)];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Parse a range like "1-5" or "MON-FRI"
|
|
102
|
+
*/
|
|
103
|
+
function parseRange(rangeStr, type) {
|
|
104
|
+
const [startStr, endStr] = rangeStr.split('-');
|
|
105
|
+
return [
|
|
106
|
+
parseValue(startStr.trim(), type),
|
|
107
|
+
parseValue(endStr.trim(), type),
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Parse a single value (number or name)
|
|
112
|
+
*/
|
|
113
|
+
function parseValue(value, type) {
|
|
114
|
+
const lower = value.toLowerCase();
|
|
115
|
+
// Handle month names
|
|
116
|
+
if (type === 'month' && MONTH_NAMES[lower] !== undefined) {
|
|
117
|
+
return MONTH_NAMES[lower];
|
|
118
|
+
}
|
|
119
|
+
// Handle day names
|
|
120
|
+
if (type === 'dayOfWeek' && DAY_NAMES[lower] !== undefined) {
|
|
121
|
+
return DAY_NAMES[lower];
|
|
122
|
+
}
|
|
123
|
+
// Special: L (last day of month)
|
|
124
|
+
if (type === 'dayOfMonth' && lower === 'l') {
|
|
125
|
+
return -1; // Special marker for last day
|
|
126
|
+
}
|
|
127
|
+
const num = parseInt(value, 10);
|
|
128
|
+
const range = RANGES[type];
|
|
129
|
+
if (isNaN(num)) {
|
|
130
|
+
throw new Error(`Invalid value "${value}" for ${type}`);
|
|
131
|
+
}
|
|
132
|
+
if (num < range.min || num > range.max) {
|
|
133
|
+
throw new Error(`Value ${num} out of range [${range.min}-${range.max}] for ${type}`);
|
|
134
|
+
}
|
|
135
|
+
return num;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Calculate the next run time for a cron expression
|
|
139
|
+
*/
|
|
140
|
+
export function getNextRun(expression, from = new Date()) {
|
|
141
|
+
const { minute, hour, dayOfMonth, month, dayOfWeek } = expression;
|
|
142
|
+
// Start from the next minute
|
|
143
|
+
let candidate = new Date(from);
|
|
144
|
+
candidate.setSeconds(0, 0);
|
|
145
|
+
candidate.setMinutes(candidate.getMinutes() + 1);
|
|
146
|
+
// Limit search to prevent infinite loops
|
|
147
|
+
const maxIterations = 366 * 24 * 60; // ~1 year in minutes
|
|
148
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
149
|
+
if (matches(candidate, expression)) {
|
|
150
|
+
return candidate;
|
|
151
|
+
}
|
|
152
|
+
candidate.setMinutes(candidate.getMinutes() + 1);
|
|
153
|
+
}
|
|
154
|
+
throw new Error('Could not find next run time within 1 year');
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Check if a date matches the cron expression
|
|
158
|
+
*/
|
|
159
|
+
function matches(date, expression) {
|
|
160
|
+
const { minute, hour, dayOfMonth, month, dayOfWeek } = expression;
|
|
161
|
+
if (!matchesField(date.getMinutes(), minute))
|
|
162
|
+
return false;
|
|
163
|
+
if (!matchesField(date.getHours(), hour))
|
|
164
|
+
return false;
|
|
165
|
+
if (!matchesMonth(date.getMonth() + 1, month))
|
|
166
|
+
return false;
|
|
167
|
+
if (!matchesDayOfMonth(date.getDate(), dayOfMonth, date))
|
|
168
|
+
return false;
|
|
169
|
+
if (!matchesField(date.getDay(), dayOfWeek))
|
|
170
|
+
return false;
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
function matchesField(value, pattern) {
|
|
174
|
+
if (pattern === '*')
|
|
175
|
+
return true;
|
|
176
|
+
return pattern.includes(value);
|
|
177
|
+
}
|
|
178
|
+
function matchesMonth(value, pattern) {
|
|
179
|
+
if (pattern === '*')
|
|
180
|
+
return true;
|
|
181
|
+
return pattern.includes(value);
|
|
182
|
+
}
|
|
183
|
+
function matchesDayOfMonth(value, pattern, date) {
|
|
184
|
+
if (pattern === '*')
|
|
185
|
+
return true;
|
|
186
|
+
// Handle L (last day of month)
|
|
187
|
+
if (pattern.includes(-1)) {
|
|
188
|
+
const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
189
|
+
if (value === lastDay)
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
return pattern.includes(value);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Parse duration strings like "20m", "2h", "1h30m", "1d"
|
|
196
|
+
*/
|
|
197
|
+
export function parseDuration(duration) {
|
|
198
|
+
const regex = /^(?:(\d+)d)?\s*(?:(\d+)h)?\s*(?:(\d+)m)?\s*(?:(\d+)s?)?$/i;
|
|
199
|
+
const match = duration.trim().match(regex);
|
|
200
|
+
if (!match) {
|
|
201
|
+
throw new Error(`Invalid duration "${duration}". Use format: 1d, 2h, 30m, 1h30m`);
|
|
202
|
+
}
|
|
203
|
+
const days = parseInt(match[1] || '0', 10);
|
|
204
|
+
const hours = parseInt(match[2] || '0', 10);
|
|
205
|
+
const minutes = parseInt(match[3] || '0', 10);
|
|
206
|
+
const seconds = parseInt(match[4] || '0', 10);
|
|
207
|
+
const milliseconds = days * 24 * 60 * 60 * 1000 +
|
|
208
|
+
hours * 60 * 60 * 1000 +
|
|
209
|
+
minutes * 60 * 1000 +
|
|
210
|
+
seconds * 1000;
|
|
211
|
+
return {
|
|
212
|
+
milliseconds,
|
|
213
|
+
hours: days * 24 + hours,
|
|
214
|
+
minutes,
|
|
215
|
+
seconds,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Parse absolute time like "2025-01-10T09:00:00" or ISO string
|
|
220
|
+
*/
|
|
221
|
+
export function parseAt(at) {
|
|
222
|
+
// Try parsing as ISO date
|
|
223
|
+
const date = new Date(at);
|
|
224
|
+
if (!isNaN(date.getTime())) {
|
|
225
|
+
return date.getTime();
|
|
226
|
+
}
|
|
227
|
+
// Try parsing relative (e.g., "20m" shorthand for duration)
|
|
228
|
+
try {
|
|
229
|
+
const duration = parseDuration(at);
|
|
230
|
+
return Date.now() + duration.milliseconds;
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// Not a valid duration either
|
|
234
|
+
}
|
|
235
|
+
throw new Error(`Invalid time "${at}". Use ISO date (2025-01-10T09:00:00) or duration (20m)`);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Format a cron expression in human-readable form
|
|
239
|
+
*/
|
|
240
|
+
export function formatCron(expression) {
|
|
241
|
+
const parts = [];
|
|
242
|
+
if (expression.minute !== '*') {
|
|
243
|
+
parts.push(`minute(s): ${Array.isArray(expression.minute) ? expression.minute.join(', ') : expression.minute}`);
|
|
244
|
+
}
|
|
245
|
+
if (expression.hour !== '*') {
|
|
246
|
+
parts.push(`hour(s): ${Array.isArray(expression.hour) ? expression.hour.join(', ') : expression.hour}`);
|
|
247
|
+
}
|
|
248
|
+
if (expression.dayOfMonth !== '*') {
|
|
249
|
+
parts.push(`day(s): ${Array.isArray(expression.dayOfMonth) ? expression.dayOfMonth.join(', ') : expression.dayOfMonth}`);
|
|
250
|
+
}
|
|
251
|
+
if (expression.month !== '*') {
|
|
252
|
+
parts.push(`month(s): ${Array.isArray(expression.month) ? expression.month.join(', ') : expression.month}`);
|
|
253
|
+
}
|
|
254
|
+
if (expression.dayOfWeek !== '*') {
|
|
255
|
+
parts.push(`weekday(s): ${Array.isArray(expression.dayOfWeek) ? expression.dayOfWeek.join(', ') : expression.dayOfWeek}`);
|
|
256
|
+
}
|
|
257
|
+
return parts.length > 0 ? parts.join(', ') : 'every minute';
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Validate a cron expression
|
|
261
|
+
*/
|
|
262
|
+
export function validateCron(expression) {
|
|
263
|
+
try {
|
|
264
|
+
parseCron(expression);
|
|
265
|
+
return { valid: true };
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
return { valid: false, error: error.message };
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Common cron presets
|
|
273
|
+
*/
|
|
274
|
+
export const CRON_PRESETS = {
|
|
275
|
+
'@yearly': '0 0 1 1 *',
|
|
276
|
+
'@annually': '0 0 1 1 *',
|
|
277
|
+
'@monthly': '0 0 1 * *',
|
|
278
|
+
'@weekly': '0 0 * * 0',
|
|
279
|
+
'@daily': '0 0 * * *',
|
|
280
|
+
'@midnight': '0 0 * * *',
|
|
281
|
+
'@hourly': '0 * * * *',
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* Parse preset or standard expression
|
|
285
|
+
*/
|
|
286
|
+
export function parseExpression(expression, timezone) {
|
|
287
|
+
const normalized = expression.trim();
|
|
288
|
+
// Check for presets
|
|
289
|
+
if (normalized in CRON_PRESETS) {
|
|
290
|
+
return parseCron(CRON_PRESETS[normalized], timezone);
|
|
291
|
+
}
|
|
292
|
+
return parseCron(normalized, timezone);
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../src/cron/parser.ts"],"names":[],"mappings":"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"}
|