UNPKG

@wuwei-labs/srsly

Version:
157 lines 4.63 kB
/** * @purpose Payment schedule parameter conversion utilities * * Converts user-friendly schedule formats to strings for use with Solana programs. * Supports common shortcuts and cron expressions. */ /** * Common schedule shortcuts */ export const SCHEDULE_SHORTCUTS = [ '@hourly', '@daily', '@weekly', '@monthly', '@yearly', '@annually', '@decasecond', '@minute', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'annually', 'decasecond', 'minute', ]; /** * Mapping of shortcuts without @ prefix to their @ equivalents */ const SHORTCUT_TO_AT_PREFIX = { hourly: '@hourly', daily: '@daily', weekly: '@weekly', monthly: '@monthly', yearly: '@yearly', annually: '@annually', decasecond: '@decasecond', minute: '@minute', }; /** * Basic cron expression validation pattern * * Supports: * - Standard 5-field cron: "0 * * * *" * - Extended 6-field cron with seconds: "0 0 * * * *" * - @shortcuts: "@hourly", "@daily", etc. */ const CRON_PATTERN = /^(@\w+|[\d\*\/\-,]+(\s+[\d\*\/\-,]+){4,5})$/; /** * Normalize payment schedule input to program-compatible format * * @param schedule - Payment schedule string * @returns Normalized schedule string for Solana program * @throws Error if schedule format is invalid * * @example * ```typescript * normalizeSchedule('daily') // '@daily' * normalizeSchedule('@hourly') // '@hourly' * normalizeSchedule('0 * * * *') // '0 * * * *' * normalizeSchedule('0 0 * * * *') // '0 0 * * * *' (with seconds) * ``` */ export function normalizeSchedule(schedule) { if (!schedule || typeof schedule !== 'string') { throw new Error(`Invalid schedule format. Expected string, got: ${typeof schedule}`); } // Trim whitespace const trimmed = schedule.trim(); if (!trimmed) { throw new Error('Schedule cannot be empty'); } // If it already has @ prefix, validate and return if (trimmed.startsWith('@')) { if (!validateScheduleFormat(trimmed)) { throw new Error(`Invalid schedule shortcut: ${trimmed}`); } return trimmed.toLowerCase(); } // Check if it's a known shortcut without @ prefix const lowerTrimmed = trimmed.toLowerCase(); if (lowerTrimmed in SHORTCUT_TO_AT_PREFIX) { return SHORTCUT_TO_AT_PREFIX[lowerTrimmed]; } // Otherwise treat as cron expression - validate and return as-is if (!validateScheduleFormat(trimmed)) { throw new Error(`Invalid schedule format. Expected @shortcut or cron expression. ` + `Valid shortcuts: ${Object.keys(SHORTCUT_TO_AT_PREFIX).join(', ')}. ` + `Got: "${trimmed}"`); } return trimmed; } /** * Validate schedule format * * Checks if a schedule string is either: * - A valid @shortcut * - A valid cron expression (5 or 6 fields) * * @param schedule - Schedule string to validate * @returns True if valid, false otherwise * * @example * ```typescript * validateScheduleFormat('@daily') // true * validateScheduleFormat('0 * * * *') // true * validateScheduleFormat('invalid') // false * ``` */ export function validateScheduleFormat(schedule) { if (!schedule || typeof schedule !== 'string') { return false; } const trimmed = schedule.trim(); // Check if it's a @shortcut if (trimmed.startsWith('@')) { const shortcut = trimmed.toLowerCase(); return SCHEDULE_SHORTCUTS.includes(shortcut); } // Check if it matches cron pattern return CRON_PATTERN.test(trimmed); } /** * Convert schedule string to human-readable description * * @param schedule - Normalized schedule string * @returns Human-readable description * * @example * ```typescript * formatSchedule('@daily') // "Daily" * formatSchedule('@hourly') // "Hourly" * formatSchedule('0 * * * *') // "Custom: 0 * * * *" * ``` */ export function formatSchedule(schedule) { const trimmed = schedule.trim().toLowerCase(); // Handle @shortcuts if (trimmed.startsWith('@')) { const shortcut = trimmed.slice(1); // Remove @ return shortcut.charAt(0).toUpperCase() + shortcut.slice(1); } // Handle cron expressions return `Custom: ${trimmed}`; } /** * Check if a schedule is a known shortcut * * @param schedule - Schedule string to check * @returns True if it's a shortcut (with or without @) */ export function isScheduleShortcut(schedule) { const lower = schedule.toLowerCase(); return SCHEDULE_SHORTCUTS.includes(lower); } //# sourceMappingURL=schedule.js.map