@shivaedev/effect-changes-prisma 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.1 - 2026-10-17
4
+
5
+ ### Fixed
6
+
7
+ - Publish against `@shivaedev/types` 0.2.1 so framework consumers share the current version.
8
+
9
+ ## 0.5.0 - 2026-10-13
10
+
11
+ ### Changed
12
+
13
+ - Prefix generic type parameter names in the Prisma binding, model mappings, transaction helpers and affected test fixtures with `T`; their types and runtime behavior stay the same.
14
+ - Explain the package's purpose, model mappings, transaction boundary and test coverage in its README, agent north star and package docs; publish `docs/` with the README while keeping agent instructions out of the package.
15
+ - Build package JavaScript, declarations and source maps with TypeScript 7.
16
+
17
+ ### Breaking
18
+
19
+ - Requires stable Effect 4.0.4 in place of 4.0.0-rc.112. Effect 4.0.4 moves the former `effect/unstable/*` modules to `effect/*` and renames constructors such as `Config.string` to `Config.String`.
20
+
3
21
  ## 0.4.0 - 2026-10-04
4
22
 
5
23
  ### Changed
package/README.md CHANGED
@@ -1,21 +1,49 @@
1
1
  # @shivaedev/effect-changes-prisma
2
2
 
3
- Commit-bound change channels for Prisma Classic (`@prisma/client` with interactive `$transaction`). Writes to mapped models record their changes automatically; the changes publish once, deduplicated, after the transaction commits, and never for a rollback. A test-time coverage check reports writes that no recorded change accounts for.
3
+ Prisma applications need to announce changes after rows commit, even when a caller is interrupted or a transaction fails at COMMIT. This package binds Prisma Classic on PostgreSQL to effect-changes: returned model rows name changes, the transaction outcome decides when they publish, and tests can find written tables that no recorded change covers.
4
4
 
5
- It works with PostgreSQL only. The coverage check reads PostgreSQL's `pg_stat_xact_user_tables`, `isolationLevel` takes the levels Prisma accepts on PostgreSQL, and every test runs against PostgreSQL.
5
+ ## Why you want this
6
6
 
7
- It binds a [`@shivaedev/effect-changes`](../effect-changes) channel to Prisma: the channel semantics (owners, savepoint merge and discard, batches, sink failures, test seams) are the same, see [commit-bound changes](../../docs/framework/changes.md).
7
+ Publishing from a write method can tell readers about rows that later roll back. Repeating a publication call after every transaction makes it easy to miss one. Put the meaning in a model map and use the same write path in each action:
8
+
9
+ ```ts
10
+ const addMember = (id: string, ownerId: string, memberId: string) =>
11
+ changes.use((db) => db.membership.create({ data: { id, ownerId, memberId } })).pipe(changes.transaction);
12
+ ```
13
+
14
+ The binding named `changes` maps a membership row to its owner and member. This action publishes their changes after COMMIT; a rollback publishes nothing. Several writes in one action become one deduplicated batch, and a caller interrupted while COMMIT is in flight still gets its landed changes published.
15
+
16
+ ## Using it
17
+
18
+ ### How to think about it
19
+
20
+ Prisma Classic here means the generated Prisma Client API with interactive `$transaction` callbacks. The separate [effect-prisma package](https://github.com/ShivaeDev/platform/tree/main/packages/effect-prisma#readme) provides a database facade for Prisma Next.
21
+
22
+ A **change** is application data, such as `{ subject, domain }`. A **model map** turns a returned Prisma row into the changes it names; `null` classifies a model whose writes need no changes. A **binding** joins that map and a publication sink to a base Prisma client.
23
+
24
+ The binding's `Client` reference identifies the client for the current Effect scope. `use(query)` runs against that client and records mapped writes. `transaction(body)` provides Prisma's transaction client to the body and opens a **change frame**, a buffer of changes waiting for a transaction outcome. The `$transaction` promise settles that frame. The body finishing is not enough: the database can still reject COMMIT.
25
+
26
+ A nested binding transaction runs as a Prisma savepoint. Its successful frame merges into the parent and publishes with the parent; its failed frame is discarded. Outside a binding transaction or batch, a successful mapped write publishes after autocommit.
27
+
28
+ The work splits into three parts:
29
+
30
+ 1. Once per application, define change data, bind the client and choose the sink.
31
+ 2. Once per model or feature, define which changes its returned rows name.
32
+ 3. In each action, run Prisma calls through `use` and wrap the action in `transaction`.
33
+
34
+ ### 1. Bind the client and classify the models
8
35
 
9
36
  ```ts
10
- import type { ChangeMap } from "@shivaedev/effect-changes-prisma/model.ts";
11
37
  import { makePrismaChanges } from "@shivaedev/effect-changes-prisma/changes.ts";
38
+ import type { ChangeMap } from "@shivaedev/effect-changes-prisma/model.ts";
12
39
  import { Effect } from "effect";
13
- import { PrismaClient } from "./generated/client.ts";
40
+ import type { PrismaClient } from "./generated/client.ts";
14
41
 
15
42
  interface Change {
16
43
  readonly subject: string;
17
44
  readonly domain: string;
18
45
  }
46
+
19
47
  declare const prisma: PrismaClient;
20
48
  declare const bus: { readonly emit: (change: Change) => void };
21
49
 
@@ -36,114 +64,248 @@ const changes = makePrismaChanges({
36
64
  key: (change) => `${change.subject}:${change.domain}`,
37
65
  publish: (batch: ReadonlyArray<Change>) => Effect.sync(() => batch.forEach((change) => bus.emit(change))),
38
66
  });
67
+ ```
39
68
 
40
- const addMember = (id: string, ownerId: string, memberId: string) =>
41
- changes.use((db) => db.membership.create({ data: { id, ownerId, memberId } })).pipe(changes.transaction);
69
+ This example has four Prisma models. A membership names both people; an audit note needs no publication. `satisfies ChangeMap<PrismaClient, Change>` checks the model names and scalar fields and requires every model to be classified. The binding also accepts a partial map; an absent model records nothing. `key` groups repeated changes for the same subject and domain into one entry in the published batch.
70
+
71
+ The application's generated client determines the models and row types. The client passed to `use` has the transaction-client type, so transaction-unavailable methods such as `$extends` are not offered there. The base client remains the binding's channel owner; providing a different current `Client` changes which client runs the calls.
72
+
73
+ ### 2. Run an action through the binding
74
+
75
+ ```ts
76
+ const saveOrder = (id: string, ownerId: string, total: number) =>
77
+ Effect.gen(function* () {
78
+ const order = yield* changes.use((db) => db.order.create({ data: { id, ownerId, total } }));
79
+ yield* changes.use((db) => db.auditNote.create({ data: { id: `saved-${id}`, text: "saved" } }));
80
+ return order;
81
+ }).pipe(changes.transaction);
42
82
  ```
43
83
 
44
- ## API
84
+ Both calls use the transaction client. The order records its owner's change; the audit note is classified as `null`. Publication happens after COMMIT and before `saveOrder` returns its row.
85
+
86
+ Use another `transaction` inside a body when a step needs its own savepoint:
45
87
 
46
88
  ```ts
47
- makePrismaChanges<Tx extends Transactional<Tx>, A, R = never>(options: PrismaChangesOptions<Tx, A, R>): PrismaChanges<Tx, A, R>
89
+ import { Data } from "effect";
48
90
 
49
- interface PrismaChangesOptions<Tx, A, R> extends Omit<ChannelOptions<A, R>, "owner" | "unowned"> {
50
- readonly client: Tx & Transactional<Tx>;
51
- readonly models: Partial<ChangeMap<Tx, A>>;
52
- }
91
+ class Rejected extends Data.TaggedError("Rejected") {}
53
92
 
54
- interface PrismaChanges<Tx, A, R> {
55
- readonly channel: Channel<A, R>;
56
- readonly Client: Context.Reference<Tx>;
57
- readonly use: <X>(query: (client: Tx) => PromiseLike<X>) => Effect<X, PrismaError, R>;
58
- readonly transaction: <X, E, R2>(body: Effect<X, E, R2>, options?: TransactionOptions) => Effect<X, E | TransactionExpired | PrismaError, R | R2>;
59
- readonly recordWrite: (write: Write) => Effect<void, never, R>;
60
- readonly Unnamed: Context.Reference<(write: UnnamedWrite) => Effect<void>>;
61
- }
93
+ const saveWithOptionalMember = Effect.gen(function* () {
94
+ yield* changes.use((db) => db.order.create({ data: { id: "o1", ownerId: "ada", total: 10 } }));
62
95
 
63
- type ChangeMap<Client, A> = { readonly [Model in ModelName<Client>]: ((row: ModelRow<Client, Model>, operation: RowOperation) => Iterable<A>) | null };
64
- type RowOperation = "create" | "update" | "upsert" | "delete" | "createManyAndReturn" | "updateManyAndReturn";
65
- type UnnamedWrite =
66
- | { readonly model: string; readonly operation: string; readonly reason: "countOnly" }
67
- | { readonly model: string; readonly operation: string; readonly reason: "narrowed"; readonly field: string };
68
- class PrismaError { readonly _tag: "PrismaError"; readonly cause: unknown }
69
- class TransactionExpired { readonly _tag: "TransactionExpired"; readonly message: string; readonly cause?: unknown }
96
+ const member = yield* Effect.exit(
97
+ Effect.andThen(
98
+ changes.use((db) => db.membership.create({ data: { id: "m1", ownerId: "ada", memberId: "bob" } })),
99
+ Effect.fail(new Rejected()),
100
+ ).pipe(changes.transaction),
101
+ );
102
+
103
+ return member;
104
+ }).pipe(changes.transaction);
105
+ ```
106
+
107
+ The failed member step rolls back its savepoint and discards its changes; the surrounding order can commit. A released savepoint's changes still disappear if its parent later rolls back.
108
+
109
+ ### Returned rows and unnamed writes
70
110
 
71
- tablesOf(schema: string): ReadonlyMap<string, string>
72
- tableWrites(client: RawQueryClient): Effect<TableWrites, PrismaError>
73
- writtenTables(client: RawQueryClient, since?: TableWrites): Effect<ReadonlyArray<string>, PrismaError>
74
- checkCoverage<A>(coverage: Coverage<A>): ReadonlyArray<CoverageViolation>
111
+ Row-returning operations are `create`, `update`, `upsert`, `delete`, `createManyAndReturn` and `updateManyAndReturn`. The model mapping receives each returned row, so a single membership can name several subjects and a returned array can name changes from several rows.
112
+
113
+ Count-only `createMany`, `updateMany` and `deleteMany` on mapped models do not provide rows for the mapping. They record nothing and report `{ model, operation, reason: "countOnly" }` to `changes.Unnamed`, including when the count is zero. A returned row missing a field the mapping reads records nothing for that write and reports `reason: "narrowed"` with the field name.
114
+
115
+ ```ts
116
+ import type { UnnamedWrite } from "@shivaedev/effect-changes-prisma/write.ts";
117
+
118
+ const unnamed: Array<UnnamedWrite> = [];
119
+
120
+ const updateWithoutOwner = changes
121
+ .use((db) => db.order.update({ where: { id: "o1" }, data: { total: 20 }, select: { id: true } }))
122
+ .pipe(
123
+ changes.transaction,
124
+ Effect.provideService(changes.Unnamed, (write) => Effect.sync(() => unnamed.push(write))),
125
+ );
126
+ ```
127
+
128
+ With the map above, this result lacks `ownerId`, so the observer receives `{ model: "Order", operation: "update", reason: "narrowed", field: "ownerId" }`. Reads, absent models and models classified as `null` record nothing.
129
+
130
+ For an existing application wrapper, feed its observed result into the same map:
131
+
132
+ ```ts
133
+ const recordMembership = Effect.gen(function* () {
134
+ yield* changes.recordWrite({
135
+ model: "Membership",
136
+ operation: "create",
137
+ result: { ownerId: "ada", memberId: "bob" },
138
+ });
139
+ });
75
140
  ```
76
141
 
77
- - `client` is the base client, usually a `PrismaClient`, or one you extended. `Tx` is inferred as the client its `$transaction` callback receives. The channel's owner is this client, so frames are kept per database.
78
- - `Client` holds the client for the current scope: the base client, or the transaction client inside `transaction`. Resolve it here if your own code calls Prisma, and provide it to run code against a transaction you opened yourself.
79
- - `use(query)` runs `query` against the current client and records every successful write it made to a mapped model, in the calling fiber: into the enclosing transaction's frame, into a `channel.batch`, or published at once when there is neither, because the write autocommitted. It waits for Prisma's promise, which cannot be cancelled, so a write is recorded if and only if it ran. A rejection fails with `PrismaError`.
80
- - `transaction(body)` runs `body` inside `$transaction` on the current client. Inside another `transaction`, Prisma makes it a savepoint and its changes merge into the parent when it is released.
81
- - `recordWrite` applies the map to a write you observed yourself, for applications that already wrap Prisma in their own Effect client.
82
- - `models` maps each model name to the changes one row names, or to `null` for models whose writes publish nothing. `satisfies ChangeMap<PrismaClient, A>` makes a model added to the schema a type error until it is classified; a `Partial` map is accepted when you do not want that.
142
+ `recordWrite` maps this row just as the automatic path does, including multiple subjects and unnamed-write reporting. Keep the call in the binding transaction that owns the write.
143
+
144
+ ### Autocommitted writes and explicit batches
145
+
146
+ ```ts
147
+ const saveInvoices = Effect.gen(function* () {
148
+ yield* changes.use((db) => db.invoice.create({ data: { id: "i1", ownerId: "ada" } }));
149
+
150
+ yield* changes.channel.batch(
151
+ Effect.gen(function* () {
152
+ yield* changes.use((db) => db.invoice.update({ where: { id: "i1" }, data: { ownerId: "bob" } }));
153
+ yield* changes.use((db) => db.order.create({ data: { id: "o1", ownerId: "bob", total: 1 } }));
154
+ }),
155
+ );
156
+ });
157
+ ```
83
158
 
84
- ## Transactions
159
+ The first write publishes after autocommit. The explicit batch groups the two later writes into one publication. Use `transaction` for an action that needs a database transaction. The exposed `channel` is an [effect-changes channel](https://github.com/ShivaeDev/platform/tree/main/packages/effect-changes#readme); its sink and observer references are available for application wiring and tests.
85
160
 
86
- `transaction` opens a frame with `channel.open` in the caller's fiber, runs the body with `Effect.runPromiseExitWith` inside the `$transaction` callback, and settles the frame from the outcome of `$transaction`'s promise, not from the body:
161
+ ### Transaction failures, interruption and timeouts
87
162
 
88
- | Situation | Result |
163
+ | Situation | Binding result |
89
164
  | --- | --- |
90
- | `$transaction` cannot start, for example because no connection frees up within `maxWait` | The body never runs; fail with `PrismaError`, even though Prisma reports it as `P2028` |
91
- | The body succeeds and `$transaction` resolves | Publish once, before `transaction` returns; a savepoint merges into its parent |
92
- | The body fails, dies or is interrupted | Prisma rolls back; discard; the body's failure is returned unchanged |
93
- | The body is still running when the transaction's timeout passes | The body is interrupted at its next step; a query already in flight completes first. Prisma rolls back; discard; fail with `TransactionExpired` |
94
- | A query or a nested `transaction` in the body fails because the transaction is already closed | The body is stopped, whatever it does with the error; discard; fail with `TransactionExpired` |
95
- | The body succeeds but `COMMIT` finds the transaction closed | Discard; fail with `TransactionExpired` |
96
- | The body succeeds but `COMMIT` fails for another reason | Discard; fail with `PrismaError` |
97
- | The caller is interrupted while the body runs | The body is interrupted, Prisma rolls back, nothing publishes |
98
- | The caller is interrupted while `COMMIT` is in flight | Keep waiting; publish if the database committed; the caller still sees the interruption |
165
+ | The body succeeds and COMMIT succeeds | Return the body's value and publish its batch. |
166
+ | The body fails with a typed error | Roll back, publish nothing and retain that error. |
167
+ | COMMIT fails a deferred constraint | Publish nothing and fail with `PrismaError`. |
168
+ | The caller is interrupted during the body | Interrupt the body, roll back and publish nothing. |
169
+ | The caller is interrupted during an in-flight COMMIT that lands | Publish after commit; the caller still sees interruption. |
170
+ | The body reaches its transaction timeout | Interrupt it, roll back, publish nothing and fail with `TransactionExpired`. |
171
+ | A query or nested transaction finds its enclosing transaction closed | Stop the body with `TransactionExpired`, even if the body ignores the query's failure. |
172
+ | A transaction cannot start before `maxWait` | Fail with `PrismaError`; do not classify it as an expired running transaction. |
173
+
174
+ ```ts
175
+ const save = changes.transaction(
176
+ changes.use((db) => db.order.create({ data: { id: "o1", ownerId: "ada", total: 10 } })),
177
+ { timeout: 10_000, maxWait: 2_000 },
178
+ );
179
+ ```
99
180
 
100
- The timeout is the `timeout` option, otherwise the one Prisma applies to the current client, extended or not: its `transactionOptions.timeout`, 5 seconds unless the client was constructed with another. Like Prisma's, the clock starts once the transaction has begun, and it reads wall-clock time, so a `TestClock` does not move it. A `transaction` running on a transaction client, which Prisma makes a savepoint, has no timeout of its own; the outer transaction's applies. On any other client, such as a per-request extended client or the base client provided inside a body, `transaction` starts a separate transaction with its own timeout, and that transaction closing does not stop the body it runs in. Prisma reports a closed transaction as `P2028`, for example when a test harness's own transaction, which `transaction` does not time, has expired.
181
+ Pass transaction options as the second argument. Without `timeout`, the binding uses the current client's configured transaction timeout; the tested Prisma default is 5,000 milliseconds. The configuration reader also handles an extended client. If that configuration cannot be read, it supplies no deadline of its own; a query finding the transaction closed still stops the body.
101
182
 
102
- A frame is a root when there is no frame for the client further out, not when the current client is the base client. A test harness can therefore run each test inside a Prisma transaction that always rolls back, provide its transaction client as `Client` without opening a frame, and the application's first `transaction` inside it publishes when its savepoint is released.
183
+ The deadline follows the wall clock, so moving Effect's `TestClock` does not expire the transaction. An outer transaction's expiry interrupts a nested body too. A separate transaction started on the base client, or another binding's transaction, has independent expiry; handling its failure can leave the original body's transaction running.
103
184
 
104
- ## Recording
185
+ `use` waits for an in-flight successful write before recording it even when its caller is interrupted. The write may have committed, so interruption alone is not evidence that no change happened.
105
186
 
106
- - Row-returning writes (`create`, `update`, `upsert`, `delete`, `createManyAndReturn`, `updateManyAndReturn`) pass each returned row to the model's mapping. One row may name any number of changes, for example one per subject.
107
- - `createMany`, `updateMany` and `deleteMany` return only a count, so they cannot name their subjects. They record nothing and are reported to `Unnamed` as `countOnly`; the coverage check turns them into violations. Use a single-row or `*AndReturn` write on mapped models. Rows are never read back.
108
- - A mapping that reads a field the write did not return, because `select` or `omit` narrowed the result, records nothing for that write; it is reported to `Unnamed` as `narrowed` with the field's name.
109
- - Reads, raw queries and models mapped to `null` or absent from the map record nothing.
187
+ ### Once per test harness: check written tables
110
188
 
111
- ## Coverage check
189
+ The coverage check compares three things: tables PostgreSQL says the test wrote, changes the channel observed as `Recorded`, and writes that `Unnamed` could not name. The test supplies a `covers(model, change)` predicate because only the application knows whether a change represents that model.
112
190
 
113
- The check runs in tests. Take a baseline from `pg_stat_xact_user_tables` when the test transaction starts, read the tables written since just before it rolls back, then compare them with the changes the channel observed:
191
+ Take a counter baseline at the start of the test's own transaction. A pooled connection can still hold earlier transaction counters; `writtenTables(tx, since)` reports tables whose counts grew after that baseline.
114
192
 
115
193
  ```ts
194
+ import { readFile } from "node:fs/promises";
195
+ import { checkCoverage, type CoverageViolation } from "@shivaedev/effect-changes-prisma/coverage.ts";
196
+ import { tablesOf, tableWrites, writtenTables } from "@shivaedev/effect-changes-prisma/tables.ts";
197
+ import type { Observation } from "@shivaedev/effect-changes/observe.ts";
198
+
116
199
  const tables = tablesOf(await readFile("prisma/schema.prisma", "utf8"));
117
- const observations: Array<Observation<Change>> = [];
118
- const unnamed: Array<UnnamedWrite> = [];
119
- // first, as the test transaction starts:
120
- const since = yield* tableWrites(testTransaction);
121
- // run the test with changes.channel.Observer and changes.Unnamed pushing into those arrays,
122
- // and changes.Client set to the test's transaction client; then, before rolling back:
123
- const written = yield* writtenTables(testTransaction, since);
124
- const violations = checkCoverage({
125
- written,
126
- tables,
127
- models,
128
- observations,
129
- unnamed,
130
- covers: (model, change) => domains[model] === change.domain,
131
- });
200
+ const domains: Readonly<Record<string, string>> = {
201
+ Order: "orders",
202
+ Membership: "memberships",
203
+ Invoice: "invoices",
204
+ };
205
+
206
+ class TestRollback {
207
+ readonly violations: ReadonlyArray<CoverageViolation>;
208
+
209
+ constructor(violations: ReadonlyArray<CoverageViolation>) {
210
+ this.violations = violations;
211
+ }
212
+ }
213
+
214
+ const coverageOf = async <A, E>(body: Effect.Effect<A, E>) => {
215
+ const observations: Array<Observation<Change>> = [];
216
+ const unnamed: Array<UnnamedWrite> = [];
217
+
218
+ return prisma.$transaction(async (tx) => {
219
+ const since = await Effect.runPromise(tableWrites(tx));
220
+
221
+ await Effect.runPromise(
222
+ body.pipe(
223
+ Effect.provideService(changes.Client, tx),
224
+ Effect.provideService(changes.channel.Sink, () => Effect.void),
225
+ Effect.provideService(changes.channel.Observer, (observation) => Effect.sync(() => observations.push(observation))),
226
+ Effect.provideService(changes.Unnamed, (write) => Effect.sync(() => unnamed.push(write))),
227
+ ),
228
+ );
229
+
230
+ const written = await Effect.runPromise(writtenTables(tx, since));
231
+ throw new TestRollback(checkCoverage({
232
+ written,
233
+ tables,
234
+ models,
235
+ observations,
236
+ unnamed,
237
+ covers: (model, change) => domains[model] === change.domain,
238
+ }));
239
+ }).catch((error: unknown) => {
240
+ if (error instanceof TestRollback) {
241
+ return error.violations;
242
+ }
243
+ throw error;
244
+ });
245
+ };
246
+ ```
247
+
248
+ The harness provides its own transaction client and captures observations while the body runs. It replaces publication with a test sink, reads the counters before throwing `TestRollback`, and receives the coverage result after the database rolls back. Other failures are rethrown. In a test, assert that `await coverageOf(addMember("m1", "ada", "bob"))` equals `[]`.
249
+
250
+ A binding transaction inside this harness has no enclosing change frame until the application opens one. Its first savepoint frame is therefore a root and publishes on release, even though the harness later rolls back. The test sink prevents that publication from reaching the real bus.
251
+
252
+ `tablesOf` maps model declarations to table names, honoring `@@map("name")`, `@@map(name: "name")` and the model name when no mapping exists, while ignoring line comments. A caller can provide a table-to-model map directly instead.
253
+
254
+ `checkCoverage` returns:
255
+
256
+ - `Unrecorded` for each distinct written table without a covering `Recorded` change. A table with no model has `model: undefined`; a model classified as `null` is exempt.
257
+ - `Unnamed` for each distinct unnamed write, even when its table otherwise has a covering change.
258
+
259
+ `Recorded` changes still count if their savepoint later rolls back: PostgreSQL's counters include those writes. A `Published` observation alone does not establish coverage. Raw SQL writes without recorded changes are detected; read-only tables are not reported.
260
+
261
+ ### API and module imports
262
+
263
+ Import the module that defines the name. There is no root entry point.
264
+
265
+ | Module | Exports for application use |
266
+ | --- | --- |
267
+ | `changes.ts` | `makePrismaChanges`, `PrismaChanges`, `PrismaChangesOptions`, `UnnamedObserver` |
268
+ | `model.ts` | `ChangeMap`, `ModelChanges`, `ModelName`, `ModelRow`, `RowOperation`, `CountOperation`, `Transactional`, `TransactionOptions` |
269
+ | `write.ts` | `Write`, `UnnamedWrite` |
270
+ | `coverage.ts` | `Coverage`, `CoverageViolation`, `checkCoverage` |
271
+ | `tables.ts` | `RawQueryClient`, `TableWrites`, `tablesOf`, `tableWrites`, `writtenTables` |
272
+ | `error.ts` | `PrismaError`, `TransactionExpired` |
273
+
274
+ `PrismaChangesOptions` takes `client`, `models` and the effect-changes channel options other than `owner` and `unowned`: `name`, `key`, `publish` and `onPublishFailure`. The binding returns `Client`, `channel`, `use`, `transaction`, `recordWrite` and `Unnamed`.
275
+
276
+ ```ts
277
+ interface Write {
278
+ readonly model: string;
279
+ readonly operation: string;
280
+ readonly result: unknown;
281
+ }
282
+
283
+ type UnnamedWrite =
284
+ | { readonly model: string; readonly operation: string; readonly reason: "countOnly" }
285
+ | { readonly model: string; readonly operation: string; readonly reason: "narrowed"; readonly field: string };
286
+
287
+ type CoverageViolation =
288
+ | { readonly _tag: "Unrecorded"; readonly table: string; readonly model: string | undefined }
289
+ | { readonly _tag: "Unnamed"; readonly write: UnnamedWrite };
132
290
  ```
133
291
 
134
- - `tablesOf` reads the table of every model from Prisma schema text, honouring `@@map`; a model without it uses its name. Pass an explicit `Map` instead if your tables come from elsewhere.
135
- - `tableWrites(client)` and `writtenTables(client, since)` must run on the test's own transaction. PostgreSQL counts inserted, updated and deleted rows, including rows written in savepoints that rolled back, but it keeps those counters per connection until it flushes them, at most once a second. On a pooled connection they still hold the writes of earlier transactions, so `writtenTables` reports only the tables whose counters grew past the `since` baseline. Without `since` it reports every table with an unflushed count. The binding cannot take the baseline for you: the test transaction is the harness's own `$transaction`, which it never sees begin.
136
- - `checkCoverage` is a pure function and throws only if `covers` throws. It reports each written table whose model is not mapped to `null` and for which no `Recorded` observation satisfies `covers`, as `Unrecorded` (with `model: undefined` when no model owns the table), and each distinct unnamed write as `Unnamed`. `Recorded` includes changes whose frame was later discarded, matching the statistics.
137
- - Raw SQL, relation writes nested in `data`, cascades and triggers write tables that nothing records; the check is how they surface. Filter the result if a table is written legitimately without a change.
292
+ These are the write input and the two diagnostic results. `Coverage<A>` takes `written`, `tables`, `models`, `observations`, `unnamed` and `covers`, as shown in the harness. `TableWrites` is a `ReadonlyMap<string, bigint>`; `RawQueryClient` requires `$queryRawUnsafe(query)`.
293
+
294
+ `use` has error type `PrismaError`. `transaction` adds `TransactionExpired | PrismaError` to the body's error type. `PrismaError` carries `cause`; `TransactionExpired` carries `message` and optional `cause`. Transaction options are `maxWait`, `timeout` and `isolationLevel`, whose type is `"ReadUncommitted" | "ReadCommitted" | "RepeatableRead" | "Serializable"`.
295
+
296
+ The module export pattern also exposes `model.ts`'s `rowOperations`, `countOperations` and `delegateOf`; `write.ts`'s `interpret`, `Interpreted`, `LooseChanges` and `LooseMap`; and the helpers in [`recording.ts`](https://github.com/ShivaeDev/platform/blob/main/packages/effect-changes-prisma/src/recording.ts), [`expiry.ts`](https://github.com/ShivaeDev/platform/blob/main/packages/effect-changes-prisma/src/expiry.ts) and [`transaction.ts`](https://github.com/ShivaeDev/platform/blob/main/packages/effect-changes-prisma/src/transaction.ts). Application examples use the binding API above.
297
+
298
+ ### Install, setup and limits
299
+
300
+ ```sh
301
+ pnpm add @shivaedev/effect-changes-prisma @shivaedev/effect-changes @prisma/client@7.10.0 effect@4.0.4
302
+ ```
138
303
 
139
- ## Limits
304
+ `@prisma/client` and `effect` are peers. Generate and construct the application's Prisma Classic client for PostgreSQL before binding it. Package tests use the generated Prisma client and `@prisma/adapter-pg`; the PostgreSQL integration suite requires `PLATFORM_EFFECT_CHANGES_PRISMA_TEST_DATABASE_URL` and otherwise skips.
140
305
 
141
- - The client handed to `use` wraps write methods of mapped models, so their results are plain promises: pass them to `transaction`, not to the array form of `$transaction`, and do not chain fluent relation calls on them. Calling `$transaction` on that client runs outside the binding; use `transaction`.
142
- - A relation write nested in `data` records only the top-level model.
143
- - Prisma's interactive transaction timeout (5 seconds by default) still applies; pass `{ timeout }` to `transaction` for a longer one.
144
- - The client's timeout is read from Prisma's internal client configuration, which Prisma `7.10.0` keeps on the client. If a later Prisma moves it, `transaction` sets no deadline of its own, and a body that outlives Prisma's timeout stops at its first query after the transaction closes; pass `{ timeout }` to have it interrupted on time.
145
- - `checkCoverage` matches tables by name, not by schema.
146
- - `writtenTables` does not see a `TRUNCATE` inside the test transaction: `TRUNCATE` resets the transaction's insert, update and delete counts in `pg_stat_xact_user_tables`, so they fall back to the baseline, and a table that was written and then truncated counts as unwritten.
147
- - Delivery is in-process, as for every effect-changes channel.
306
+ - Use the binding's `transaction` for the transaction outcome it observes, and `use` for automatically recorded model writes.
307
+ - Return the fields the model mapping needs. The count-only and missing-field diagnostics are part of coverage, not a way to infer omitted subjects.
308
+ - Coverage is a table-level check: one matching recorded change covers a written model's table. Test the correctness of affected subjects separately.
309
+ - A test harness's native rollback transaction can contain root binding savepoints that publish before the harness rolls back. Capture publication in tests that must not call a real external sink.
148
310
 
149
- Tested with Prisma `7.10.0` and `@prisma/adapter-pg` on PostgreSQL 18, and Effect `4.0.0-rc.112`.
311
+ Read the [north star](https://github.com/ShivaeDev/platform/blob/main/packages/effect-changes-prisma/docs/north-star.md) for design boundaries and the [roadmap](https://github.com/ShivaeDev/platform/blob/main/packages/effect-changes-prisma/docs/roadmap.md) for status and open questions.
package/dist/changes.d.ts CHANGED
@@ -4,17 +4,17 @@ import { PrismaError, type TransactionExpired } from "./error.ts";
4
4
  import type { ChangeMap, Transactional, TransactionOptions } from "./model.ts";
5
5
  import { type UnnamedWrite, type Write } from "./write.ts";
6
6
  export type UnnamedObserver = (write: UnnamedWrite) => Effect.Effect<void>;
7
- export interface PrismaChangesOptions<Tx, A, R> extends Omit<ChannelOptions<A, R>, "owner" | "unowned"> {
8
- readonly client: Tx & Transactional<Tx>;
9
- readonly models: Partial<ChangeMap<Tx, A>>;
7
+ export interface PrismaChangesOptions<TTx, A, R> extends Omit<ChannelOptions<A, R>, "owner" | "unowned"> {
8
+ readonly client: TTx & Transactional<TTx>;
9
+ readonly models: Partial<ChangeMap<TTx, A>>;
10
10
  }
11
- export interface PrismaChanges<Tx, A, R> {
12
- readonly Client: Context.Reference<Tx>;
11
+ export interface PrismaChanges<TTx, A, R> {
12
+ readonly Client: Context.Reference<TTx>;
13
13
  readonly channel: Channel<A, R>;
14
14
  readonly recordWrite: (write: Write) => Effect.Effect<void, never, R>;
15
- readonly transaction: <X, E, R2>(body: Effect.Effect<X, E, R2>, options?: TransactionOptions) => Effect.Effect<X, E | TransactionExpired | PrismaError, R | R2>;
15
+ readonly transaction: <TX, E, TR2>(body: Effect.Effect<TX, E, TR2>, options?: TransactionOptions) => Effect.Effect<TX, E | TransactionExpired | PrismaError, R | TR2>;
16
16
  readonly Unnamed: Context.Reference<UnnamedObserver>;
17
- readonly use: <X>(query: (client: Tx) => PromiseLike<X>) => Effect.Effect<X, PrismaError, R>;
17
+ readonly use: <TX>(query: (client: TTx) => PromiseLike<TX>) => Effect.Effect<TX, PrismaError, R>;
18
18
  }
19
- export declare const makePrismaChanges: <Tx extends Transactional<Tx>, A, R = never>(options: PrismaChangesOptions<Tx, A, R>) => PrismaChanges<Tx, A, R>;
19
+ export declare const makePrismaChanges: <TTx extends Transactional<TTx>, A, R = never>(options: PrismaChangesOptions<TTx, A, R>) => PrismaChanges<TTx, A, R>;
20
20
  //# sourceMappingURL=changes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../src/changes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAE,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,cAAc,EAAe,MAAM,sCAAsC,CAAC;AACtG,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAG/E,OAAO,EAA4B,KAAK,YAAY,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAErF,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAE3E,MAAM,WAAW,oBAAoB,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAE,SAAQ,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACtG,QAAQ,CAAC,MAAM,EAAE,EAAE,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IACtC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACtE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAC9B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAC7B,OAAO,CAAC,EAAE,kBAAkB,KACxB,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,kBAAkB,GAAG,WAAW,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;IACpE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IACrD,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,EAAE,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;CAC7F;AAUD,eAAO,MAAM,iBAAiB,GAAI,EAAE,SAAS,aAAa,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,SAAS,oBAAoB,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,KAAG,aAAa,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CA8C7I,CAAC"}
1
+ {"version":3,"file":"changes.d.ts","sourceRoot":"","sources":["../src/changes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAE,MAAM,EAAgB,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,cAAc,EAAe,MAAM,sCAAsC,CAAC;AACtG,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAG/E,OAAO,EAA4B,KAAK,YAAY,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAErF,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAE3E,MAAM,WAAW,oBAAoB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAE,SAAQ,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvG,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;CAC5C;AAED,MAAM,WAAW,aAAa,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IACtE,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAChC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,EAC/B,OAAO,CAAC,EAAE,kBAAkB,KACxB,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,GAAG,kBAAkB,GAAG,WAAW,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;IACtE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IACrD,QAAQ,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,WAAW,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;CACjG;AAWD,eAAO,MAAM,iBAAiB,GAAI,GAAG,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,KAAK,WACpE,oBAAoB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,KACtC,aAAa,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CA8CzB,CAAC"}
package/dist/changes.js CHANGED
@@ -6,10 +6,12 @@ import { delegatesOf, recordingClient } from "./recording.js";
6
6
  import { runTransaction } from "./transaction.js";
7
7
  import { interpret } from "./write.js";
8
8
  const ignoreUnnamed = () => Effect.void;
9
- const expireOnClosed = (Expiry, exit) => Option.match(Exit.isFailure(exit) ? Cause.findErrorOption(exit.cause) : Option.none(), {
10
- onNone: () => Effect.void,
11
- onSome: ({ cause }) => (isTransactionClosed(cause) ? Effect.flatMap(Effect.service(Expiry), (expire) => expire(cause)) : Effect.void),
12
- });
9
+ function expireOnClosed(Expiry, exit) {
10
+ return Option.match(Exit.isFailure(exit) ? Cause.findErrorOption(exit.cause) : Option.none(), {
11
+ onNone: () => Effect.void,
12
+ onSome: ({ cause }) => (isTransactionClosed(cause) ? Effect.flatMap(Effect.service(Expiry), (expire) => expire(cause)) : Effect.void),
13
+ });
14
+ }
13
15
  export const makePrismaChanges = (options) => {
14
16
  const { client, models: typed, ...channelOptions } = options;
15
17
  const models = typed;
@@ -1 +1 @@
1
- {"version":3,"file":"changes.js","sourceRoot":"","sources":["../src/changes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"changes.js","sourceRoot":"","sources":["../src/changes.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,iBAAiB,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAC3F;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAA;CAAE,CAAC;AAE9D,MAAM,WAAW,QAAQ,CAAC,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;IACvD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACnC;AAQD,eAAO,MAAM,aAAa,GAAI,CAAC,EAAE,UAAU,QAAQ,CAAC,CAAC,CAAC,KAAG,SAAS,iBAAiB,EAclF,CAAC"}
1
+ {"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,iBAAiB,GAC1B;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GAC3F;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAA;CAAE,CAAC;AAE9D,MAAM,WAAW,QAAQ,CAAC,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC;IACvD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CACnC;AAUD,eAAO,MAAM,aAAa,GAAI,CAAC,YAAY,QAAQ,CAAC,CAAC,CAAC,KAAG,SAAS,iBAAiB,EAclF,CAAC"}
package/dist/coverage.js CHANGED
@@ -1,5 +1,9 @@
1
- const recordedIn = (observations) => [...observations].flatMap((observation) => (observation._tag === "Recorded" ? observation.changes : []));
2
- const identify = (write) => write.reason === "narrowed" ? `${write.model}.${write.operation}.${write.field}` : `${write.model}.${write.operation}`;
1
+ function recordedIn(observations) {
2
+ return [...observations].flatMap((observation) => (observation._tag === "Recorded" ? observation.changes : []));
3
+ }
4
+ function identify(write) {
5
+ return write.reason === "narrowed" ? `${write.model}.${write.operation}.${write.field}` : `${write.model}.${write.operation}`;
6
+ }
3
7
  export const checkCoverage = (coverage) => {
4
8
  const recorded = recordedIn(coverage.observations);
5
9
  const unrecorded = [...new Set(coverage.written)].flatMap((table) => {
@@ -1 +1 @@
1
- {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,GAAG,CAAI,YAAsC,EAAgB,EAAE,CAC9E,CAAC,GAAG,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAE1G,MAAM,QAAQ,GAAG,CAAC,KAAmB,EAAU,EAAE,CAChD,KAAK,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;AAExH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAI,QAAqB,EAAgC,EAAE;IACvF,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAgC,EAAE;QACjG,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;YAC5D,OAAO,EAAE,CAAC;QACX,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;YACtF,OAAO,EAAE,CAAC;QACX,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC;IACjG,OAAO,CAAC,GAAG,UAAU,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAqB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AAClH,CAAC,CAAC"}
1
+ {"version":3,"file":"coverage.js","sourceRoot":"","sources":["../src/coverage.ts"],"names":[],"mappings":"AAgBA,SAAS,UAAU,CAAI,YAAsC;IAC5D,OAAO,CAAC,GAAG,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACjH,CAAC;AAED,SAAS,QAAQ,CAAC,KAAmB;IACpC,OAAO,KAAK,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;AAC/H,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAI,QAAqB,EAAgC,EAAE;IACvF,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACnD,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAgC,EAAE;QACjG,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;YAC5D,OAAO,EAAE,CAAC;QACX,CAAC;QACD,IAAI,KAAK,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;YACtF,OAAO,EAAE,CAAC;QACX,CAAC;QACD,OAAO,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAU,CAAC,CAAC,CAAC;IACjG,OAAO,CAAC,GAAG,UAAU,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAqB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AAClH,CAAC,CAAC"}
package/dist/expiry.d.ts CHANGED
@@ -6,5 +6,5 @@ export declare const makeExpiry: (key: string) => Context.Reference<Expire>;
6
6
  export declare const isTransactionClient: (client: object) => boolean;
7
7
  export declare const isTransactionClosed: (cause: unknown) => boolean;
8
8
  export declare const configuredTimeout: (client: object) => number | undefined;
9
- export declare const expiring: <X, E, R>(body: Effect.Effect<X, E, R>, timeout: number | undefined, Expiry: Context.Reference<Expire>) => Effect.Effect<X, E | TransactionExpired, R>;
9
+ export declare const expiring: <TX, E, R>(body: Effect.Effect<TX, E, R>, timeout: number | undefined, Expiry: Context.Reference<Expire>) => Effect.Effect<TX, E | TransactionExpired, R>;
10
10
  //# sourceMappingURL=expiry.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"expiry.d.ts","sourceRoot":"","sources":["../src/expiry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAY,MAAM,EAA6B,MAAM,QAAQ,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAE7D,eAAO,MAAM,QAAQ,EAAE,MAA0B,CAAC;AAElD,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,8BAAqE,CAAC;AAE5G,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM,KAAG,OAAqD,CAAC;AAE3G,eAAO,MAAM,mBAAmB,GAAI,OAAO,OAAO,KAAG,OAAyE,CAAC;AAM/H,eAAO,MAAM,iBAAiB,GAAI,QAAQ,MAAM,KAAG,MAAM,GAAG,SAG/C,CAAC;AAId,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/B,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAC5B,SAAS,MAAM,GAAG,SAAS,EAC3B,QAAQ,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,KAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,kBAAkB,EAAE,CAAC,CAoB1C,CAAC"}
1
+ {"version":3,"file":"expiry.d.ts","sourceRoot":"","sources":["../src/expiry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,OAAO,EAAY,MAAM,EAA6B,MAAM,QAAQ,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAE7D,eAAO,MAAM,QAAQ,EAAE,MAA0B,CAAC;AAElD,eAAO,MAAM,UAAU,QAAS,MAAM,8BAAqE,CAAC;AAE5G,eAAO,MAAM,mBAAmB,WAAY,MAAM,KAAG,OAAqD,CAAC;AAE3G,eAAO,MAAM,mBAAmB,UAAW,OAAO,KAAG,OAAyE,CAAC;AAM/H,eAAO,MAAM,iBAAiB,WAAY,MAAM,KAAG,MAAM,GAAG,SAG/C,CAAC;AAId,eAAO,MAAM,QAAQ,GAAI,EAAE,EAAE,CAAC,EAAE,CAAC,QAC1B,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,WACpB,MAAM,GAAG,SAAS,UACnB,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,KAC/B,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,GAAG,kBAAkB,EAAE,CAAC,CAoB3C,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"expiry.js","sourceRoot":"","sources":["../src/expiry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"expiry.js","sourceRoot":"","sources":["../src/expiry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIhD,MAAM,CAAC,MAAM,QAAQ,GAAW,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;AAElD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,SAAS,CAAS,GAAG,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;AAE5G,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAc,EAAW,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAE3G,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAc,EAAW,EAAE,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;AAE/H,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,kBAAkB,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;AAEtG,MAAM,kBAAkB,GAAG,MAAM,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,MAAc,EAAsB,EAAE,CACvE,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC;IAC7C,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5H,CAAC,CAAC,SAAS,CAAC;AAEd,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC;AAE7C,MAAM,CAAC,MAAM,QAAQ,GAAG,CACvB,IAA6B,EAC7B,OAA2B,EAC3B,MAAiC,EACc,EAAE,CACjD,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACnB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC;IAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,EAA6B,CAAC;IAClE,MAAM,MAAM,GAAW,CAAC,KAAK,EAAE,EAAE,CAChC,MAAM,CAAC,OAAO,CACb,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,kBAAkB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,qDAAqD,EAAE,CAAC,CAAC,EACzH,KAAK,CAAC,KAAK,CAAC,CACZ,CAAC;IACH,MAAM,QAAQ,GACb,OAAO,KAAK,SAAS;QACpB,CAAC,CAAC,MAAM,CAAC,KAAK;QACd,CAAC,CAAC,MAAM,CAAC,OAAO,CACd,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,EACpE,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,kBAAkB,CAAC,EAAE,OAAO,EAAE,qCAAqC,OAAO,aAAa,EAAE,CAAC,CAAC,CACtH,CAAC;IACL,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3G,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CACtF,MAAM,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAC5I,CAAC;AACH,CAAC,CAAC,CAAC"}