From 657fc53d8b4fc1c64996de14f6c62cc068235f97 Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 11 Nov 2026 13:05:05 -0800 Subject: [PATCH] chore(deps): upgrade cronstrue to 3.38.0 Use cronstrue's trimHoursLeadingZero option instead of a regex over its output, and update the schedule description tests to the new English wording. --- .../sim/lib/workflows/schedules/utils.test.ts | 29 +++++++------------ apps/sim/lib/workflows/schedules/utils.ts | 11 ++++--- apps/sim/package.json | 2 +- bun.lock | 4 +-- 4 files changed, 19 insertions(+), 27 deletions(-) diff --git a/apps/sim/lib/workflows/schedules/utils.test.ts b/apps/sim/lib/workflows/schedules/utils.test.ts index 284b6bc1df4..b2d39e6fbc8 100644 --- a/apps/sim/lib/workflows/schedules/utils.test.ts +++ b/apps/sim/lib/workflows/schedules/utils.test.ts @@ -421,27 +421,20 @@ describe('Schedule Utilities', () => { }) describe('parseCronToHumanReadable', () => { - it.concurrent('should parse common cron patterns using cronstrue', () => { - // cronstrue produces "Every minute" for '* * * * *' + it.concurrent('should describe the schedules the builder generates', () => { expect(parseCronToHumanReadable('* * * * *')).toBe('Every minute') - - // cronstrue produces "Every 15 minutes" for '*/15 * * * *' expect(parseCronToHumanReadable('*/15 * * * *')).toBe('Every 15 minutes') + expect(parseCronToHumanReadable('1 * * * *')).toBe('At 1 minute past the hour') + expect(parseCronToHumanReadable('30 * * * *')).toBe('At 30 minutes past the hour') + expect(parseCronToHumanReadable('0 9 * * *')).toBe('At 9:00 AM') + expect(parseCronToHumanReadable('30 14 * * *')).toBe('At 2:30 PM') + expect(parseCronToHumanReadable('0 9 * * 1')).toBe('At 9:00 AM, only on Monday') + expect(parseCronToHumanReadable('30 14 15 * *')).toBe('At 2:30 PM, on day 15 of the month') + }) - // cronstrue produces "At 30 minutes past the hour" for '30 * * * *' - expect(parseCronToHumanReadable('30 * * * *')).toContain('30 minutes past the hour') - - // cronstrue produces "At 9:00 AM" for '0 9 * * *' (no leading zero on hour) - expect(parseCronToHumanReadable('0 9 * * *')).toContain('9:00 AM') - - // cronstrue produces "At 2:30 PM" for '30 14 * * *' (no leading zero on hour) - expect(parseCronToHumanReadable('30 14 * * *')).toContain('2:30 PM') - - // cronstrue produces "At 09:00 AM, only on Monday" for '0 9 * * 1' - expect(parseCronToHumanReadable('0 9 * * 1')).toContain('Monday') - - // cronstrue produces "At 02:30 PM, on day 15 of the month" for '30 14 15 * *' - expect(parseCronToHumanReadable('30 14 15 * *')).toContain('15') + it.concurrent('should describe step schedules in custom cron expressions', () => { + expect(parseCronToHumanReadable('0 */2 * * *')).toBe('On the hour, every 2 hours') + expect(parseCronToHumanReadable('0 0 */2 * *')).toBe('At 12:00 AM, every 2 days in a month') }) it.concurrent('should describe the nth weekday of the month', () => { diff --git a/apps/sim/lib/workflows/schedules/utils.ts b/apps/sim/lib/workflows/schedules/utils.ts index 4e33965648a..393e650b7f2 100644 --- a/apps/sim/lib/workflows/schedules/utils.ts +++ b/apps/sim/lib/workflows/schedules/utils.ts @@ -450,12 +450,11 @@ export function calculateNextRunTime( export const parseCronToHumanReadable = (cronExpression: string, timezone?: string): string => { try { const forDisplay = cronExpression.replace(/([0-7])#L\b/g, '$1L') - const baseDescription = cronstrue - .toString(forDisplay, { - use24HourTimeFormat: false, - verbose: false, - }) - .replace(/\b0(\d:\d{2})/g, '$1') + const baseDescription = cronstrue.toString(forDisplay, { + use24HourTimeFormat: false, + trimHoursLeadingZero: true, + verbose: false, + }) if (timezone && timezone !== 'UTC') { const tzAbbr = getTimezoneAbbreviation(timezone) diff --git a/apps/sim/package.json b/apps/sim/package.json index 42cc8cf119e..f096f148c12 100644 --- a/apps/sim/package.json +++ b/apps/sim/package.json @@ -206,7 +206,7 @@ "class-variance-authority": "^0.7.1", "cmdk": "^1.0.0", "croner": "^9.0.0", - "cronstrue": "3.3.0", + "cronstrue": "3.38.0", "csv-parse": "7.0.3", "date-fns": "4.4.0", "decimal.js": "10.6.0", diff --git a/bun.lock b/bun.lock index ec60d0537a9..307c2027b94 100644 --- a/bun.lock +++ b/bun.lock @@ -360,7 +360,7 @@ "class-variance-authority": "^0.7.1", "cmdk": "^1.0.0", "croner": "^9.0.0", - "cronstrue": "3.3.0", + "cronstrue": "3.38.0", "csv-parse": "7.0.3", "date-fns": "4.4.0", "decimal.js": "10.6.0", @@ -2795,7 +2795,7 @@ "croner": ["croner@9.1.0", "", {}, "sha512-p9nwwR4qyT5W996vBZhdvBCnMhicY5ytZkR4D1Xj0wuTDEiMnjwR57Q3RXYY/s0EpX6Ay3vgIcfaR+ewGHsi+g=="], - "cronstrue": ["cronstrue@3.3.0", "", { "bin": { "cronstrue": "bin/cli.js" } }, "sha512-iwJytzJph1hosXC09zY8F5ACDJKerr0h3/2mOxg9+5uuFObYlgK0m35uUPk4GCvhHc2abK7NfnR9oMqY0qZFAg=="], + "cronstrue": ["cronstrue@3.38.0", "", { "bin": { "cronstrue": "bin/cli.js" } }, "sha512-i10xR7fS4AH9LKwmt3gYdt/5lSsB2qFGSNfC8aeyYybxo48DCMz+nUrSVI4kUj8yo+SgTbMJqp/BWEem9avlcA=="], "cross-dirname": ["cross-dirname@0.1.0", "", {}, "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q=="],