Skip to content

@unthrown/prisma


@unthrown/prisma ​

Classes ​

ForeignKeyViolation ​

Defined in: packages/prisma/src/index.ts:84

A foreign key constraint was violated (Prisma error P2003).

Extends ​

  • TaggedErrorInstance<"ForeignKeyViolation", { cause: unknown; }>

Constructors ​

Constructor ​
ts
new ForeignKeyViolation(fields): ForeignKeyViolation;

Defined in: packages/prisma/src/index.ts:85

Parameters ​
ParameterType
fields{ cause: unknown; }
fields.causeunknown
Returns ​

ForeignKeyViolation

Overrides ​
ts
TaggedError("ForeignKeyViolation")<{ cause: unknown }>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
_tagreadonly"ForeignKeyViolation"TaggedError("ForeignKeyViolation")._tagpackages/core/dist/index.d.mts:2360
causepublicunknownTaggedError("ForeignKeyViolation").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstringTaggedError("ForeignKeyViolation").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstringTaggedError("ForeignKeyViolation").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
stack?publicstringTaggedError("ForeignKeyViolation").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

InvalidCursor ​

Defined in: packages/prisma/src/index.ts:121

The cursor handed to withCursor could not be used — the caller's parseCursor rejected it, or the query it produced was one Prisma refuses.

Remarks ​

The one anticipated failure of pagination, and the reason it is modeled at all: a cursor is an opaque string from the outside world (a query parameter), so a client sending garbage is input you answer with a 400 — not a bug in your code. Every other pagination failure is a defect, like any other query.

Extends ​

  • TaggedErrorInstance<"InvalidCursor", { cause: unknown; }>

Constructors ​

Constructor ​
ts
new InvalidCursor(fields): InvalidCursor;

Defined in: packages/prisma/src/index.ts:122

Parameters ​
ParameterType
fields{ cause: unknown; }
fields.causeunknown
Returns ​

InvalidCursor

Overrides ​
ts
TaggedError("InvalidCursor")<{ cause: unknown }>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
_tagreadonly"InvalidCursor"TaggedError("InvalidCursor")._tagpackages/core/dist/index.d.mts:2360
causepublicunknownTaggedError("InvalidCursor").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstringTaggedError("InvalidCursor").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstringTaggedError("InvalidCursor").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
stack?publicstringTaggedError("InvalidCursor").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

RecordNotFound ​

Defined in: packages/prisma/src/index.ts:103

A record required by the operation does not exist (Prisma errors P2025 and P2018) — the missing row of a findUniqueOrThrow, update, or delete, or the missing target of a nested connect.

Remarks ​

The nested-connect case is why tryCreate and tryUpsert carry this error despite never "missing" a row of their own: create({ data: { author: { connect: { id } } } }) raises P2025 when that author does not exist (and P2018 for the to-many side of the same mistake). Both codes say the same thing — a record the write depended on was not found — so both map here.

Extends ​

  • TaggedErrorInstance<"RecordNotFound", { cause: unknown; }>

Constructors ​

Constructor ​
ts
new RecordNotFound(fields): RecordNotFound;

Defined in: packages/prisma/src/index.ts:104

Parameters ​
ParameterType
fields{ cause: unknown; }
fields.causeunknown
Returns ​

RecordNotFound

Overrides ​
ts
TaggedError("RecordNotFound")<{ cause: unknown }>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
_tagreadonly"RecordNotFound"TaggedError("RecordNotFound")._tagpackages/core/dist/index.d.mts:2360
causepublicunknownTaggedError("RecordNotFound").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
messagepublicstringTaggedError("RecordNotFound").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstringTaggedError("RecordNotFound").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
stack?publicstringTaggedError("RecordNotFound").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

UniqueConstraintViolation ​

Defined in: packages/prisma/src/index.ts:73

A unique constraint was violated (Prisma error P2002).

Remarks ​

fields carries the offending column set from the error's meta.target (empty when the driver does not report it).

Extends ​

  • TaggedErrorInstance<"UniqueConstraintViolation", { cause: unknown; fields: readonly string[]; }>

Constructors ​

Constructor ​
ts
new UniqueConstraintViolation(fields): UniqueConstraintViolation;

Defined in: packages/prisma/src/index.ts:77

Parameters ​
ParameterType
fields{ cause: unknown; fields: readonly string[]; }
fields.causeunknown
fields.fieldsreadonly string[]
Returns ​

UniqueConstraintViolation

Overrides ​
ts
TaggedError("UniqueConstraintViolation")<{
  fields: readonly string[];
  cause: unknown;
}>.constructor

Properties ​

PropertyModifierTypeInherited fromDefined in
_tagreadonly"UniqueConstraintViolation"TaggedError("UniqueConstraintViolation")._tagpackages/core/dist/index.d.mts:2360
causepublicunknownTaggedError("UniqueConstraintViolation").causenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es2022.error.d.ts:24
fieldsreadonlyreadonly string[]TaggedError("UniqueConstraintViolation").fieldspackages/prisma/src/index.ts:74
messagepublicstringTaggedError("UniqueConstraintViolation").messagenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1075
namepublicstringTaggedError("UniqueConstraintViolation").namenode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1074
stack?publicstringTaggedError("UniqueConstraintViolation").stacknode_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1076

Type Aliases ​

CreateError ​

ts
type CreateError = 
  | UniqueConstraintViolation
  | ForeignKeyViolation
  | RecordNotFound;

Defined in: packages/prisma/src/index.ts:250

What tryCreate can fail with.


CreateManyError ​

ts
type CreateManyError = 
  | UniqueConstraintViolation
  | ForeignKeyViolation;

Defined in: packages/prisma/src/index.ts:252

What tryCreateMany / tryCreateManyAndReturn can fail with.


CursorPaginationMeta ​

ts
type CursorPaginationMeta = object & 
  | {
  endCursor: string;
  startCursor: string;
}
  | {
  endCursor: null;
  startCursor: null;
};

Defined in: packages/prisma/src/pagination.ts:20

The page metadata of withCursor.

Type Declaration ​

NameTypeDefined in
hasNextPagebooleanpackages/prisma/src/pagination.ts:22
hasPreviousPagebooleanpackages/prisma/src/pagination.ts:21

Remarks ​

startCursor / endCursor are the cursors of the page's boundary rows, so they are null together exactly when the page is empty — checking one narrows the other. They are deliberately NOT coupled to the flags: the last page has hasNextPage: false with a non-null endCursor, and an empty page past the end has hasPreviousPage: true with a null startCursor.


CursorPaginationOptions ​

ts
type CursorPaginationOptions<Row, Cursor> = object & 
  | {
  after?: string;
  before?: never;
  limit: number;
}
  | {
  after?: never;
  before?: string;
  limit: number;
}
  | {
  after?: string;
  before?: never;
  limit: null;
};

Defined in: packages/prisma/src/pagination.ts:49

Options of withCursor, in the style of prisma-extension-pagination.

Type Declaration ​

NameTypeDescriptionDefined in
getCursor()?(row) => stringSerialize a row into an opaque cursor. Defaults to row.id, as described above.packages/prisma/src/pagination.ts:51
parseCursor()?(cursor) => CursorParse an opaque cursor back into the model's cursor input.packages/prisma/src/pagination.ts:53

Type Parameters ​

Type ParameterDescription
Rowthe (selection-narrowed) result row type.
Cursorthe model's cursor input (its unique-where shape).

Remarks ​

after and before are mutually exclusive — a page runs in one direction, and passing both used to silently drop after. Pick a direction.

limit: null returns everything (from the after cursor when given). Combining limit: null with before is a compile error — "everything before the cursor, backwards, unbounded" is not something Prisma's negative take can express.

The default cursor is the record's id field, serialized with String and parsed back to a number when it is all digits (autoincrement ids) — a bigint once it exceeds Number.MAX_SAFE_INTEGER, so BigInt ids never lose precision — or kept as a string otherwise (uuid / cuid ids). A string id that is itself all digits is serialized with a leading ~ ("~123"), so it parses back to the string rather than to a number. Provide getCursor / parseCursor for composite keys, or when the selection omits id.


CursorPaginator ​

ts
type CursorPaginator<Results, Cursor> = object;

Defined in: packages/prisma/src/index.ts:352

What tryPaginate returns: a builder holding the query, consumed by withCursor.

Type Parameters ​

Type ParameterDescription
Results extends readonly unknown[]the (selection-narrowed) findMany payload.
Cursorthe model's cursor input (its unique-where shape).

Properties ​

PropertyModifierTypeDescriptionDefined in
withCursorreadonly(options) => AsyncResult<[Results, CursorPaginationMeta], InvalidCursor>Run the paginated query: the page and its metadata, or an InvalidCursor — the only modeled failure, since the cursor is the only part of the query that came from outside.packages/prisma/src/index.ts:358

DeleteError ​

ts
type DeleteError = 
  | RecordNotFound
  | UniqueConstraintViolation
  | ForeignKeyViolation;

Defined in: packages/prisma/src/index.ts:260

What tryDelete can fail with — UniqueConstraintViolation included, raised when an onDelete: SetDefault / SetNull rewrite of the referencing rows collides with a unique index.


DeleteManyError ​

ts
type DeleteManyError = 
  | UniqueConstraintViolation
  | ForeignKeyViolation;

Defined in: packages/prisma/src/index.ts:266

What tryDeleteMany can fail with — see DeleteError.


PrismaQueryError ​

ts
type PrismaQueryError = 
  | UniqueConstraintViolation
  | ForeignKeyViolation
  | RecordNotFound;

Defined in: packages/prisma/src/index.ts:140

The full union of domain errors a Prisma query can surface.

Remarks ​

This is the RUNTIME-side union: qualifyPrismaError maps into it. Each try* method narrows the static type to the codes its operation can actually hit — a read hits none of them, so it is typed never.

Infrastructure failures are deliberately absent: they are defects, not values (see qualifyPrismaError). InvalidCursor is absent too — it belongs to pagination, not to a query.


TransactionClient ​

ts
type TransactionClient<C> = Omit<C, TxDenyList>;

Defined in: packages/prisma/src/index.ts:405

The client an interactive $tryTransaction callback receives — the extended client minus what a transaction cannot do.

Type Parameters ​

Type ParameterDescription
Cthe extended client, usually typeof db.

Remarks ​

Name the tx parameter of a helper factored out of a callback with this, rather than restating the deny list: $tryTransaction uses the very same alias, so the two cannot drift. Restating it by hand does drift silently — Omit of a key that does not exist is not an error, so a hand-copied list keeps compiling after the library's own list changes.

Not to be confused with Prisma's own generated Prisma.TransactionClient — that one is non-generic and, notably, does not remove $tryTransaction.

Example ​

ts
type Tx = TransactionClient<typeof db>;

const chargeFees = (tx: Tx, id: number) =>
  tx.invoice.tryUpdate({ where: { id }, data: { charged: true } });

db.$tryTransaction((tx) => chargeFees(tx, 1));

TransactionIsolationLevel ​

ts
type TransactionIsolationLevel = 
  | "ReadUncommitted"
  | "ReadCommitted"
  | "RepeatableRead"
  | "Snapshot"
  | "Serializable";

Defined in: packages/prisma/src/index.ts:338

The isolation levels Prisma accepts across databases, as a closed union.

Remarks ​

The schema-derived Prisma.TransactionIsolationLevel of a generated client is narrower (it lists only what YOUR database supports), but a shareable extension cannot name a generated type — this union at least rejects typos at compile time; a level your database does not support still fails at runtime as a defect (an unsupported level is a bug, not an outcome).


TryTransaction ​

ts
type TryTransaction = {
<C, T, E>  (this, fn, options?): AsyncResult<T, PrismaQueryError | E>;
<C, P>  (this, operations, options?): AsyncResult<UnwrapPrismaTuple<P>, PrismaQueryError>;
};

Defined in: packages/prisma/src/index.ts:425

The type of $tryTransaction: overloaded exactly as Prisma's own $transaction is — an interactive callback, or a batch of raw operations.

Call Signature ​

ts
<C, T, E>(
   this, 
   fn, 
   options?
): AsyncResult<T, PrismaQueryError | E>;

An interactive transaction whose callback speaks AsyncResult: an Err triggers a ROLLBACK and comes out as the same typed Err.

Type Parameters ​
Type Parameter
C
T
E
Parameters ​
ParameterType
thisC
fn(tx) => AsyncResult<T, E>
options?{ isolationLevel?: TransactionIsolationLevel; maxWait?: number; timeout?: number; }
options.isolationLevel?TransactionIsolationLevel
options.maxWait?number
options.timeout?number
Returns ​

AsyncResult<T, PrismaQueryError | E>

Remarks ​

The callback's Err is thrown internally as a sentinel so Prisma aborts the transaction, then unwrapped back into the typed error channel — AsyncResult<T, E | PrismaQueryError>. A defect inside the callback also rolls back and stays a defect — including a callback that throws instead of returning an AsyncResult (a bug, never downgraded to a modeled error). The try* methods are available on tx (extensions propagate into the interactive transaction); the deny list additionally removes $tryTransaction itself — no nesting. Name a helper's tx parameter with TransactionClient.

The | PrismaQueryError is not merely defensive: a deferred constraint surfaces its violation at COMMIT rather than at the statement, so the transaction boundary itself can produce one. Prisma's own machinery failing any other way (a maxWait / timeout expiry, a lost connection) is infrastructure, and so a defect like everywhere else.

Example ​
ts
const moved = db.$tryTransaction((tx) =>
  tx.account
    .tryUpdate({ where: { id: from }, data: { balance: { decrement: amount } } })
    .flatMap(() =>
      tx.account.tryUpdate({
        where: { id: to },
        data: { balance: { increment: amount } },
      }),
    ),
);
// Err anywhere → both updates rolled back, and the Err is in `moved`.

Call Signature ​

ts
<C, P>(
   this, 
   operations, 
   options?
): AsyncResult<UnwrapPrismaTuple<P>, PrismaQueryError>;

A batch transaction: the operations run in one round trip, all or nothing, with no application code held open in between.

Type Parameters ​
Type Parameter
C
P extends readonly PrismaPromise<unknown>[]
Parameters ​
ParameterType
thisC
operationsreadonly [P]
options?{ isolationLevel?: TransactionIsolationLevel; }
options.isolationLevel?TransactionIsolationLevel
Returns ​

AsyncResult<UnwrapPrismaTuple<P>, PrismaQueryError>

Remarks ​

Two things follow from Prisma's batch form taking unexecutedPrismaPromises, and both are deliberate:

  • The array holds the raw delegate methods — db.user.create(...), not tryCreate. A try* method has already executed and returns an AsyncResult, so passing one is a compile error.
  • E is the whole PrismaQueryError union rather than the per-operation narrowing the try* methods give: a raw PrismaPromise carries no error-type information. Every infrastructure failure is still a defect, exactly as everywhere else.

A fixed tuple keeps positional types; a dynamic array (a .map(...)) collapses to AsyncResult<T[], PrismaQueryError>.

maxWait and timeout are absent by design — they govern an interactive transaction's open window, which a single-round-trip batch does not have.

Example ​
ts
const rows = db.$tryTransaction(
  inputs.map((data) => db.user.create({ data })),
);
//    ^? AsyncResult<User[], PrismaQueryError>
// Any constraint violation → nothing is written, and the Err is modeled.

TxDenyList ​

ts
type TxDenyList = 
  | "$connect"
  | "$disconnect"
  | "$on"
  | "$transaction"
  | "$use"
  | "$extends"
  | "$tryTransaction";

Defined in: packages/prisma/src/index.ts:370

What an interactive-transaction client cannot do: Prisma's own ITXClientDenyList, plus $tryTransaction itself — nested transactions are not a thing, and the itx client has no $transaction for the bridge to delegate to. Name a tx with TransactionClient rather than Omit-ing this by hand.


UnwrapPrismaTuple ​

ts
type UnwrapPrismaTuple<P> = { -readonly [K in keyof P]: P[K] extends Prisma.PrismaPromise<infer X> ? X : never };

Defined in: packages/prisma/src/index.ts:417

The results of a batch $tryTransaction([...]): each PrismaPromise<T> unwrapped to its T. A fixed tuple keeps positional types; a dynamic PrismaPromise<T>[] collapses to T[] — the same duality as core's all.

Type Parameters ​

Type Parameter
P extends readonly unknown[]

Remarks ​

Prisma's own UnwrapTuple lives at runtime.Types.Utils.UnwrapTuple, behind a runtime entry path this package deliberately never imports (it moved between Prisma 6 and 7), so the mapping is written here.


UpdateError ​

ts
type UpdateError = 
  | RecordNotFound
  | UniqueConstraintViolation
  | ForeignKeyViolation;

Defined in: packages/prisma/src/index.ts:254

What tryUpdate can fail with.


UpdateManyError ​

ts
type UpdateManyError = 
  | UniqueConstraintViolation
  | ForeignKeyViolation;

Defined in: packages/prisma/src/index.ts:264

What tryUpdateMany / tryUpdateManyAndReturn can fail with.


UpsertError ​

ts
type UpsertError = 
  | UniqueConstraintViolation
  | ForeignKeyViolation
  | RecordNotFound;

Defined in: packages/prisma/src/index.ts:262

What tryUpsert can fail with.

Variables ​

unthrownPrisma ​

ts
const unthrownPrisma: (client) => PrismaClientExtends<InternalArgs<{
}, {
  $allModels: {
     tryAggregate: AsyncResult<Result<T, A, "aggregate">, never>;
     tryCount: AsyncResult<Result<T, A, "count">, never>;
     tryCreate: AsyncResult<Result<T, A, "create">, CreateError>;
     tryCreateMany: AsyncResult<Result<T, A, "createMany">, CreateManyError>;
     tryCreateManyAndReturn: AsyncResult<Result<T, A, "createManyAndReturn">, CreateManyError>;
     tryDelete: AsyncResult<Result<T, A, "delete">, DeleteError>;
     tryDeleteMany: AsyncResult<Result<T, A, "deleteMany">, DeleteManyError>;
     tryFindFirst: AsyncResult<Result<T, A, "findFirst">, never>;
     tryFindFirstOrThrow: AsyncResult<Result<T, A, "findFirstOrThrow">, RecordNotFound>;
     tryFindMany: AsyncResult<Result<T, A, "findMany">, never>;
     tryFindUnique: AsyncResult<Result<T, A, "findUnique">, never>;
     tryFindUniqueOrThrow: AsyncResult<Result<T, A, "findUniqueOrThrow">, RecordNotFound>;
     tryGroupBy: AsyncResult<Result<T, A, "groupBy">, never>;
     tryPaginate: CursorPaginator<Result<T, A, "findMany">, NonNullable<Args<T, "findMany">["cursor"]>>;
     tryUpdate: AsyncResult<Result<T, A, "update">, UpdateError>;
     tryUpdateMany: AsyncResult<Result<T, A, "updateMany">, UpdateManyError>;
     tryUpdateManyAndReturn: AsyncResult<Result<T, A, "updateManyAndReturn">, UpdateManyError>;
     tryUpsert: AsyncResult<Result<T, A, "upsert">, UpsertError>;
  };
}, {
}, {
  $tryTransaction: TryTransaction;
}>>;

Defined in: packages/prisma/src/index.ts:589

The Prisma Client extension. Apply it with $extends to add the try* methods to every model delegate, and $tryTransaction to the client.

Parameters ​

ParameterType
clientany

Returns ​

PrismaClientExtends<InternalArgs<{ }, { $allModels: { tryAggregate: AsyncResult<Result<T, A, "aggregate">, never>; tryCount: AsyncResult<Result<T, A, "count">, never>; tryCreate: AsyncResult<Result<T, A, "create">, CreateError>; tryCreateMany: AsyncResult<Result<T, A, "createMany">, CreateManyError>; tryCreateManyAndReturn: AsyncResult<Result<T, A, "createManyAndReturn">, CreateManyError>; tryDelete: AsyncResult<Result<T, A, "delete">, DeleteError>; tryDeleteMany: AsyncResult<Result<T, A, "deleteMany">, DeleteManyError>; tryFindFirst: AsyncResult<Result<T, A, "findFirst">, never>; tryFindFirstOrThrow: AsyncResult<Result<T, A, "findFirstOrThrow">, RecordNotFound>; tryFindMany: AsyncResult<Result<T, A, "findMany">, never>; tryFindUnique: AsyncResult<Result<T, A, "findUnique">, never>; tryFindUniqueOrThrow: AsyncResult<Result<T, A, "findUniqueOrThrow">, RecordNotFound>; tryGroupBy: AsyncResult<Result<T, A, "groupBy">, never>; tryPaginate: CursorPaginator<Result<T, A, "findMany">, NonNullable<Args<T, "findMany">["cursor"]>>; tryUpdate: AsyncResult<Result<T, A, "update">, UpdateError>; tryUpdateMany: AsyncResult<Result<T, A, "updateMany">, UpdateManyError>; tryUpdateManyAndReturn: AsyncResult<Result<T, A, "updateManyAndReturn">, UpdateManyError>; tryUpsert: AsyncResult<Result<T, A, "upsert">, UpsertError>; }; }, { }, { $tryTransaction: TryTransaction; }>>

Remarks ​

Typing follows Prisma's documented $allModels pattern: this: T binds the concrete delegate, Prisma.Exact checks args, and Prisma.Result computes the payload — so select / include inference survives the wrap.

Example ​

ts
import { PrismaClient } from "./generated/prisma/client.ts";
import { unthrownPrisma } from "@unthrown/prisma";

const db = new PrismaClient({ adapter }).$extends(unthrownPrisma);

const users = db.user.tryFindMany({ select: { id: true } });
//    ^? AsyncResult<{ id: number }[], never>  — a read has no modeled failure

Functions ​

qualifyPrismaError() ​

ts
function qualifyPrismaError<D>(cause, defect): D | PrismaQueryError;

Defined in: packages/prisma/src/index.ts:206

Qualify a Prisma rejection — the runtime half of the bridge, and a ready-made qualify for any boundary you build yourself (raw SQL).

Type Parameters ​

Type Parameter
D

Parameters ​

ParameterTypeDescription
causeunknownthe rejected value from a Prisma query.
defect(cause) => Dthe defect helper the boundary injects (never import it).

Returns ​

D | PrismaQueryError

Remarks ​

The three P-codes that describe a domain outcome map to their tagged errors — P2002 → UniqueConstraintViolation, P2003 → ForeignKeyViolation, P2025 / P2018 → RecordNotFound.

Everything else is a defect, with the original cause preserved: a dropped connection, a pool timeout, a deadlock, an unmapped P-code, a malformed query, a client that could not start, an engine panic. None of those is something domain code branches on — they are logged and turned into a 500 at the edge, which is precisely what the defect channel is for. Modelling them would force every call site to carry an arm that duplicates its own defect arm.

A defect is not a crash: it flows through the pipeline untouched and is folded by match's defect handler like any other unmodeled failure.

Example ​

ts
// Pass it straight to a boundary — `defect` is injected for you.
const rows = fromPromise(db.$queryRaw`SELECT 1`, qualifyPrismaError);

Released under the MIT License.