3.7 KiB
OpenSpec Change: enterprise-server-seed
- Change ID: enterprise-server-seed
- Package:
@suaveplan/seed - Category: server/infra
- Target path:
server/infra/seed - Status: PROPOSED
- Date: 2026-04-24
- Reference spec:
/mnt/s/web/suaveplan/enterprise/seed.md
Summary
Deliver @suaveplan/seed on the genesis branch from scratch at enterprise quality. The package provides a database seeding and fixture framework for development, testing, and demo environments. It exposes a SeedRunner with declarative SeedDefinition entries (each with name, run, optional dependsOn, condition, and teardown), ordered execution based on dependency graph, idempotent re-run via onConflict: 'skip' | 'update' | 'error', and a SeedContext injected into each handler carrying a DatabaseAdapter (from @suaveplan/db), logger, and factory helpers. Genesis adds Zod schemas, @suaveplan/error codes, OTel spans per seed step, and full integration tests against @suaveplan/db-sqlite.
Current-state audit (genesis)
Does not exist on genesis — fresh build.
Available workspace deps on genesis
| Package | Role |
|---|---|
@suaveplan/error (workspace:^) |
Typed SEED.* error codes |
@suaveplan/types (workspace:^) |
DatabaseLike, LoggerLike |
@suaveplan/db (workspace:^) |
DatabaseAdapter interface |
@suaveplan/logger (workspace:^) |
Structured logs |
zod (catalog:forms) |
Options and definition schemas |
@opentelemetry/api (catalog:observability) |
Spans + counters |
tslib (catalog:build) |
Runtime helpers |
Public API surface
class SeedRunner {
constructor(options: SeedRunnerOptions)
register(definition: SeedDefinition): void
run(names?: string[]): Promise<SeedReport>
teardown(names?: string[]): Promise<void>
}
function createSeedRunner(options: SeedRunnerOptions): SeedRunner
type SeedFn = (ctx: SeedContext) => Promise<void>
interface SeedDefinition {
name: string
run: SeedFn
teardown?: SeedFn
dependsOn?: string[]
condition?: (ctx: SeedContext) => Promise<boolean>
onConflict?: 'skip' | 'update' | 'error' // default: 'skip'
}
interface SeedContext {
db: DatabaseAdapter
logger: LoggerLike
env: string // 'development' | 'test' | 'production'
}
interface SeedRunnerOptions {
db: DatabaseAdapter
env?: string // default: process.env.NODE_ENV ?? 'development'
logger?: LoggerLike
}
interface SeedReport {
total: number
ran: number
skipped: number
failed: number
results: SeedStepResult[]
}
interface SeedStepResult {
name: string
status: 'ran' | 'skipped' | 'failed'
duration: number
error?: string
}
type SeedErrorCode =
| 'SEED_CIRCULAR_DEPENDENCY'
| 'SEED_STEP_FAILED'
| 'SEED_DEFINITION_NOT_FOUND'
| 'SEED_DEPENDENCY_NOT_REGISTERED'
function registerSeedErrorCodes(): void
File layout
server/infra/seed/
package.json
tsconfig.json
vitest.config.ts
src/
index.ts
error-codes.ts
constants/index.ts
types/
seed.types.ts
seed.types.md
runner/
seed-runner/
seed-runner.ts
seed-runner.md
seed-runner.types.ts
seed-runner.test.ts
index.ts
graph/
dependency-graph/
dependency-graph.ts
dependency-graph.md
dependency-graph.test.ts
index.ts
tests/
integration.test.ts
Impact
Downstream: all server packages that need development data (auth, user, product seeds). Works with any @suaveplan/db-compatible adapter.
Prerequisites on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/db, @suaveplan/logger.
Integration tests use @suaveplan/db-sqlite (dev dep).