Skip to content
Warlock.js v4

API Reference

Every public export of @warlock.js/scheduler, in one place. For the narrative version of any of these, follow the cross-links into the guides.

import {
scheduler, // default Scheduler singleton
Scheduler, // the class, for isolated instances
job, // Job factory
Job, // the class
parseCron, // CronParser factory
CronParser, // the class
} from "@warlock.js/scheduler";
import type {
TimeType,
Day,
JobIntervals,
JobResult,
JobStatus,
RetryConfig,
SchedulerEvents,
CronFields,
} from "@warlock.js/scheduler";

Creates a Job. The callback is (job: Job) => Promise<any> — it receives the job instance, so you can read job.name / job.lastRun / job.isRunning at run time.

const cleanup = job("cleanup", async () => {
await db.deleteExpiredTokens();
});

Creates a standalone CronParser — useful for previewing next-run times without scheduling anything. Equivalent to new CronParser(expression).

A schedule + a callback. Every configuration method returns this for chaining and recomputes nextRun on the spot. The fluent methods and cron() are mutually exclusive — setting one clears the other.

MethodEquivalentNotes
every(value, unit)Throws if value is 0, negative, NaN, or Infinity
everySecond()every(1, "second")
everySeconds(n)every(n, "second")
everyMinute()every(1, "minute")
everyMinutes(n)every(n, "minute")
everyHour()every(1, "hour")
everyHours(n)every(n, "hour")
everyDay()every(1, "day")
daily()every(1, "day")alias of everyDay()
twiceDaily()every(12, "hour")
everyWeek()every(1, "week")
weekly()every(1, "week")alias of everyWeek()
everyMonth()every(1, "month")
monthly()every(1, "month")alias of everyMonth()
everyYear()every(1, "year")
yearly()every(1, "year")alias of everyYear()
always()every(1, "minute")

unit is a TimeType. See Defining Jobs.

"HH:mm" or "HH:mm:ss". Throws at definition time on a malformed string or out-of-range component (hour > 23, minute/second > 59).

A Day string ("monday", …) or a day-of-month number 1–31. Numeric values outside 1–31 throw. A numeric day also sets intervals.dayOfMonthMode to "specific".

type is "day" | "month" | "year" (any other TimeType throws).

CallFires at
beginOf("day")00:00 daily
endOf("day")23:59 daily
beginOf("month")1st at 00:00
endOf("month")last day at 23:59 (recomputed per month)
beginOf("year")Jan 1 at 00:00
endOf("year")Dec 31 at 23:59

endOf("month") is dynamic (correct across February, leap years); beginOf("year") / endOf("year") lock the month.

Switch the job to a 5-field cron expression. Clears any fluent interval config. Throws on an invalid expression. See the cron field reference.

An IANA string (e.g. "America/New_York"). Default is "UTC". The zone applies to every “now” comparison and every constraint. See Timezone.

retry(maxRetries, delay = 1000, backoffMultiplier?)

Section titled “retry(maxRetries, delay = 1000, backoffMultiplier?)”

Retry on failure. delay is milliseconds; passing backoffMultiplier enables exponential backoff (delay × multiplier^(attempt-1)). Throws on negative maxRetries, negative delay, or zero/negative backoffMultiplier. retry(0) means a single attempt, no retries. See Retry & Backoff.

Skip a scheduled tick if the job is already running (only relevant when the job is also invoked outside the scheduler loop). See Overlap Prevention.

MethodReturnsPurpose
run()Promise<JobResult>Run the callback once now. Honors retry; never throws — failures land in result.error. Advances lastRun and nextRun on both success and failure.
waitForCompletion()Promise<void>Resolves when the current run finishes; resolves immediately if not running. All concurrent waiters resolve together.
prepare()voidRecompute nextRun against the current clock. Called by the scheduler on start() / addJob while running.
terminate()thisClear all schedule config, cron parser, nextRun, and lastRun. The job stays registered but never fires until reconfigured.
GetterTypeNotes
namestringSet at construction (readonly).
nextRunDayjs | nullNext scheduled run.
lastRunDayjs | nullLast attempt — success or failure.
isRunningbooleanCurrently executing?
intervalsReadonly<JobIntervals>Current fluent config.
cronExpressionstring | nullnull when using the fluent API.

isDue() and shouldRun() also exist (booleans the scheduler uses internally): isDue() is pure time readiness; shouldRun() is isDue() plus the overlap rule.

Owns the tick loop, the registered jobs, the execution mode, and the typed event emitter. Use the exported scheduler singleton, or new Scheduler() for an isolated instance (tests, separate pools).

MethodReturnsPurpose
addJob(job)thisRegister a job. Prepares it immediately if the scheduler is already running.
addJobs(jobs)thisRegister several. Prepares each if already running.
newJob(name, callback)JobCreate, register, and return a job in one call.
removeJob(name)booleantrue if found and removed.
getJob(name)Job | undefinedLook up by name.
list()readonly Job[]All registered jobs.
MethodReturnsPurpose
runEvery(ms)thisTick interval. Minimum 100 ms (lower throws). Default 1000 ms.
runInParallel(parallel, maxConcurrency = 10)thisRun a tick’s due jobs concurrently, batched by maxConcurrency. Default is sequential.
MethodReturnsPurpose
start()voidPrepare all jobs and begin ticking. Emits scheduler:started. Throws if already running or if zero jobs are registered.
stop()voidHalt the tick loop immediately (does not wait for in-flight jobs). Emits scheduler:stopped. No-op (and silent) if not running.
shutdown(timeout = 30000)Promise<void>Stop, then await in-flight jobs up to timeout ms. The timeout is a hard cap — jobs still running after it are abandoned.
GetterType
isRunningboolean
jobCountnumber

Scheduler extends Node’s EventEmitter with a typed on / once / off / emit narrowed by SchedulerEvents. See Events.

Standard 5-field cron engine. Day-of-month + day-of-week use Vixie OR semantics: when both fields are restricted (neither is *), a date matches if either matches.

MemberTypePurpose
new CronParser(expression)Parse and validate. Throws on bad field count, out-of-range values, inverted ranges, or bad steps.
nextRun(from = dayjs())DayjsNext fire moment after from. Scans up to one year forward, then throws.
matches(date)booleanIs date a fire moment?
fieldsReadonly<CronFields>The parsed numeric arrays.
expressionstringThe original string.

Supported field syntax: *, 5, 1,3,5, 1-5, */5, 1-10/2. Not supported: named tokens (MON, JAN), macros (@daily), a seconds field, or Quartz modifiers (L, W, #).

type TimeType = "second" | "minute" | "hour" | "day" | "week" | "month" | "year";
type Day = "sunday" | "monday" | "tuesday" | "wednesday" | "thursday" | "friday" | "saturday";
type JobIntervals = {
day?: Day | number;
dayOfMonthMode?: "specific" | "last";
month?: number;
time?: string;
every?: { type?: TimeType; value?: number };
};
type JobResult = {
success: boolean;
duration: number; // ms, end-to-end including retry waits
error?: unknown; // present when success === false
retries?: number; // attempts that failed before the final outcome
};
type RetryConfig = {
maxRetries: number;
delay: number;
backoffMultiplier?: number;
};
type SchedulerEvents = {
"job:start": [jobName: string];
"job:complete": [jobName: string, result: JobResult];
"job:error": [jobName: string, error: unknown];
"job:skip": [jobName: string, reason: string];
"scheduler:started": [];
"scheduler:stopped": [];
"scheduler:tick": [timestamp: Date];
};
type CronFields = {
minutes: number[];
hours: number[];
daysOfMonth: number[];
months: number[];
daysOfWeek: number[];
};
type JobStatus = "idle" | "running" | "completed" | "failed";

Exported for downstream typing. The current Job surface exposes run state through the isRunning boolean rather than a single status field.