Back to home
Apisurf Logo
ngn logo

ngn

Schedules and runs Node tasks, with every run, log and timing kept in one SQLite file.

What is ngn?

ngn runs JavaScript and TypeScript files on a schedule. Each task is a plain file. Every run, with its logs and result, is saved in one SQLite file on your disk, so you can see what happened from the terminal or in a dashboard.


Get started

bash
npm install -g @apisurf/ngn

# or, without installing
npx @apisurf/ngn <command>

Also add it to your project, for the types: npm i @apisurf/ngn. Then:

bash
ngn init            # creates ngn.config.ts and tasks/
ngn add hello.ts    # creates tasks/hello.ts
ngn run             # runs every task, until Ctrl-C

Writing a task

A task file exports timing (when to run) and task (what to run):

tasks/hello.ts
import type { TaskContext } from "@apisurf/ngn";

// Every 10 seconds
export const timing = "*/10 * * * * *";

export const task = async (ctx: TaskContext) => {
  const res = await fetch("https://example.com", { signal: ctx.run.signal });
  const html = await res.text();

  await ctx.log.info(`fetched ${html.length} bytes`);

  // Whatever you return is stored with the run
  return { length: html.length };
};

Import any package you have installed. A file or folder whose name starts with _ is never treated as a task, so use it for shared helpers.

Timing

Use a cron pattern, or { every } for a fixed interval. A cron pattern can have an optional seconds field in front.

typescript
export const timing = "*/10 * * * * *"; // cron, with seconds: every 10 seconds
export const timing = "0 9 * * 1-5";    // cron: weekdays at 9:00
export const timing = { every: "5m" };  // every 5 minutes
PatternRuns
*/5 * * * * *Every 5 seconds
* * * * *Every minute
0 * * * *Every hour
0 9 * * *Daily at 9:00
0 9 * * 1-5Weekdays at 9:00

The context

task gets a ctx with:

On ctxWhat it does
ctx.log.info(text)Log a line. Also warning and error
ctx.kv.get(key) / set(key, value)Small string values that are kept between runs
ctx.sqlite.execute(sql, args)Query the task's own SQLite database, kept next to the task file
ctx.envVariables from .env
ctx.run.signalAborts when the run should stop. Pass it to fetch

Commands

CommandDoes
ngn runRun every task, until Ctrl-C
ngn run helloRun only the tasks you name
ngn run hello --onceRun one task now, then exit
ngn statusHow each task is doing, and when it runs next
ngn runsRecent runs
ngn show <run>One run: its logs, error and result
ngn logs <task>A task's log lines
ngn pause <task> / ngn resume <task>Stop and restart a task without editing it
ngn uiOpen the dashboard in a browser

Run ngn --help for the full list, or ngn help task for everything a task can do.


Configuration

ngn init writes ngn.config.ts. Every option is optional:

ngn.config.ts
import { defineConfig } from "@apisurf/ngn";

export default defineConfig({
  dbPath: "file:./ngn.sqlite",
});
OptionWhat it is
dbPathWhere runs and logs are saved. ngn init sets file:./ngn.sqlite
matchWhich files are tasks. Default ["tasks/**/*.ts"]
envFileLoaded into ctx.env. Default .env