Cron plugin
Use @reionjs/cron for scheduled tasks under appDir/cron and manual runs via ctx.schedule().
Scheduled tasks are provided by @reionjs/cron. It recursively scans <appDir>/cron/ for matching files (including nested subfolders), runs them on a timer in dev/production as configured, and exposes ctx.schedule() on each request.
Install
Peer dependency: reion.
npx reion add -p @reionjs/cronyarn dlx reion add -p @reionjs/cronbunx reion add -p @reionjs/cronpnpm exec reion add -p @reionjs/cronInstalls with your project's package manager. There is no separate setup scaffold—add Cron to reion.config.ts as in the next section.
npm install @reionjs/cronyarn add @reionjs/cronbun add @reionjs/cronpnpm add @reionjs/cronRegister in reion.config.ts
import { Cron } from "@reionjs/cron";
export default {
plugins: [Cron()],
};Disable the in-process scheduler while reion dev is running (tasks can still be triggered with ctx.schedule):
plugins: [Cron({ disableDevCron: true })];Importing Cron from @reionjs/cron applies the package's type augmentation so ctx.schedule is known on ReionContext.
Where cron jobs live
- Directory:
<appDir>/cron/— scanned recursively; you can group jobs in subfolders (e.g.cron/billing/,cron/reports/weekly/). - File names:
*.cron.ts,*.cron.js,*.cron.mts,*.cron.mjs(and other extensions the loader treats as cron modules).
Each file defines one task. The default schedule id (what you pass to ctx.schedule) is built from the path relative to cron/: every folder segment and the file basename are turned from camelCase into dot.case, then joined with dots (same idea as event names under events/).
Path under cron/ | Default task name |
|---|---|
cleanup.cron.ts | cleanup |
intervalExample.cron.ts | interval.example |
reportDaily.cron.ts | report.daily |
billing/syncOrders.cron.ts | billing.sync.orders |
reports/weekly/summary.cron.ts | reports.weekly.summary |
You can override the id by exporting a name string from the cron module (see below).
Cron file exports
Each cron file exports:
schedule—ScheduleDeforScheduleDef[]run—(ctx: TaskContext) => void | Promise<void>name(optional) —string; if set, this becomes the task id instead of the default derived from the file path.
import type { ScheduleDef, TaskContext } from "@reionjs/cron";
export const schedule: ScheduleDef = { every: "day", at: "00:00" };
export async function run(ctx: TaskContext) {
console.log("cleanup", ctx.payload);
}(Use src/cron or app/cron to match your appDir.)
Trigger manually from routes
When the plugin is enabled, ctx.schedule(name, payload, options?) is available on request context:
export async function POST(ctx) {
await ctx.schedule("report.daily", { triggeredBy: "admin" });
ctx.res.status(202).json({ ok: true });
}Delayed or timed invocation:
await ctx.schedule("report.daily", { source: "api" }, { delayMs: 2000 });
await ctx.schedule(
"report.daily",
{ source: "api" },
{ at: new Date(Date.now() + 60_000) }
);