fix: allow 6-field cron expressions with seconds

The cron editor rejected sub-minute expressions like `*/30 * * * * *`
because validation required exactly 5 fields. Now accepts both 5-field
(standard) and 6-field (with seconds) cron expressions.

Also fixes schedule type auto-detection to correctly fall back to
'custom' for 6-field expressions instead of misinterpreting field
positions.

Fixes #819
This commit is contained in:
GiulioSavini authored and jarek committed 2026-04-19 16:01:50 +02:00
1 parent d10f6dfd6d
commit 8671dfaf32
2 files changed
+5 -13

No files matched your search

+4 -12
View File
@@ -19,7 +19,7 @@
// Detect schedule type from cron expression // Detect schedule type from cron expression
function detectScheduleType(cron: string): 'daily' | 'weekly' | 'custom' { function detectScheduleType(cron: string): 'daily' | 'weekly' | 'custom' {
const parts = cron.split(' '); const parts = cron.split(' ');
if (parts.length < 5) return 'custom'; if (parts.length !== 5) return 'custom';
const [min, hr, day, month, dow] = parts; const [min, hr, day, month, dow] = parts;
@@ -137,23 +137,15 @@
onchange(newValue); onchange(newValue);
} }
// Validate cron expression // Validate cron expression (supports 5-field and 6-field with seconds)
function isValidCron(cron: string): boolean { function isValidCron(cron: string): boolean {
const parts = cron.trim().split(/\s+/); const parts = cron.trim().split(/\s+/);
if (parts.length !== 5) return false; if (parts.length !== 5 && parts.length !== 6) return false;
const [min, hr, day, month, dow] = parts;
// Basic pattern validation (number, *, */n, range, list) // Basic pattern validation (number, *, */n, range, list)
const cronFieldPattern = /^(\*|(\*\/\d+)|\d+(-\d+)?(,\d+(-\d+)?)*)$/; const cronFieldPattern = /^(\*|(\*\/\d+)|\d+(-\d+)?(,\d+(-\d+)?)*)$/;
return ( return parts.every((part) => cronFieldPattern.test(part));
cronFieldPattern.test(min) &&
cronFieldPattern.test(hr) &&
cronFieldPattern.test(day) &&
cronFieldPattern.test(month) &&
cronFieldPattern.test(dow)
);
} }
// Human-readable description using cronstrue // Human-readable description using cronstrue
@@ -66,7 +66,7 @@ export const POST: RequestHandler = async ({ params, url, request, cookies }) =>
let scheduleType: 'daily' | 'weekly' | 'custom' = 'custom'; let scheduleType: 'daily' | 'weekly' | 'custom' = 'custom';
if (cronExpression) { if (cronExpression) {
const parts = cronExpression.split(' '); const parts = cronExpression.split(' ');
if (parts.length >= 5) { if (parts.length === 5) {
const [, , day, month, dow] = parts; const [, , day, month, dow] = parts;
if (dow !== '*' && day === '*' && month === '*') { if (dow !== '*' && day === '*' && month === '*') {
scheduleType = 'weekly'; scheduleType = 'weekly';