work-hub-server/openspec/changes/archive/2026-06-04-add-shared-schema-package/design.md
Nicolas HOARAU 9190908062 docs: archive completed changes
Archive add-shared-schema-package and swap-superstruct-valibot changes to openspec/changes/archive/
2026-06-04 12:49:12 +04:00

2.9 KiB

Context

The monorepo currently has three workspace roots: apps/api (NestJS), apps/web (Nuxt), and packages/schema (empty placeholder). The API and web apps share no type definitions, validation logic, or database schema — each would need to duplicate these. The packages/schema directory exists but has no package.json, no tsconfig.json, and no source files.

The chosen stack is:

  • Drizzle ORM (PostgreSQL) for database table definitions, relations, and migrations
  • Superstruct for runtime schema validation (request payloads, configs, etc.)
  • TypeScript types derived from both Drizzle and Superstruct schemas

Goals / Non-Goals

Goals:

  • Create a working @workspace/schema package with proper package.json, tsconfig.json, and build pipeline
  • Define Drizzle table schemas, relations, and enums targeting PostgreSQL
  • Define Superstruct validators for runtime data validation
  • Export derived TypeScript types that both api and web can consume
  • Wire the package into the Turborepo build graph so it builds before its consumers

Non-Goals:

  • No migrations or database connections — this package only provides schema definitions
  • No API endpoints or web UI — this is purely a data layer package
  • No initial table definitions — the package structure and conventions will be set up; actual tables come in follow-up changes

Decisions

  1. Package name @workspace/schema — follows the existing packages/ directory pattern; scoped to avoid conflicts with npm; private: true in package.json.

  2. Entry points split by concern — three source entry points (or one barrel export):

    • src/drizzle/ — Drizzle table definitions (pgTable, relations, enums)
    • src/validation/ — Superstruct schemas (object(), string(), etc.)
    • src/types/ — Re-exported TypeScript types (inferred from Drizzle and Superstruct)

    Single src/index.ts barrel re-exports everything. The exports field in package.json may expose sub-paths if the package grows large.

  3. Drizzle schema is the source of truth for DB structure — Superstruct validators mirror the same shapes but can be more permissive (e.g., optional fields for partial updates). TypeScript types are inferred from both.

  4. tsconfig.json extends the root — no root tsconfig exists yet, so packages/schema gets its own with module: nodenext, target: ES2023, strict mode, and declaration output.

  5. Build via tsc — simple tsc build; no bundler needed since it's consumed internally by the monorepo.

Risks / Trade-offs

  • [Duplication risk] Superstruct schemas and Drizzle definitions could drift apart. Mitigation: Superstruct validators should reference Drizzle-derived types where possible, and tests should assert consistency.
  • [Build order] Turborepo's ^build dependsOn already handles topological order, so no config changes needed — just ensure api/web list @workspace/schema in dependencies.