cron-validate

A configurable TypeScript/JavaScript validator for cron expressions, with presets for crontab, node-cron, cron-schedule, and AWS CloudWatch.

Library
npm
v1.5.3
82stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
50/100Fair
Development Activity48
Maintenance32
Community40
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
71/100Good
Architecture74
Code Quality78
Innovation62
Learning Curve70

cron-validate checks whether a cron expression string is well-formed before it gets handed to a scheduler. Rather than assuming one dialect of cron syntax, it ships with option presets for classic crontab, npm’s node-cron, cron-schedule, and AWS CloudWatch Events, each of which enables or restricts fields like seconds, years, aliases, blank-day markers, last-day-of-month (L), nearest-weekday (W), and Nth-weekday-of-month (#) independently.

Validation results come back as a Valid/Err result type (an adaptation of the neverthrow pattern) rather than throwing, so callers explicitly branch on isValid()/isError() and read either the parsed cron fields or a list of human-readable error strings. Field-level constraints (min/max/lower/upper limits per field) can also be overridden per call without redefining a whole preset, and options are cached by preset+override key to avoid re-validating identical configurations.

It’s a small, dependency-light building block (only yup at runtime) meant to sit in front of whatever actually runs the schedule — projects like Bree use it to reject malformed cron strings before a job is ever scheduled.

What You Get

  • A single cron(cronString, options) function returning a typed Valid/Err result instead of throwing on invalid input
  • Four built-in presets — default/crontab, npm-node-cron, npm-cron-schedule, and aws-cloud-watch — each with different field counts and enabled features
  • Support for extended cron syntax: seconds and years fields, month/weekday aliases (jan, mon), blank-day ?, last-day-of-month L, nearest-weekday W, and Nth-weekday-of-month #
  • Per-call override options to relax or tighten field limits (e.g. custom lower/upper bounds) without registering a new preset
  • A registerOptionPreset API for defining and reusing a fully custom validation preset across an application
  • Descriptive, field-specific error messages (e.g. which field failed and why) rather than a single generic failure

Common Use Cases

  • Validating a user-supplied cron string in a scheduling UI before saving a scheduled job
  • Guarding a job scheduler (like node-cron or Bree) so malformed cron expressions are rejected before a task is registered
  • Enforcing a stricter or platform-specific cron dialect, such as AWS CloudWatch Events’ required blank-day field
  • Building a custom internal DSL for scheduling by registering a project-specific option preset with its own field limits

Under The Hood

Architecture cron-validate is a small, linear pipeline rather than a layered system: the exported cron() function in src/index.ts first resolves and validates the active options (validateOptions in src/option.ts, which merges a named or custom preset with any per-call override and validates the merged shape with a yup schema), then splits the raw cron string into positional fields (splitCronString) based on how many fields the resolved options expect (5, 6, or 7 depending on useSeconds/useYears), and finally runs one field-checker per cron field (src/fieldCheckers/*.ts) that each call into a shared checkField helper (src/helper.ts) for range/alias/wildcard/list/step parsing. Results flow through a small Result/Valid/Err type (src/result.ts, adapted from the neverthrow pattern) instead of exceptions, so every stage can short-circuit by returning an Err that the caller inspects with isValid()/isError(). Swapping the core Result abstraction would ripple through every field checker and the public API, since all of them depend on its map/mapErr contract.

Tech Stack The library is written in TypeScript (targeting ES module output per package.json’s "type": "module") and has exactly one runtime dependency, yup, used both to validate the shape of preset/option objects and to strip unknown keys via stripUnknown. Builds go through tsc against a dedicated tsconfig.build.json, and releases are fully automated with semantic-release (commit-analyzer, changelog, npm, GitHub, and git plugins chained together) gated behind a scripts/remove-type.ts/restore-type.ts pair that temporarily toggles the type field for CJS-compatible publishing. Linting uses ESLint with airbnb-base plus @typescript-eslint, and Prettier handles formatting; dependency freshness is managed by Renovate.

Code Quality Testing uses Jest with ts-jest, and the suite is substantial relative to the library’s size — index.test.ts and a dedicated matrix.test.ts (which appears to exercise field/preset combinations systematically) together account for over half of the repository’s source lines, run with coverage enabled by default (jest --coverage). Field checkers are short, single-purpose functions with early-return guard clauses and inline comments citing the exact upstream cron implementations (Quartz Scheduler) their edge-case rules were modeled on. Typing is consistently applied throughout (Options, OptionPreset, InputOptions, CronData are all explicit interfaces/types in src/types.ts and src/index.ts), and error paths return typed string arrays rather than throwing, though a TODO: Right error return comment in src/index.ts signals the author considers the current error-aggregation shape provisional.

What Makes It Unique Most cron parsers validate against a single fixed dialect; cron-validate’s preset system treats the dialect itself as configurable data — enabling/disabling whole fields (seconds, years), toggling alias support, and switching which extended symbols (L, W, #, ?) are legal, all through one shared field-checking core rather than separate parsers per platform. Combining this with per-call overrides and a registerOptionPreset extension point lets consumers express platform-specific cron rules (crontab vs AWS CloudWatch vs a scheduler library) without forking or reimplementing the validator, which is a deliberate design choice rather than a byproduct of general-purpose parsing.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search