Dev

Dev-mode helpers — hot-reload signal (file watch + child-process restart), route-list dump exposed via dev.stats(), and a request inspector courtesy of stdio: 'inherit' so the operator sees the spawned app's logs unchanged.

The hot-reload loop spawns the app as a child process, watches the source directories with fs.watch({ recursive: true }), and restarts the child when an unignored file changes. On-disk state (vault keys, encrypted DB, sealed cookies) survives the restart because the child re-opens the files; only in-process state is lost, which is the correct semantic for "I just edited a route handler and want to see it."

Hygiene baked in: - Bursts of file events (save-everything keystrokes, multi-file format-on-save) collapse into one restart via the graceMs debounce (default 250 ms). - A restart-in-flight queues at most one follow-up — many edits during a slow restart yield two restarts, not N. - Ignored kinds by default: node_modules/, .git/, dotfiles, SQLite journal/WAL/SHM siblings, .log, editor scratch files (.swp, ~$). - Crash without a pending stop/restart leaves the child corpse in place and waits for a file change rather than spawn-thrashing. - Graceful kill via SIGTERM; SIGKILL escalation after killTimeoutMs (default 4000 ms) if the child ignores it.

Production refusal: dev.create() throws dev/refused-in-production when NODE_ENV=production, unless the operator explicitly sets opts.allowProduction: true with an audited reason. This is what blamejs dev (CLI) calls; production deployments that accidentally wire it crash loudly at boot rather than spawning shells on every save.

Test seams: opts._spawn(cmd, args, sopts) and opts._watch(dir, wopts, listener) default to child_process.spawn and fs.watch; unit tests pass fakes to drive the engine without real subprocesses.

b.dev.create(opts) #

stable0.4.0
{
  command:        string,                       // required — program to spawn (e.g. "node")
  args:           [string],                     // argv after command; default []
  watch:          [string],                     // directories to watch (recursive); default ["."]
  ignore:         [RegExp | string],            // appended to the framework default-ignore list
  graceMs:        number,                       // debounce window (ms); default 250
  killSignal:     string,                       // initial kill signal; default "SIGTERM"
  killTimeoutMs:  number,                       // SIGKILL escalation budget (ms); default 4000
  log:            object,                       // structured logger ({ info, warn, error })
  env:            object,                       // child env; default process.env
  cwd:            string,                       // child cwd; default process.cwd()
  stdio:          string | array,               // child stdio; default "inherit"
  allowProduction: boolean,                     // override the production refusal (audited reason required)
}

Build a hot-reload supervisor — spawn opts.command with opts.args, watch opts.watch directories, and restart the child on every unignored file change. Returns { start, stop, restart, stats }; stats() reports { pid, running, restarts, lastRestartAt, watchers }.

Throws DevError at config time on a missing command, a non-finite graceMs / killTimeoutMs, or an attempt to load with NODE_ENV=production (without opts.allowProduction).

var dev = b.dev.create({
  command: "node",
  args:    ["./server.js"],
  watch:   ["./routes", "./views", "./lib"],
  ignore:  [/\.tmp$/],
  graceMs: 250,
});

// await dev.start();
// dev.stats();   // → { pid: , running: true, restarts: 0, lastRestartAt: null, watchers: 3 }
// await dev.stop();

Last updated 2026-08-08T16:39:49.652Z by seeder.