3.5 KiB
parseField
(no submodules)
Purpose
parseField is the single-field tokenizer at the heart of cron parsing.
Each of the five (or six/seven) whitespace-separated positions in a cron
expression is independently expanded into the sorted, unique numeric set
of values it matches. The function is total over its FieldKind
discriminator: it accepts the canonical crontab syntax surface (literals,
ranges, lists, steps, wildcards, and alphabetic aliases for month +
day-of-week) and rejects every Quartz extension (L/W/#/?) with
typed errors so the caller can branch on err.code.
Features
- Wildcards (
*), literals, comma-separated lists, hyphenated ranges, step values (*/nanda-b/nanda/n), case-insensitive aliases (JAN-DECfor month,SUN-SATfor day-of-week). - Day-of-week normalization: both
0and7are accepted for Sunday and collapse to0after sorting and deduplication. - Range bounds per field exposed via
rangeFor(kind)for downstream next-run computations. - Typed errors via
CronError: out-of-range numerics, unsupported tokens, and malformed atoms each surface a distinctCronErrorCode.
Usage: Basic Example
import { parseField } from "@suaveplan/cron";
const minutes = parseField("*/15", "minute");
console.log(Array.from(minutes)); // [0, 15, 30, 45]
const weekdays = parseField("MON-FRI", "dayOfWeek");
console.log(Array.from(weekdays)); // [1, 2, 3, 4, 5]
Usage: Advanced Example
import { parseField, rangeFor, CronError, CRON_CODES } from "@suaveplan/cron";
function expandOrFallback(token: string, kind: Parameters<typeof parseField>[1]) {
try {
return parseField(token, kind);
} catch (err) {
if (err instanceof CronError && err.code === CRON_CODES.UNSUPPORTED_SYNTAX) {
const range = rangeFor(kind);
return Object.freeze(
Array.from({ length: range.max - range.min + 1 }, (_, i) => range.min + i)
);
}
throw err;
}
}
console.log(expandOrFallback("L", "dayOfMonth")); // falls back to full range
API Reference
parseField(token: string, kind: FieldKind): readonly number[]— returns a frozen, sorted, deduplicated value set. ThrowsCronErrorwith codesCRON.UNSUPPORTED_SYNTAX,CRON.FIELD_OUT_OF_RANGE, orCRON.INVALID_EXPRESSIONper the failure mode.rangeFor(kind: FieldKind): FieldRange— inclusive{min, max}for the given field kind.FieldKind—"second" | "minute" | "hour" | "dayOfMonth" | "month" | "dayOfWeek" | "year".FieldRange—{ readonly min: number; readonly max: number }.FieldAliases—Readonly<Record<string, number>>(internal alias map shape).
Implementation Notes
The tokenizer walks comma-separated terms left-to-right, dispatching each
term through the step parser before falling through to the range parser.
Step extraction is bounded to a single / per term; nested steps
(*/15/2) are rejected up front. Range expansion is O(n) over the result
set and feeds a Set for deduplication before a final monotonically
sorted Array.from. Day-of-week values are normalized after expansion so
both 0,7 and SAT,SUN collapse correctly. Unsupported Quartz tokens
(L/W/#/?) are caught by a single regex before any further parsing
to keep the error path cheap; alias resolution is case-insensitive via
toUpperCase. The output array is Object.freezed to prevent downstream
mutation.