# audit() function · @imqueue/pg-prisma

Source: https://imqueue.org/api/pg-prisma/latest/pg-prisma.audit/
Published: 2026-08-01
Author: @imqueue maintainers (https://github.com/imqueue)
Package: @imqueue/pg-prisma 1.0.1 — generated reference, not hand-written

Build the query extension that records every write to an audited model.

**Signature:**

```typescript
export declare function audit(input: AuditOptions): (client: any) => import("@prisma/client/extension").PrismaClientExtends<import("@prisma/client/runtime/client").InternalArgs<{}, {}, {}, {}>>;
```

## Parameters


| Parameter | Type | Description |
| --- | --- | --- |
| input | [AuditOptions](https://imqueue.org/api/pg-prisma/latest/pg-prisma.auditoptions/) | The unextended client, the target config, the audited model names, and the actor resolver. |


**Returns:**

(client: any) => import("@prisma/client/extension").PrismaClientExtends<import("@prisma/client/runtime/client").InternalArgs<{}, {}, {}, {}>>

A Prisma extension to pass to `client.$extends()`.

## Remarks

Rows are inserted into `config.model` under the names in `config.columns`, using raw SQL rather than a Prisma model — which is what lets the trail live in a table Prisma knows nothing about. The row id is generated by Postgres (`gen_random_uuid()`) because a Prisma-level `@default(uuid())` on the target is client-side and never applies to a raw insert.

What gets captured depends on the operation. `create`, `update` and `delete` record the affected record itself, keyed by its `id`. `updateMany` and `deleteMany` cannot identify rows, so they record the query args and the affected count under the literal `recordId` of `'many'`. A model absent from `models` is not recorded, and neither is a single-row write whose result has no `id` — every audited model is assumed to carry a surrogate `id`.

Auditing is fire-and-forget by design: the insert is not awaited, and a failure is swallowed rather than thrown or logged. A write therefore never fails because its audit row could not be stored — and equally, a broken audit configuration is silent. Verify it once against a real table rather than trusting that no error means it is working.

Ordering matters when this is combined with an extension that reroutes an operation to another client — [softDelete()](https://imqueue.org/api/pg-prisma/latest/pg-prisma.softdelete/) turning a delete into an update is exactly that. Prisma runs the first-added query hook outermost, so `audit` must be added FIRST or the rerouted operation never reaches it and vanishes from the trail.

## Example


```typescript
const base = new PrismaClient();
const client = base
    .$extends(audit({
        client: base,
        config: AUDIT_CONFIG,
        models: new Set(['User']),
        getPrincipal: () => context.get()?.user ?? null,
    }))
    .$extends(softDelete({ client: base, models: SOFT_DELETE_MODELS }));
```

