Seeders

Load fixture data into a database, per environment, recording what has been loaded so a second run does not load it twice.

Seeds and migrations answer different questions. A migration changes the schema and runs everywhere. A seed puts rows in, and which rows depend on where you are: a local admin account belongs in dev and nowhere else. So a seed lives under the environment it is for, and a run names the environment it wants.

A seed may declare that it must run after another, and the order is resolved from those declarations rather than from the file numbers alone, because a fixture that references another's rows has to follow it whatever they happen to be numbered.

A seed may also declare itself rerunnable, for a baseline that is written to be idempotent and should be reasserted on every run. Anything else is applied once and recorded.

Like migrations, a run takes a lock in the database, so two processes seeding together do not both insert the same fixture.

b.seeders.create(opts) #

stable0.2.35
{
  dir:              string,          // directory holding the per-env seed folders; required
  db:               object,          // database handle; defaults to b.db
  audit:            boolean|object,  // audit sink
  auditApplied:     boolean,         // default true — audit each applied seed
  auditFailures:    boolean,         // default true — audit each failure
  lockStaleAfterMs: number,          // default 0 — never take over a held lock
  clock:            function,        // () → epoch ms; a test seam
}

Open the seeder over a directory and answer the handle to work it. The handle carries run(args), status(args), list(args) and dir, and each of the first three takes { env }.

A seed file lives at

//-.js and exports description, an optional envs array narrowing where it applies, an optional rerunnable flag, and optional dependsOn names. A file whose name does not match -.js is not a seed and is skipped.

run applies what has not been applied, in dependency order, and records each one. A rerunnable seed is applied every time, which is for a baseline written to be idempotent. status answers what is applied and what is pending without changing anything.

A run takes a lock in the database first, so two processes seeding together do not both insert the same fixture. lockStaleAfterMs is when a lock left behind by a dead process may be taken over; it defaults to 0, which means a held lock is never taken over and a crash during a seed needs the lock cleared.

var b = require("@blamejs/core");
var seed = b.seeders.create({ dir: "./seeders" });
await seed.status({ env: "dev" });   // → what is applied and what is pending
await seed.run({ env: "dev" });

Last updated 2026-10-12T14:21:56.879Z by seeder.