SlintORM
Docsnpm

Soft Delete

Annotate a deletedAt field with @softDelete and SlintORM automatically injects WHERE deletedAt IS NULL on every query for that model. Calling .delete() sets the timestamp instead of removing the row.

Model setup

// Mark deletedAt with @softDelete
interface User {
  id: number;
  email: string;
  name: string;
  // @softDelete
  deletedAt: string;   // added automatically to the table
}

// Tables without @softDelete are unaffected — no extra column

Auto-filter on all queries

// Default behavior: WHERE deletedAt IS NULL is injected on every query

const users = await User.getAll();
// SELECT * FROM users WHERE deletedAt IS NULL

const user = await User.get({ email: 'joe@example.com' });
// WHERE email = 'joe@example.com' AND deletedAt IS NULL

Soft delete operation

// .delete() on a soft-delete model sets deletedAt, not removes the row
await User.delete({ id: 42 });
// UPDATE users SET deletedAt = '2024-01-15T10:30:00Z' WHERE id = 42

// The row is now invisible to all standard queries
const user = await User.get({ id: 42 }); // null

withTrashed

Access via model.softDelete() which returns a SoftDeleteQueryBuilder<T>.

// .withTrashed() — include soft-deleted rows
const allUsers = await User.softDelete()
  .withTrashed()
  .get();
// SELECT * FROM users (no deletedAt filter)

// Combine with other clauses
const suspendedAdmins = await User.softDelete()
  .withTrashed()
  .where('role', '=', 'admin')
  .get();

onlyTrashed

// .onlyTrashed() — return only soft-deleted rows
const deleted = await User.softDelete()
  .onlyTrashed()
  .get();
// SELECT * FROM users WHERE deletedAt IS NOT NULL

restore

// .restore(filter) — un-delete: sets deletedAt = NULL
await User.restore({ id: 42 });
// UPDATE users SET deletedAt = NULL WHERE id = 42

// User is now visible in standard queries again
const user = await User.get({ id: 42 }); // found

Hard delete note

// To permanently remove a soft-delete row,
// use the query builder with whereRaw to bypass the auto-filter

await User.softDelete()
  .withTrashed()
  .where('id', '=', 42)
  // No direct hardDelete method — use deleteMany after withTrashed
  // or use orm.adapter.exec() for raw DELETE
Clean tables stay clean

The deletedAt column is only added to tables whose model has a field annotated with @softDelete. Models without this annotation are not affected in any way. Migration is non-destructive: existing data is preserved.

PreviousWindow FunctionsNextValidation