You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(database-design): add soft-delete query filters and helpers
Implements the soft-delete pattern that pipeline.config.json enables by
default (database.softDeleteDefault: true) but was previously unimplemented.
- Add nullable deletedAt column to the shared users schema template
- Add shared db/soft-delete.ts with notDeleted, withSoftDeleteFilter,
softDelete, and restore helpers (generic over postgres-js and neon-http)
- Add a node users route demonstrating DELETE -> softDelete and the
?include_deleted=true admin query param
- Add tests asserting generated SQL for each helper
- Document soft-delete column/helper/route generation in the
database-design skill, gated on softDeleteDefault
Closes#53
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@@ -583,4 +721,5 @@ cd api && pnpm add -D drizzle-kit drizzle-zod
583
721
-**Zod inference from Drizzle**: Single source of truth -- change the Drizzle schema, the Zod validators follow automatically.
584
722
-**UUID primary keys**: Default for all tables. Avoids sequential ID enumeration attacks and works well in distributed systems.
585
723
-**Soft timestamps**: `createdAt` and `updatedAt` on every table. `$onUpdate` handles automatic timestamp refresh.
724
+
-**Soft deletes by default**: when `database.softDeleteDefault` is true, deletable tables get a nullable `deletedAt` column and a shared `soft-delete.ts` helper module instead of issuing hard `DELETE`s. Reads filter with `notDeleted`/`withSoftDeleteFilter`, deletes stamp `deletedAt` via `softDelete`, and `?include_deleted=true` exposes deleted rows to admin endpoints. Set the flag to `false` to opt back into hard deletes.
586
725
-**snake_case columns**: PostgreSQL convention. Drizzle maps to camelCase in TypeScript automatically.
0 commit comments