A soft delete marks a record as deleted without physically removing the row from the database. This lets you recover accidentally deleted data, maintain audit trails, and keep referential integrity intact. Drizzle Castor bakes soft delete directly into the schema builder so you declare the behavior once and it is enforced everywhere — queries, joins, mutations, and telemetry — without extra code in your application layer.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/fajarnugraha37/drizzle-castor/llms.txt
Use this file to discover all available pages before exploring further.
Declaring soft delete on a table
Soft delete is configured per table insidebuilder.table() using the softDelete option. You provide two objects: deleteValue describes what the flagged-as-deleted state looks like, and restoreValue describes the active state.
deletedFlag column declared in the schema:
The values in
deleteValue and restoreValue can be static primitives, synchronous functions, or Promise-returning functions. Drizzle Castor resolves them via resolveProviderValues() immediately before each mutation, making dynamic values like Date.now() or an audit user ID straightforward to implement.Automatic safety filters
OncesoftDelete is configured, Drizzle Castor automatically injects a filter that excludes soft-deleted rows from every query and every JOIN on that table. The injection is handled by injectSoftDeleteFilter() in src/helper/soft-delete-helper.ts and is idempotent — it checks for duplicate conditions before appending.
For a table configured with deleteValue: { deletedFlag: 1 }, every standard searchOne, searchMany, and searchPage call transparently applies:
JOIN conditions for related tables that also have soft delete configured, so soft-deleted posts are excluded when you join users to posts even if you never mention deletedFlag in your query.
Soft-delete methods
Soft-deleting a single record
softDeleteOne(id, profile) finds the record by primary key, verifies it is currently active (not already soft-deleted), and applies deleteValue in a single atomic transaction.
Soft-deleting multiple records
softDeleteMany(filter, profile) applies deleteValue to every row matching the filter. The filter syntax is the same JSON query language used everywhere else in the library.
softDeleteMany uses executeBatchMutation which routes through Strategy A (RETURNING) for PostgreSQL and SQLite, or Strategy B (temporary table) for MySQL, ensuring the operation is race-condition free.
Restore methods
Restoring a single record
restoreOne(id, profile) finds the record by primary key among soft-deleted rows and applies restoreValue.
Restoring multiple records
restoreMany(filter, profile) applies restoreValue to every soft-deleted row matching the filter.
Querying soft-deleted records
Standard search methods never return soft-deleted rows. Use thesearchDeleted* variants to query the soft-deleted partition explicitly:
mode: "deleted" to injectSoftDeleteFilter, which inverts the safety condition to WHERE deleted_flag = 1 instead of excluding it.
Hard delete methods
Hard delete permanently removes a row. Unlike soft delete, the record cannot be recovered.Telemetry events
Every soft-delete, restore, and hard-delete operation emits a structured telemetry event on the asynchronous event bus. Subscribe viabuilder.on() to build audit logs or metrics.
soft-deleted event
soft-deleted event
restored event
restored event
hard-deleted event
hard-deleted event
All telemetry events are emitted asynchronously via microtask scheduling using
mitt. The event emission never blocks the database transaction or the return value of the repository method.Operation summary
softDeleteOne / softDeleteMany
Marks records as deleted by writing
deleteValue. Only targets currently active records. Returns true / count of affected rows.restoreOne / restoreMany
Writes
restoreValue back to flagged records. Only targets currently soft-deleted records.hardDeleteOne / hardDeleteMany
Permanently removes rows. Hydrates a snapshot before deletion for telemetry. Cannot be undone.
searchDeletedOne / searchDeletedMany
Queries the soft-deleted partition. Injects the inverse safety filter so only deleted rows are returned.
Related pages
Multi-dialect support
How the atomic mutation strategy differs between PostgreSQL/SQLite and MySQL.
Middleware and telemetry
Full reference for the telemetry event bus and all event payload shapes.