tekir
All Packages
Communicationv0.1.9

@tekir/cron

Cron scheduler with named jobs, pause/resume, and overlap safety.

Installation

$bun add @tekir/cron

Features

  • Named cron jobs with add() and remove()
  • Standard 5/6-field cron expressions
  • Pause and resume individual jobs
  • Built-in Patterns constants for common schedules
  • Automatic error handling per tick
  • Fixed-timezone scheduling (UTC or any IANA zone)
  • CronProvider for DI integration

Quick Example

TypeScript
import { Cron, Patterns } from '@tekir/cron'

const cron = new Cron()

await cron.add('cleanup', '0 * * * *', async () => {
  console.log('Running hourly cleanup')
})

await cron.add('heartbeat', Patterns.EVERY_MINUTE, () => {
  console.log('Alive')
})

Changelog

v0.1.9LatestSeptember 16, 2026
  • Published output now uses the shared Node-targeted ESM bundle pipeline with external dependencies and generated TypeScript declarations, while Bun consumers keep the native source export.
v0.1.8July 23, 2026
  • Package metadata now follows the shared compatible 0.1.x dependency range used by this coordinated Tekir release.
v0.1.7July 16, 2026
  • Cron overlap protection and error tracking now recognize Promise-compatible thenables, not only native Promise instances.
v0.1.6July 2, 2026
  • Jobs can now run in a fixed IANA timezone: new Cron({ timezone: 'UTC' }), cron.setTimezone('UTC') before registering, or a per-job cron.add(name, pattern, cb, { timezone }). Patterns then evaluate in that zone instead of the host's local time, so 5 0 1 * *-style boundaries line up with UTC-based date math regardless of the server's timezone. Omitting it keeps the previous local-time behavior.
  • Found and fixed with Fable.
v0.1.5June 13, 2026
  • Overlapping runs of the same job are now prevented. A per-job in-flight flag (plus the underlying scheduler's overlap protection) skips a tick that arrives while the previous async run is still going, so a long job no longer runs concurrently with itself.
  • An invalid cron pattern now throws at registration time with the job name and pattern, and the job is not registered, instead of failing later at tick time.
  • Added an async shutdown() that stops every job's timer and clears the registry, so no further ticks fire after it returns.
  • Found and fixed with Fable.
v0.1.4May 4, 2026
  • Fixes 0.1.3's caller capture in cron.registerDir. Same root cause as @tekir/core 0.1.16: await import('@tekir/core') ran before captureCallerFile, so the user's frame was already gone by the time the stack was inspected and the warning printed (resolved against native). Static top-level imports for captureCallerFile/loadDirEntries keep the capture synchronous on registerDir entry. Pair with @tekir/core 0.1.16+.
v0.1.3May 4, 2026
  • **Breaking**: cron.registerDir(...) now resolves a relative path against the caller's own directory, not process.cwd(). Matches the AST inliner's build-time behavior so await cron.registerDir('./jobs') from api/index.ts lands at api/jobs regardless of cwd, and the cd <root> && tekir serve --dev --entry api/index.ts monorepo dev pattern works as-is. Pass options.from = process.cwd() for the old cwd-relative behavior on a specific call site.
v0.1.2May 4, 2026
  • registerDir warning now names the source file: [cron.registerDir] core/jobs/typo.ts: skipped (unrecognized export shape: object). Replaces a generic Skipping ... log line that did not say which file dropped out.
  • Single No modules loaded warning with an inliner hint when registerDir matches zero modules. Replaces the previous silent failure where a misconfigured production bundle would just have no jobs attached with no log line explaining why.
v0.1.1May 3, 2026
  • cron.registerDir(path) loads every file in a folder and registers whatever each module exports as a job: decorator classes (the @Schedule('* * * * *') pattern with __schedules metadata) go through cron.register, functional registrars (export default async (cron) => cron.add(...)) are invoked with the manager, and classes with a register(cron) method are constructed and called.
v0.1.0April 1, 2026
  • Initial release

Other Communication packages