Soft Delete
A soft delete stamps a row as deleted instead of removing it. The row drops out of queries, but you can still restore or audit it, and rows pointing at it stay valid. Mark one field softDelete to enable it:
import { Entity, Id, Field } from 'uql-orm';
@Entity()export class User { @Id({ type: Number }) id?: number; @Field({ type: String }) name?: string | null; @Field({ type: 'timestamptz', softDelete: true }) deletedAt?: Date | null;}softDelete: true stamps new Date(). To stamp something else, pass a value, SQL such as currentTimestamp, or a callback, like () => Date.now() for an epoch-millis column. An entity has at most one soft-delete field.
Deleting and reading
Section titled “Deleting and reading”A delete becomes an update that stamps only rows not already deleted:
await pool.deleteOneById(User, 1);UPDATE "User" SET "deletedAt" = $1 WHERE "id" = $2 AND "deletedAt" IS NULLEvery read leaves deleted rows out, through the built-in softDelete query filter, which combines with any filters you define:
const users = await pool.findMany(User, { $select: { id: true, name: true } });SELECT "id", "name" FROM "User" WHERE "deletedAt" IS NULLReading deleted rows
Section titled “Reading deleted rows”The filter steps aside when your $where names the field, so reading only deleted rows is a plain query, which works over HTTP too. To read live and deleted rows together, pass withDeleted(), a server-side option that never travels over the wire. It covers the read’s own rows; populated relations still hide their deleted ones. Given options, withDeleted(opts) returns them with soft-deleted rows let in.
import { withDeleted } from 'uql-orm';
const trashed = await pool.findMany(User, { $where: { deletedAt: { $ne: null } },});const all = await pool.findMany(User, {}, withDeleted());Restoring and hard deletes
Section titled “Restoring and hard deletes”restoreOneById and restoreMany set the field back to null, finding deleted rows despite the filter. { hardDelete: true } removes rows for good, already-deleted ones included:
await pool.restoreMany(User, { $where: { companyId: 5 } });await pool.deleteOneById(User, 1, { hardDelete: true });A soft delete cascades only to related entities that also soft-delete, and keeps the rest. A restore does not cascade, so restore related rows yourself.