Skip to content

Soft Delete

Global Default + Entity Override

// Global: Default fuer alle Entities
createApp({
features: [...],
softDelete: true, // Default: true
});
// Entity Override: in beide Richtungen
r.entity("order", {
fields: { ... },
// softDelete nicht angegeben → nutzt Global Default
});
r.entity("tempToken", {
fields: { ... },
softDelete: false, // Kein Soft Delete fuer dieses Entity
});
r.entity("auditEntry", {
fields: { ... },
softDelete: true, // Auch wenn Global aus — dieses Entity soft-deletes
});

Was das Framework automatisch macht

OperationVerhalten
DeleteSetzt isDeleted: true, deletedAt, deletedById
Alle QueriesAutomatisch WHERE isDeleted = false
SearchGeloeschte Entities aus Meilisearch entfernt
CacheCache invalidiert bei Delete
RelationsCascading Deletes respektieren Soft Delete

Restore

// Automatisch generiert wenn softDelete: true:
r.writeHandler("order.restore", ...);
// → Setzt isDeleted: false, deletedAt: null

Papierkorb (geloeschte Daten abfragen)

// Queries koennen explizit geloeschte einschliessen:
r.queryHandler("order.list", schema, async (query, ctx) => {
// ctx.includeDeleted = true wenn Admin den Papierkorb oeffnet
});
// Oder als eigener Handler:
r.queryHandler("order.trash", ...); // Nur geloeschte

Hard Delete: Cleanup Job

// Framework liefert automatisch wenn softDelete aktiv:
r.scheduledJob("softDelete.cleanup", {
cron: "0 3 * * *", // Taeglich 3 Uhr
// Loescht Entities die laenger als gracePeriod geloescht sind
});

Grace Period konfigurierbar via Config:

r.config({
keys: {
softDeleteGraceDays: {
type: "number",
default: 30,
access: { write: ["SystemAdmin"], read: ["Admin"] },
},
},
});

Felder (automatisch hinzugefuegt)

Wenn softDelete: true:

  • isDeleted (boolean, default false)
  • deletedAt (date, nullable)
  • deletedById (number, nullable)