From cf3cbfba9ed19bcf13a9e68de0b95d9551a44aa2 Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Sat, 13 Jun 2026 17:31:02 -0300 Subject: [PATCH] Simplify the cron-to-schedule inference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite inferScheduleFromCron: bail once on a pinned month, group the branches by cadence (sub-hourly / hourly / daily / weekly / monthly), and share the hour+minute via one `clock` object instead of repeating the same guards in eight stacked conditionals. Behavior-preserving — verified the generate↔infer round-trip across every preset. --- .../automations/schedule-summary.ts | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/resources/js/components/automations/schedule-summary.ts b/resources/js/components/automations/schedule-summary.ts index 916401d9..c71531c4 100644 --- a/resources/js/components/automations/schedule-summary.ts +++ b/resources/js/components/automations/schedule-summary.ts @@ -26,33 +26,40 @@ const inferScheduleFromCron = (cron: string): Partial | null => { if (parts.length !== 5) return null; const [minute, hour, dom, month, dow] = parts; - const intervalOf = (token: string): number | null => - token.startsWith('*/') && /^\d+$/.test(token.slice(2)) ? Number(token.slice(2)) : null; - const isNum = (t: string) => /^\d+$/.test(t); + if (month !== '*') return null; // no preset pins a month - if (minute === '*' && hour === '*' && dom === '*' && month === '*' && dow === '*') { - return { schedule_field: ScheduleField.Minutes, schedule_minutes_interval: 1 }; + const interval = (token: string): number | null => (/^\*\/\d+$/.test(token) ? Number(token.slice(2)) : null); + const isNum = (token: string) => /^\d+$/.test(token); + + // Sub-hourly: every minute or every Nth minute, regardless of hour/day. + if (hour === '*' && dom === '*' && dow === '*') { + const every = minute === '*' ? 1 : interval(minute); + return every === null ? null : { schedule_field: ScheduleField.Minutes, schedule_minutes_interval: every }; } - const m = intervalOf(minute); - if (m !== null && hour === '*' && dom === '*' && month === '*' && dow === '*') { - return { schedule_field: ScheduleField.Minutes, schedule_minutes_interval: m }; + + if (!isNum(minute)) return null; + const schedule_minute = Number(minute); + + // Hourly: a fixed minute past every Nth hour. + const everyHours = interval(hour); + if (everyHours !== null && dom === '*' && dow === '*') { + return { schedule_field: ScheduleField.Hours, schedule_hours_interval: everyHours, schedule_minute }; } - const h = intervalOf(hour); - if (isNum(minute) && h !== null && dom === '*' && month === '*' && dow === '*') { - return { schedule_field: ScheduleField.Hours, schedule_hours_interval: h, schedule_minute: Number(minute) }; + + if (!isNum(hour)) return null; + const clock = { schedule_hour: Number(hour), schedule_minute }; + + // Daily: at `clock`, every Nth day (a bare `*` means every day). + if (dow === '*' && (dom === '*' || interval(dom) !== null)) { + return { schedule_field: ScheduleField.Days, schedule_days_interval: interval(dom) ?? 1, ...clock }; } - const d = intervalOf(dom); - if (isNum(minute) && isNum(hour) && d !== null && month === '*' && dow === '*') { - return { schedule_field: ScheduleField.Days, schedule_days_interval: d, schedule_hour: Number(hour), schedule_minute: Number(minute) }; + // Weekly: at `clock`, on the listed weekdays. + if (dom === '*' && /^\d+(,\d+)*$/.test(dow)) { + return { schedule_field: ScheduleField.Weeks, schedule_weekdays: dow.split(',').map(Number), ...clock }; } - if (isNum(minute) && isNum(hour) && dom === '*' && month === '*' && dow === '*') { - return { schedule_field: ScheduleField.Days, schedule_days_interval: 1, schedule_hour: Number(hour), schedule_minute: Number(minute) }; - } - if (isNum(minute) && isNum(hour) && dom === '*' && month === '*' && /^\d+(,\d+)*$/.test(dow)) { - return { schedule_field: ScheduleField.Weeks, schedule_weekdays: dow.split(',').map(Number), schedule_hour: Number(hour), schedule_minute: Number(minute) }; - } - if (isNum(minute) && isNum(hour) && isNum(dom) && month === '*' && dow === '*') { - return { schedule_field: ScheduleField.Months, schedule_day_of_month: Number(dom), schedule_hour: Number(hour), schedule_minute: Number(minute) }; + // Monthly: at `clock`, on a fixed day of the month. + if (dow === '*' && isNum(dom)) { + return { schedule_field: ScheduleField.Months, schedule_day_of_month: Number(dom), ...clock }; } return null; };