Skip to content

Seeders

Seeders populate your database with initial or test data. The @stratal/seeders package provides a Seeder base class and a CLI for running seeders against your Cloudflare Workers bindings.

Terminal window
yarn add -D @stratal/seeders

Extend the Seeder base class and implement the run() method:

import { Seeder } from '@stratal/seeders'
import { inject, DI_TOKENS } from 'stratal/di'
import type { DatabaseService } from '@stratal/framework/database'
import { UserFactory } from './user.factory'
export class UserSeeder extends Seeder {
constructor(
@inject(DI_TOKENS.Database) private readonly db: DatabaseService,
) {
super()
}
async run(): Promise<void> {
await new UserFactory().count(10).createMany(this.db)
}
}

Register the seeder in a module’s providers array:

@Module({
providers: [UserSeeder],
})
export class UsersModule {}

Seeder names are derived from the class name by removing the Seeder suffix and converting to kebab-case:

Class nameCLI name
UserSeederuser
RolePermissionsSeederrole-permissions
InitialDataSeederinitial-data

The stratal-seed CLI discovers seeders from your module tree and runs them.

Terminal window
npx stratal-seed run user
Terminal window
npx stratal-seed run --all
Terminal window
npx stratal-seed list

Preview which seeders would run without executing them:

Terminal window
npx stratal-seed run --all --dry-run

The CLI uses Wrangler’s getPlatformProxy() to obtain your Cloudflare bindings (D1, KV, R2, etc.) locally. It then bootstraps your module tree, discovers all classes that extend Seeder, and executes their run() methods inside a request scope.

Seeders are automatically discovered from the module tree. Any class that extends Seeder and is listed in a module’s providers array will be found by the CLI. Only bare class providers are scanned — value, factory, and existing providers are skipped.

Seeders pair naturally with factories for generating realistic data:

import { Seeder } from '@stratal/seeders'
import { inject, DI_TOKENS } from 'stratal/di'
import type { DatabaseService } from '@stratal/framework/database'
import { UserFactory } from './user.factory'
import { PostFactory } from './post.factory'
export class DemoDataSeeder extends Seeder {
constructor(
@inject(DI_TOKENS.Database) private readonly db: DatabaseService,
) {
super()
}
async run(): Promise<void> {
const users = await new UserFactory().count(5).createManyAndReturn(this.db)
for (const user of users) {
await new PostFactory()
.state(attrs => ({ ...attrs, authorId: user.id }))
.count(3)
.createMany(this.db)
}
}
}