@pipeline-builder/pipeline-data 3.4.113 → 3.4.114

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -110,6 +110,22 @@ export declare abstract class CrudService<TEntity extends BaseEntity, TFilter, T
110
110
  protected onAfterUpdate(_id: string, _entity: TEntity, _userId: string): Promise<void>;
111
111
  /** Called after an entity is soft-deleted */
112
112
  protected onAfterDelete(_id: string, _entity: TEntity, _userId: string): Promise<void>;
113
+ /** Called after a soft-deleted entity is restored (undo the delete). Override
114
+ * for entities whose restore has side-effects (e.g. re-notify). Best-effort. */
115
+ protected onAfterRestore(_id: string, _entity: TEntity, _userId: string): Promise<void>;
116
+ /** Called (best-effort) with the ids about to be hard-purged, BEFORE the
117
+ * delete, so a subclass can tear down dependents that lack ON DELETE CASCADE.
118
+ * Throwing aborts that batch's purge (rows stay tombstoned, retried next tick). */
119
+ protected onBeforePurge(_ids: string[]): Promise<void>;
120
+ /** Called after rows are hard-purged, for external side-effects (e.g. plugin
121
+ * image GC). Best-effort: errors are logged, never block the sweep. */
122
+ protected onAfterPurge(_ids: string[]): Promise<void>;
123
+ /** Retention before a soft-deleted row becomes purge-eligible. Defaults to the
124
+ * shared `SOFT_DELETE_RETENTION_DAYS`; override per entity for a bespoke window. */
125
+ protected get softDeleteRetentionMs(): number;
126
+ /** The `purge_after` value to stamp on a soft-delete: `now + retention`, or the
127
+ * spread-friendly empty object when the entity has no `purge_after` column. */
128
+ private purgeAfterStamp;
113
129
  /**
114
130
  * Org → team hierarchy: when a read is widened to a parent org (`parentOrgId`
115
131
  * set), the parent's rows are outside the caller's RLS scope, so the read must
@@ -241,4 +257,46 @@ export declare abstract class CrudService<TEntity extends BaseEntity, TFilter, T
241
257
  * (shared/sysadmin-managed) records. No-op for entities without an
242
258
  * `accessModifier` column. Callers pass `!isSystemAdmin(req)`. */
243
259
  restrictToPrivate?: boolean): Promise<TEntity[]>;
260
+ /**
261
+ * Restore a soft-deleted (tombstoned) entity: clear `isActive`/`deletedAt`/
262
+ * `deletedBy`/`purgeAfter` so it reappears in normal reads.
263
+ *
264
+ * Matches ONLY a genuine tombstone — `isActive = false` AND `deletedAt IS NOT
265
+ * NULL` — so a merely *deactivated* row (isActive=false, no deletedAt) is never
266
+ * silently "restored". Pinned to the caller's own org (orgId-less sysadmin
267
+ * context spans orgs, matching delete/update). Returns null when there is no
268
+ * such tombstone (already active, purged, or unknown) so the route can 404.
269
+ * A unique-key collision (a live row already holds the key) surfaces as the
270
+ * driver's unique-violation for the route to map to 409 — in practice the
271
+ * tombstone IS the key holder, so this is defensive.
272
+ */
273
+ restore(id: string, orgId: string, userId: string): Promise<TEntity | null>;
274
+ /**
275
+ * Read a soft-deleted entity by id (the inverse of the default `isActive=true`
276
+ * reads) — used by restore routes to load the tombstone for access-control
277
+ * gating before restoring. Returns null unless the row exists AND is a genuine
278
+ * tombstone (`isActive=false` + `deletedAt IS NOT NULL`).
279
+ */
280
+ findDeletedById(id: string, orgId?: string, parentOrgId?: string): Promise<TEntity | null>;
281
+ /**
282
+ * List an org's soft-deleted tombstones (`isActive=false` + `deletedAt IS NOT
283
+ * NULL`), most-recently-deleted first — powers the "recently deleted" restore
284
+ * UI. Returns `[]` for entities without a soft-delete lifecycle. `limit` is
285
+ * clamped to [1, 200] to keep the response bounded (the retention sweep hard-
286
+ * deletes old tombstones anyway, so this is a short, self-limiting list).
287
+ */
288
+ findDeleted(orgId: string, opts?: {
289
+ limit?: number;
290
+ offset?: number;
291
+ }, parentOrgId?: string): Promise<TEntity[]>;
292
+ /**
293
+ * Hard-delete a batch of tombstones whose purge deadline has passed
294
+ * (`deletedAt IS NOT NULL AND purge_after < now`). Batched (`limit`) so a
295
+ * sweep tick stays bounded; the per-service sweep loops until a tick returns
296
+ * `< limit`. Runs across ALL orgs, so callers MUST invoke it from a system
297
+ * (no-tenant) context. `onBeforePurge` tears down dependents lacking ON DELETE
298
+ * CASCADE (inside the tx); `onAfterPurge` handles external side-effects.
299
+ * Returns the number of rows purged. No-op (0) for entities without the columns.
300
+ */
301
+ purgeExpired(now: Date, limit?: number): Promise<number>;
244
302
  }