or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cli-interface.mdconfiguration-management.mddata-seeding.mddatabase-interface.mddatabase-operations.mdindex.mdmigration-management.md
tile.json

data-seeding.mddocs/

Data Seeding

Data seeding functionality for populating databases with initial or test data. db-migrate supports both version-controlled and static seeding approaches, allowing you to manage data insertion and removal with the same precision as schema migrations.

Capabilities

Execute Seeds

Execute database seeding operations to populate tables with data.

/**
 * Execute database seeding operations
 * @param mode - Seeding mode: 'vc' (version controlled) or 'static'
 * @param scope - Seeding scope/mode (string) or callback (function)
 * @param callback - Completion callback (function)
 * @returns Promise
 */
seed(mode, scope, callback): Promise;

Usage Examples:

const dbMigrate = require('db-migrate');
const instance = dbMigrate.getInstance();

// Run version-controlled seeds (default)
await instance.seed();

// Explicitly run version-controlled seeds
await instance.seed('vc');

// Run static seeds
await instance.seed('static'); 

// With callback
instance.seed('vc', (err) => {
  if (err) console.error('Seeding failed:', err);
  else console.log('Seeding completed');
});

// With scope
await instance.seed('vc', 'user-data');

Undo Seeds

Undo seed operations by running the down methods of previously executed seeds.

/**
 * Undo seed operations (rollback seeding)
 * @param specification - Count (number) or callback (function)
 * @param scope - Seeding scope/mode (string)
 * @param callback - Completion callback (function)
 * @returns Promise
 */
undoSeed(specification, scope, callback): Promise;

Usage Examples:

// Undo the last seed
await instance.undoSeed(1);

// Undo the last 3 seeds
await instance.undoSeed(3);

// With callback
instance.undoSeed(2, (err) => {
  if (err) console.error('Undo seed failed:', err);
  else console.log('Seeds undone');
});

// With scope
await instance.undoSeed(1, 'user-data');

Reset Seeds

Reset all seeds by undoing all previously executed seed operations.

/**
 * Reset all seeds by undoing all executed seeds
 * @param specification - Count parameter (ignored for API consistency with undoSeed)
 * @param scope - Seeding scope/mode (string) or callback (function)
 * @param callback - Completion callback (function)
 * @returns Promise
 */
resetSeed(specification?, scope, callback): Promise;

Note: The specification parameter is ignored internally - resetSeed always resets all seeds regardless of the count provided. This parameter exists for API consistency with undoSeed.

Usage Examples:

// Reset all seeds
await instance.resetSeed();

// With callback
instance.resetSeed(null, (err) => {
  if (err) console.error('Reset seed failed:', err);
  else console.log('All seeds reset');
});

// With scope
await instance.resetSeed(null, 'user-data');

Seeding Modes

Version Controlled Seeds ('vc')

Version-controlled seeds work like migrations - they track which seeds have been applied and can be rolled back.

Directory Structure:

seeds/
├── vc/
│   ├── 20231201120000-add-default-users.js
│   ├── 20231201130000-add-sample-products.js
│   └── 20231201140000-add-test-data.js
└── static/
    ├── users.json
    └── products.json

Version Controlled Seed File:

'use strict';

var dbm;
var type;
var seed;

exports.setup = function(options, seedLink) {
  dbm = options.dbmigrate;
  type = dbm.dataType;
  seed = seedLink;
};

exports.up = function(db) {
  return db.insert('users', [
    { name: 'Admin User', email: 'admin@example.com', role: 'admin' },
    { name: 'Test User', email: 'test@example.com', role: 'user' }
  ]);
};

exports.down = function(db) {
  return db.runSql("DELETE FROM users WHERE email IN ('admin@example.com', 'test@example.com')");
};

exports._meta = {
  "version": 1
};

Static Seeds ('static')

Static seeds are simple data files that are loaded each time seeding runs, without version tracking.

Static Seed File (JSON):

{
  "users": [
    { "name": "Default Admin", "email": "admin@site.com", "role": "admin" },
    { "name": "Demo User", "email": "demo@site.com", "role": "user" }
  ],
  "categories": [
    { "name": "Electronics", "slug": "electronics" },
    { "name": "Books", "slug": "books" }
  ]
}

CLI Usage

Seeding operations are available through the command-line interface:

# Run version-controlled seeds
db-migrate seed

# Run static seeds  
db-migrate seed:static

# Undo seeds
db-migrate seed:down

# Reset all seeds
db-migrate seed:reset

# With environment
db-migrate seed --env test

# With specific count
db-migrate seed:down -c 2

Seed File Creation

Create seed files manually or using templates:

Manual Creation:

// seeds/vc/20231201120000-add-sample-users.js
'use strict';

exports.setup = function(options, seedLink) {
  // Setup code
};

exports.up = function(db) {
  return db.insert('users', [
    { name: 'Alice Smith', email: 'alice@example.com' },
    { name: 'Bob Jones', email: 'bob@example.com' }
  ]);
};

exports.down = function(db) {
  return db.runSql("DELETE FROM users WHERE email IN ('alice@example.com', 'bob@example.com')");
};

exports._meta = {
  "version": 1
};

Database Interface for Seeds

Seeds have access to database interface methods for data manipulation:

Insert Data

exports.up = function(db) {
  // Insert single record
  return db.insert('users', {
    name: 'John Doe',
    email: 'john@example.com'
  });
  
  // Insert multiple records
  return db.insert('users', [
    { name: 'Alice', email: 'alice@example.com' },
    { name: 'Bob', email: 'bob@example.com' }
  ]);
};

Run SQL

exports.up = function(db) {
  return db.runSql(`
    INSERT INTO users (name, email, created_at) 
    VALUES 
      ('Admin', 'admin@site.com', NOW()),
      ('User', 'user@site.com', NOW())
  `);
};

exports.down = function(db) {
  return db.runSql("DELETE FROM users WHERE email IN ('admin@site.com', 'user@site.com')");
};

Update Data

exports.up = function(db) {
  return db.runSql("UPDATE users SET status = 'active' WHERE role = 'admin'");
};

Link to Other Seeds

exports.up = function(db) {
  // Link to another seed
  seed.link('20231201130000-add-categories');
  
  return db.insert('products', [
    { name: 'Laptop', category_id: 1 },
    { name: 'Book', category_id: 2 }
  ]);
};

Configuration

Seeding respects the same configuration as migrations:

{
  "development": {
    "driver": "mysql",
    "host": "localhost",
    "user": "root", 
    "password": "password",
    "database": "myapp_development",
    "seeds-table": "seeds_meta",
    "vcseeder-dir": "seeds/vc",
    "staticseeder-dir": "seeds/static"
  }
}

Environment-Specific Seeding

// Development seeds
const devInstance = dbMigrate.getInstance(true, { env: 'development' });
await devInstance.seed('vc');

// Test seeds
const testInstance = dbMigrate.getInstance(true, { env: 'test' });
await testInstance.seed('static');

// Production seeds (usually minimal)
const prodInstance = dbMigrate.getInstance(true, { env: 'production' });
await prodInstance.seed('vc'); // Only essential data

Error Handling

try {
  await instance.seed('vc');
} catch (error) {
  if (error.message.includes('duplicate key')) {
    console.log('Seed data already exists, skipping...');
  } else if (error.message.includes('foreign key')) {
    console.error('Seed references missing data, check dependencies');
    throw error;
  } else {
    throw error;
  }
}

Best Practices

Development Workflow

async function setupDevelopmentData() {
  const instance = dbMigrate.getInstance(true, { env: 'development' });
  
  // Run migrations first
  await instance.up();
  
  // Then seed data
  await instance.seed('vc');
  
  console.log('Development environment ready with sample data');
}

Testing Workflow

async function setupTestData() {
  const instance = dbMigrate.getInstance(true, { env: 'test' });
  
  // Reset seeds for clean test state
  await instance.resetSeed();
  
  // Apply fresh test data
  await instance.seed('static');
}

Types

/**
 * Seeding mode specification
 */
type SeedMode = 'vc' | 'static';

/**
 * Seed specification for targeting specific counts
 */
type SeedSpecification = number | (() => void);

/**
 * Seeding scope for organizing seeds
 */
type SeedScope = string;

/**
 * Seed callback function signature
 */
type SeedCallback = (error?: Error, result?: any) => void;

/**
 * Database interface available in seed files
 */
interface SeedDatabase {
  /** Insert data into table */
  insert(tableName: string, data: object | object[]): Promise<any>;
  /** Update data in table */
  update(tableName: string, data: object, where: object): Promise<any>;
  /** Delete data from table */
  delete(tableName: string, where: object): Promise<any>;
  /** Truncate table (remove all data) */
  truncate(tableName: string): Promise<any>;
  /** Execute raw SQL query */
  runSql(sql: string, params?: any[]): Promise<any>;
  /** Lookup data from table */
  lookup(spec: object): Promise<any>;
  /** Build WHERE clause from specification object */
  buildWhereClause(spec: object): string;
  /** Escape string for SQL safety */
  escapeString(str: string): string;
  /** Escape value for SQL safety */
  escape(str: any): string;
  /** Quote array values for SQL */
  quoteArr(arr: any[]): string;
}