noctcore-prisma/prisma-write-in-transaction
Two or more Prisma writes in one function must run inside a
$transaction.
Recommended preset: error · Autofix: no · Suggestions: no · Type information: not needed
Two writes in a row outside a transaction are a partial-failure split-brain: the first commits, the second throws, and the data is left half-written. Nothing in the type system or a happy-path test notices.
What it flags
Section titled “What it flags”The Nth Prisma write (default: the second) in one function body that is not lexically inside a
$transaction(...) call. Both transaction forms count as covered: the interactive callback
$transaction(async (tx) => { ... }) and the array form $transaction([ ... ]). Counting is per
innermost function, so writes split across two methods are never added together.
A call is a Prisma write when its method is one of Prisma’s writes (create, createMany,
createManyAndReturn, update, updateMany, updateManyAndReturn, upsert, delete,
deleteMany) and its receiver looks like a Prisma client: a name in the chain matches
receiverPattern or is one of clientProperties, or the chain’s root is one of txRootNames.
That second condition keeps createHash('sha256').update(x) and this.cache.delete(k) quiet.
async function issue(prisma: PrismaClient) { await prisma.invoice.create({ data }); await prisma.ledgerEntry.create({ data: entry }); // reported}async function issue(prisma: PrismaClient) { await prisma.$transaction(async (tx) => { await tx.invoice.create({ data }); await tx.ledgerEntry.create({ data: entry }); });}What it does not flag
Section titled “What it does not flag”- A single write in a function, including the one-write-per-method repository idiom
(
this.client.invoice.create(...)). - Writes inside either transaction form, interactive callback or array.
- Writes split across two methods: each function body is counted on its own.
- Write-named calls on something that is not a Prisma client (
createHash('sha256').update(x),this.cache.delete(k), an SDK’sthis.client.messages.create(...)whileclientis not inclientProperties).
Options
Section titled “Options”| Option | Type | Default | Meaning |
|---|---|---|---|
thresholdWrites |
integer (>= 2) |
2 |
The Nth non-transactional write in one function is reported. |
receiverPattern |
string (regex source) |
'prisma' |
A name in the receiver chain matching this (case-insensitive) makes it a Prisma client. |
clientProperties |
string[] |
[] |
Extra property names that expose a Prisma client, e.g. ['client'] for a repository base class with a get client(). |
txRootNames |
string[] |
['tx'] |
Root identifiers that are a transaction client, e.g. a tx passed into a helper. |
clientProperties is empty by default on purpose: this.client is just as often an HTTP or SDK
client (this.client.messages.create(...)), and recognising it by name would report that code.
'noctcore-prisma/prisma-write-in-transaction': ['error', { clientProperties: ['client'] }]When not to use it
Section titled “When not to use it”Test setup legitimately performs several writes outside a transaction. Scope the rule to
production source with a files / ignores block rather than living with the noise.