Plugins

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/cron
yarn dlx reion add -p @reionjs/cron
bunx reion add -p @reionjs/cron
pnpm exec reion add -p @reionjs/cron

Installs 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/cron
yarn add @reionjs/cron
bun add @reionjs/cron
pnpm add @reionjs/cron

Register in reion.config.ts

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):

reion.config.ts
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.tscleanup
intervalExample.cron.tsinterval.example
reportDaily.cron.tsreport.daily
billing/syncOrders.cron.tsbilling.sync.orders
reports/weekly/summary.cron.tsreports.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:

  1. scheduleScheduleDef or ScheduleDef[]
  2. run(ctx: TaskContext) => void | Promise<void>
  3. name (optional) — string; if set, this becomes the task id instead of the default derived from the file path.
src/cron/cleanup.cron.ts
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:

src/router/admin/report/route.ts
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) }
);