softdelete

package
v0.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package softdelete provides a decorator for r3.CRUD[T, ID] that adds Restore and HardDelete capabilities to any CRUD implementation that supports soft-delete.

It follows the same decorator pattern as features/history: the decorator wraps any r3.CRUD[T, ID] and transparently satisfies the same interface, passing all seven CRUD methods through to the inner implementation.

Soft-delete filtering and Delete-as-UPDATE logic remain in the engines (engine/sql, engine/mongo) and ORM drivers (gorm, bun, gopg). The decorator only adds new capabilities:

  • Restore: un-deletes a soft-deleted record by clearing its deleted_at field.
  • HardDelete: permanently removes a record, bypassing soft-delete.

These operations are delegated to the inner CRUD if it implements the SoftDeleter[ID] interface. If it does not, ErrNotSoftDeletable is returned.

Usage:

inner := r3pgx.NewPgxCRUD[User, int64](db)
repo := softdelete.WithSoftDelete[User, int64](inner)

// repo satisfies r3.CRUD[User, int64] — all methods pass through.
// Additionally:
repo.Restore(ctx, userID)    // un-deletes
repo.HardDelete(ctx, userID) // permanent delete

Index

Constants

This section is empty.

Variables

View Source
var ErrNotSoftDeletable = errors.New("r3/softdelete: inner CRUD does not implement SoftDeleter")

ErrNotSoftDeletable is returned when Restore or HardDelete is called on a decorator whose inner CRUD does not implement the SoftDeleter interface.

Functions

This section is empty.

Types

type CRUD

type CRUD[T any, ID comparable] struct {
	// contains filtered or unexported fields
}

CRUD is a decorator that wraps any r3.CRUD[T, ID] and adds Restore and HardDelete capabilities. All seven standard CRUD methods are passed through to the inner implementation unchanged.

Restore and HardDelete are delegated to the inner CRUD if it implements the SoftDeleter[ID] interface. Otherwise, ErrNotSoftDeletable is returned.

func WithSoftDelete

func WithSoftDelete[T any, ID comparable](inner r3.CRUD[T, ID]) *CRUD[T, ID]

WithSoftDelete wraps an existing r3.CRUD with soft-delete capabilities (Restore and HardDelete). All standard CRUD methods pass through unchanged.

func (*CRUD[T, ID]) Aggregate added in v0.0.3

func (s *CRUD[T, ID]) Aggregate(ctx context.Context, qarg ...r3.Query) ([]r3.AggregateRow, error)

Aggregate passes through to the inner CRUD's Aggregate (trashed filtering is an engine concern, like List/Count).

func (*CRUD[T, ID]) AggregateThroughRelation added in v0.0.5

func (s *CRUD[T, ID]) AggregateThroughRelation(
	ctx context.Context, relation string, qarg ...r3.Query,
) ([]r3.AggregateRow, error)

AggregateThroughRelation passes through to the inner CRUD (trashed filtering is an engine concern, like List/Count).

func (*CRUD[T, ID]) Count

func (s *CRUD[T, ID]) Count(ctx context.Context, qarg ...r3.Query) (int64, error)

Count passes through to the inner CRUD.

func (*CRUD[T, ID]) Create

func (s *CRUD[T, ID]) Create(ctx context.Context, entity T) (T, error)

Create passes through to the inner CRUD.

func (*CRUD[T, ID]) Delete

func (s *CRUD[T, ID]) Delete(ctx context.Context, id ID) error

Delete passes through to the inner CRUD.

func (*CRUD[T, ID]) Get

func (s *CRUD[T, ID]) Get(ctx context.Context, id ID, qarg ...r3.Query) (T, error)

Get passes through to the inner CRUD.

func (*CRUD[T, ID]) HardDelete

func (s *CRUD[T, ID]) HardDelete(ctx context.Context, id ID) error

HardDelete permanently removes a record, bypassing soft-delete. It looks for SoftDeleter support anywhere in the inner decorator chain. Returns ErrNotSoftDeletable if no layer implements SoftDeleter.

func (*CRUD[T, ID]) Inner

func (s *CRUD[T, ID]) Inner() r3.CRUD[T, ID]

Inner returns the wrapped CRUD (for advanced usage / unwrapping).

func (*CRUD[T, ID]) List

func (s *CRUD[T, ID]) List(ctx context.Context, qarg ...r3.Query) ([]T, int64, error)

List passes through to the inner CRUD.

func (*CRUD[T, ID]) Patch

func (s *CRUD[T, ID]) Patch(ctx context.Context, entity T, fields r3.Fields) (T, error)

Patch passes through to the inner CRUD.

func (*CRUD[T, ID]) PatchWhere added in v0.0.4

func (s *CRUD[T, ID]) PatchWhere(
	ctx context.Context, filters r3.Filters, entity T, fields r3.Fields,
) (int64, error)

PatchWhere forwards to the inner CRUD's BulkPatcher capability, returning r3.ErrBulkPatchNotSupported when the inner repo does not implement it.

func (*CRUD[T, ID]) Restore

func (s *CRUD[T, ID]) Restore(ctx context.Context, id ID) error

Restore un-deletes a soft-deleted record by clearing its deleted_at field. It looks for SoftDeleter support anywhere in the inner decorator chain, so it works even when other decorators sit between this one and the backend. Returns ErrNotSoftDeletable if no layer implements SoftDeleter.

func (*CRUD[T, ID]) Rewrap

func (s *CRUD[T, ID]) Rewrap(inner r3.CRUD[T, ID]) r3.CRUD[T, ID]

Rewrap rebuilds this decorator around a different inner CRUD (used to re-apply the soft-delete layer on top of a transaction-bound CRUD).

func (*CRUD[T, ID]) Unwrap

func (s *CRUD[T, ID]) Unwrap() r3.CRUD[T, ID]

Unwrap returns the wrapped CRUD so capability detection and transaction propagation can walk the decorator chain.

func (*CRUD[T, ID]) Update

func (s *CRUD[T, ID]) Update(ctx context.Context, entity T) (T, error)

Update passes through to the inner CRUD.

func (*CRUD[T, ID]) Upsert added in v0.0.4

func (s *CRUD[T, ID]) Upsert(ctx context.Context, entity T, opts ...r3.UpsertOption) (T, error)

Upsert forwards to the inner CRUD's Upserter capability (soft-delete adds no concern to an upsert), returning r3.ErrUpsertNotSupported when the inner repo does not implement it.

type SoftDeleter

type SoftDeleter[ID comparable] interface {
	// Restore un-deletes a soft-deleted record by clearing its deleted_at field.
	Restore(ctx context.Context, id ID) error

	// HardDelete permanently removes a record, bypassing soft-delete.
	HardDelete(ctx context.Context, id ID) error
}

SoftDeleter is an optional interface that CRUD implementations can satisfy to support soft-delete restore and hard-delete operations.

Engine-based drivers (engine/sql, engine/mongo) and ORM drivers (gorm, bun, gopg) implement this interface. The decorator checks for it at runtime.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL