Communicationv0.1.9
@tekir/cron
Cron scheduler with named jobs, pause/resume, and overlap safety.
Installation
$
bun add @tekir/cronFeatures
- 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.xdependency 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-jobcron.add(name, pattern, cb, { timezone }). Patterns then evaluate in that zone instead of the host's local time, so5 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/core0.1.16:await import('@tekir/core')ran beforecaptureCallerFile, 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 forcaptureCallerFile/loadDirEntrieskeep the capture synchronous on registerDir entry. Pair with@tekir/core0.1.16+.
v0.1.3May 4, 2026
- **Breaking**:
cron.registerDir(...)now resolves a relative path against the caller's own directory, notprocess.cwd(). Matches the AST inliner's build-time behavior soawait cron.registerDir('./jobs')fromapi/index.tslands atapi/jobsregardless of cwd, and thecd <root> && tekir serve --dev --entry api/index.tsmonorepo dev pattern works as-is. Passoptions.from = process.cwd()for the old cwd-relative behavior on a specific call site.
v0.1.2May 4, 2026
registerDirwarning now names the source file:[cron.registerDir] core/jobs/typo.ts: skipped (unrecognized export shape: object). Replaces a genericSkipping ...log line that did not say which file dropped out.- Single
No modules loadedwarning with an inliner hint whenregisterDirmatches 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__schedulesmetadata) go throughcron.register, functional registrars (export default async (cron) => cron.add(...)) are invoked with the manager, and classes with aregister(cron)method are constructed and called.
v0.1.0April 1, 2026
- Initial release