Skip to content

Bun

since: 1.7

@runwisp/js runs under Bun 1.1 or later the same way it runs under Node.js. It also replaces both forms of Bun.cron.

Terminal window
bun add @runwisp/js
index.ts
import { RunWisp } from "@runwisp/js";
const runwisp = new RunWisp({ exitOnSignal: true });
runwisp.task("sync-inventory", { cron: "*/15 * * * *" }, async () => {
await syncInventory();
});
Terminal window
bun index.ts

Everything in the JavaScript SDK guide applies. exitOnSignal lets running tasks finish when you stop the script with Ctrl-C.

Bun.cron(schedule, handler) runs a callback in your process. Give the task a name and pass the same schedule:

// Bun.cron("*/15 * * * *", () => syncInventory(), { tz: "Europe/Berlin" });
runwisp.task(
"sync-inventory",
{ cron: "*/15 * * * *", timezone: "Europe/Berlin", on_overlap: "skip" },
() => syncInventory(),
);

RunWisp accepts Bun’s cron syntax as is, including month and weekday names and @daily-style nicknames. It also takes an optional seconds field.

Bun.cron @runwisp/js
{ tz } timezone
A time that comes while the handler still runs is skipped. on_overlap: "skip". Without it, the run waits for the previous one.
A thrown error exits the process, unless you handle uncaughtException. The run fails, with the stack trace in its log. The app keeps running.
job.stop() task.stop() pauses the task, task.destroy() removes it.
job.unref() No equivalent. The app keeps running until you call close().
Bun.cron.parse(schedule) task.getNextRun()

Bun.cron(path, schedule, title) registers a script with the system scheduler: crontab on Linux, launchd on macOS. RunWisp runs the same script and records each run, which crontab and launchd don’t.

On Linux, import the jobs from your crontab:

Terminal window
crontab -l | runwisp import cron

Each job Bun registered becomes a task named after its title. Review the output, save it as runwisp.toml, and remove the jobs from crontab so they don’t run twice:

await Bun.cron.remove("weekly-report");

On macOS, write the task yourself. The command is the one Bun runs, which calls the script’s scheduled() handler:

runwisp.toml
# Was: await Bun.cron("./worker.ts", "30 2 * * MON", "weekly-report");
[tasks.weekly-report]
cron = "30 2 * * MON"
run = "bun run --cron-title=weekly-report --cron-period='30 2 * * MON' ./worker.ts"

A scheduled() handler that throws fails the run. See From cron for the rest of moving off crontab.