fixed some migration issues and added generics for update and insert

This commit is contained in:
2026-02-09 21:58:50 +11:00
parent bf3e526f1e
commit b89ee75ca7
19 changed files with 591 additions and 261 deletions

View File

@@ -3,13 +3,18 @@ package db
import (
"context"
"database/sql"
"net/http"
"github.com/pkg/errors"
"github.com/uptrace/bun"
)
type deleter[T any] struct {
q *bun.DeleteQuery
tx bun.Tx
q *bun.DeleteQuery
resourceID any // Store ID before deletion for audit
auditCallback AuditCallback
auditRequest *http.Request
}
type systemType interface {
@@ -18,13 +23,27 @@ type systemType interface {
func DeleteItem[T any](tx bun.Tx) *deleter[T] {
return &deleter[T]{
tx.NewDelete().
tx: tx,
q: tx.NewDelete().
Model((*T)(nil)),
}
}
func (d *deleter[T]) Where(query string, args ...any) *deleter[T] {
d.q = d.q.Where(query, args...)
// Try to capture resource ID from WHERE clause if it's a simple "id = ?" pattern
if query == "id = ?" && len(args) > 0 {
d.resourceID = args[0]
}
return d
}
// WithAudit enables audit logging for this delete operation
// The callback will be invoked after successful deletion with auto-generated audit info
// If the callback returns an error, the transaction will be rolled back
func (d *deleter[T]) WithAudit(r *http.Request, callback AuditCallback) *deleter[T] {
d.auditRequest = r
d.auditCallback = callback
return d
}
@@ -34,8 +53,29 @@ func (d *deleter[T]) Delete(ctx context.Context) error {
if errors.Is(err, sql.ErrNoRows) {
return nil
}
return errors.Wrap(err, "bun.DeleteQuery.Exec")
}
return errors.Wrap(err, "bun.DeleteQuery.Exec")
// Handle audit logging if enabled
if d.auditCallback != nil && d.auditRequest != nil {
tableName := extractTableName[T]()
resourceType := extractResourceType(tableName)
action := buildAction(resourceType, "delete")
info := &AuditInfo{
Action: action,
ResourceType: resourceType,
ResourceID: d.resourceID,
Details: nil, // Delete doesn't need details
}
// Call audit callback - if it fails, return error to trigger rollback
if err := d.auditCallback(ctx, d.tx, info, d.auditRequest); err != nil {
return errors.Wrap(err, "audit.callback")
}
}
return nil
}
func DeleteByID[T any](tx bun.Tx, id int) *deleter[T] {