# 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 (`*/n` and `a-b/n` and `a/n`), case-insensitive aliases (`JAN`-`DEC` for month, `SUN`-`SAT` for day-of-week). - Day-of-week normalization: both `0` and `7` are accepted for Sunday and collapse to `0` after 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 distinct `CronErrorCode`. ## Usage: Basic Example ```typescript 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 ```typescript import { parseField, rangeFor, CronError, CRON_CODES } from "@suaveplan/cron"; function expandOrFallback(token: string, kind: Parameters[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. Throws `CronError` with codes `CRON.UNSUPPORTED_SYNTAX`, `CRON.FIELD_OUT_OF_RANGE`, or `CRON.INVALID_EXPRESSION` per 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>` (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.freeze`d to prevent downstream mutation.