139 lines
3.7 KiB
Markdown
139 lines
3.7 KiB
Markdown
# 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
|
|
|
|
```ts
|
|
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
|
|
|
|
```text
|
|
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).
|