Smart database seeding with run-once tracking, environment awareness, and multi-ORM support.
Database seeders in most ORMs run every single time. Unlike migrations, there's no tracking of what's already been seeded.
# This runs ALL seeders, even ones that already ran
npx knex seed:run # π¬ Duplicate admin users? Again?Seedwise fixes this. It tracks which seeders have run, supports multiple run modes, and gives you full control over your seeding strategy.
- β Run-once tracking β Seeders only run when they haven't before
- π Multiple run modes β
once,always,changed,manual - π Environment-aware β Different seeds for dev/staging/prod
- π·οΈ Tags & groups β Run subsets of seeds with
--tag - π Dependencies β Define seed execution order
- π Lock mechanism β Prevents concurrent seeding
- π History tracking β See what ran, when, and how long it took
- π Multi-ORM β Knex, Prisma, Sequelize, Drizzle (planned)
# For Knex/Objection.js users
npm install @seedwise/core @seedwise/knex
# Coming soon:
# npm install @seedwise/core @seedwise/prisma
# npm install @seedwise/core @seedwise/sequelize
# npm install @seedwise/core @seedwise/drizzlenpx seedwise initThis creates:
seedwise.config.jsβ Configuration fileseeds/directory (if it doesn't exist)- Database tables (
_seedwise_history,_seedwise_lock)
npx seedwise create admin-user// seeds/001_admin_user.ts
import { SeedConfig } from '@seedwise/core';
export const config: SeedConfig = {
mode: 'once',
environments: ['development', 'staging', 'production'],
tags: ['auth', 'critical'],
};
export async function seed(knex) {
await knex('users').insert({
email: 'admin@example.com',
role: 'admin',
created_at: new Date(),
});
}npx seedwise runOutput:
π± Seedwise v1.0.0
Environment: development
Running seeds...
β 001_admin_user (once) β 23ms
β 002_default_roles (once) β 15ms
β 003_test_users (skipped, prod-only)
Done! 2 seeds executed, 1 skipped.
| Mode | Behavior | Use Case |
|---|---|---|
once |
Runs one time ever (default) | Admin users, default roles, initial config |
always |
Runs on every seedwise run |
Cache warmup, reference data sync |
changed |
Re-runs if file content changed | Config that evolves with code |
manual |
Only runs with --force or --name |
Dangerous operations, data fixes |
export const config: SeedConfig = {
mode: 'always', // This seed runs every time
};module.exports = {
// Adapter configuration
adapter: 'knex',
// Path to your knexfile or ORM config
connection: './knexfile.js',
// Seeds directory
seedsDir: './seeds',
// Table names (customizable)
historyTable: '_seedwise_history',
lockTable: '_seedwise_lock',
// Default timeout for seeds (ms)
timeout: 30000,
// Lock timeout - force release if held longer (ms)
lockTimeout: 60000,
// File extensions to look for
extensions: ['.js', '.ts'],
// Sort order
sortBy: 'filename', // or 'dependency'
};import { SeedConfig } from '@seedwise/core';
export const config: SeedConfig = {
// Run mode
mode: 'once' | 'always' | 'changed' | 'manual',
// Environment filtering
environments: ['development', 'staging'],
// OR
excludeEnvironments: ['production'],
// Tags for filtering
tags: ['auth', 'critical'],
// Dependencies (run these first)
dependsOn: ['001_roles', '002_permissions'],
// Transaction control
transaction: true, // default: true
// Timeout override (ms)
timeout: 60000,
// Mark as idempotent (informational)
idempotent: true,
};Initialize Seedwise in your project.
npx seedwise init
npx seedwise init --adapter prismaCreate a new seed file.
npx seedwise create user-roles
npx seedwise create user-roles --mode always
npx seedwise create user-roles --tags auth,criticalExecute pending seeds.
npx seedwise run # Run all pending seeds
npx seedwise run --force # Re-run all seeds
npx seedwise run --tag auth # Only seeds tagged 'auth'
npx seedwise run --env production # Override NODE_ENV
npx seedwise run --dry-run # Show what would run
npx seedwise run --name 001_admin # Run specific seed
npx seedwise run --verbose # Detailed outputShow seed history and pending seeds.
npx seedwise status
npx seedwise status --pending # Only show pending
npx seedwise status --json # JSON outputOutput:
π± Seedwise Status
History:
β 001_admin_user once 2024-01-15 10:23:45 (23ms)
β 002_default_roles once 2024-01-15 10:23:45 (15ms)
β 003_cache_warmup always 2024-01-15 10:23:46 (102ms)
Pending:
β― 004_new_feature once (not yet run)
Clear seed history (use with caution).
npx seedwise reset # Reset all (requires confirmation)
npx seedwise reset --name 001_admin # Reset specific seed
npx seedwise reset --force # Skip confirmationForce-release a stale lock.
npx seedwise unlockimport { Seedwise } from '@seedwise/core';
import { KnexAdapter } from '@seedwise/knex';
import knex from './knexfile';
const seedwise = new Seedwise({
adapter: new KnexAdapter(knex),
seedsDir: './seeds',
});
// Run all pending seeds
await seedwise.run();
// Run with options
await seedwise.run({
tags: ['auth'],
force: true,
dryRun: false,
});
// Get status
const status = await seedwise.status();
console.log(status.pending); // Seeds that need to run
console.log(status.history); // Seeds that have run
// Reset specific seed
await seedwise.reset('001_admin_user');Seedwise creates two tables in your database:
| Column | Type | Description |
|---|---|---|
| id | serial | Primary key |
| name | varchar(255) | Seed filename |
| batch | integer | Batch number |
| mode | varchar(50) | Run mode used |
| environment | varchar(50) | NODE_ENV when run |
| checksum | varchar(64) | File hash (for changed mode) |
| executed_at | timestamp | Execution timestamp |
| duration_ms | integer | Execution time |
| status | varchar(20) | success, failed, skipped |
| Column | Type | Description |
|---|---|---|
| index | integer | Always 1 |
| is_locked | integer | 0 or 1 |
| locked_at | timestamp | When lock was acquired |
| locked_by | varchar(255) | Hostname/process ID |
npm install @seedwise/core @seedwise/knex// seedwise.config.js
module.exports = {
adapter: 'knex',
connection: './knexfile.js',
};npm install @seedwise/core @seedwise/prismanpm install @seedwise/core @seedwise/sequelizenpm install @seedwise/core @seedwise/drizzleβ 001_create_admin_user.ts
β 002_seed_default_roles.ts
β 003_populate_countries.ts
β seed1.ts
β data.ts
Prefix with numbers to ensure consistent ordering:
001_roles.ts
002_permissions.ts
003_users.ts # depends on roles
export const config = {
dependsOn: ['001_roles', '002_permissions'],
};export const config = {
tags: ['auth'], // Can run just auth seeds in CI
};// Good: Upsert pattern
await knex('roles')
.insert({ name: 'admin', level: 100 })
.onConflict('name')
.merge();
// Risky: Plain insert (fails on re-run)
await knex('roles').insert({ name: 'admin', level: 100 });export const config = {
environments: ['development', 'test'], // Never in prod
};Q: How is this different from Knex's built-in seeding?
Knex seeds run every time with no tracking. Seedwise adds run-once tracking, environment awareness, tags, dependencies, and more.
Q: Can I use this with an existing project?
Yes! Run seedwise init and it will detect your existing seed files. Already-seeded data won't be affected until you run seedwise run.
Q: What happens if seeding fails midway?
By default, each seed runs in a transaction. If it fails, that seed rolls back. The lock is released, and you can fix and re-run.
Q: How do I run seeds in CI/CD?
# GitHub Actions example
- name: Run database seeds
run: npx seedwise run --env productionQ: Can I use TypeScript?
Yes! Seedwise supports both .js and .ts files out of the box.
Contributions are welcome! Please read our Contributing Guide before submitting a PR.
# Clone the repo
git clone https://github.com/vanjoe667/seedwise.git
# Install dependencies
pnpm install
# Run tests
pnpm test
# Build
pnpm buildMIT Β© Joel Ajide Ademola
Inspired by the migration patterns in Knex, Prisma, and Laravel's seeding system.
Built with β€οΈ by Joel Ajide Ademola