@nestjs-transactional/core 1.0.0-alpha.3 → 1.0.0

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/README.md CHANGED
@@ -1,265 +1,204 @@
1
1
  # @nestjs-transactional/core
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/%40nestjs-transactional%2Fcore/alpha?style=flat-square&label=npm)](https://www.npmjs.com/package/@nestjs-transactional/core)
3
+ [![npm version](https://img.shields.io/npm/v/%40nestjs-transactional%2Fcore?style=flat-square&label=npm)](https://www.npmjs.com/package/@nestjs-transactional/core)
4
4
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/igorgolovanov/nestjs-transactional/blob/main/LICENSE)
5
5
 
6
- Core primitives for declarative Spring-style transaction management
7
- in NestJS.
8
-
9
- ## Overview
10
-
11
- The adapter-agnostic foundation of the `@nestjs-transactional` family:
12
-
13
- - `TransactionContext` `AsyncLocalStorage`-backed carrier that
14
- propagates the active transaction across `await` boundaries.
15
- - `TransactionManager` — runtime with the full Spring propagation
16
- semantics (`REQUIRED`, `REQUIRES_NEW`, `NESTED`, `SUPPORTS`,
17
- `NOT_SUPPORTED`, `NEVER`, `MANDATORY`) plus `rollbackFor` /
18
- `noRollbackFor` rules and before / after commit / rollback hooks.
19
- - `@Transactional()`, `@ReadOnly()`, `@TransactionalOn(instance)`
20
- decorators — metadata-only; runtime wrapping is performed by the
21
- three coordinated mechanisms documented in
22
- [ADR-005](../../docs/adr/005-method-wrapping-strategy.md).
23
- - `TransactionalInterceptor` — wires `@Transactional` on controllers,
24
- resolvers, gateways, and microservice handlers via `APP_INTERCEPTOR`.
25
- - `TransactionalModule.forRoot` / `forRootAsync` — module wiring,
26
- one call per dataSource (multi-`forRoot` pattern, see
27
- [ADR-019](../../docs/adr/019-outbox-multi-forroot-pattern.md)).
28
- - `TransactionAdapter<THandle>` SPI — the port for ORM-specific
29
- adapters.
30
- - `InMemoryTransactionAdapter` (via the `@nestjs-transactional/core/testing`
31
- subpath) — drop-in adapter for unit tests.
32
-
33
- This package does not depend on any concrete ORM. Install
34
- `@nestjs-transactional/typeorm` for TypeORM integration, or implement
35
- your own adapter against the `TransactionAdapter` interface.
36
-
37
- ## Installation
6
+ Declarative transactions for NestJS, with Spring's semantics.
7
+
8
+ Put `@Transactional()` on a method and everything it touches runs in
9
+ one transaction — across `await` boundaries, without threading a
10
+ manager through your call stack. All seven Spring propagation modes are
11
+ implemented, including `NESTED` via savepoints.
12
+
13
+ This package is ORM-agnostic and does nothing on its own: it needs an
14
+ adapter. Most applications install
15
+ [`@nestjs-transactional/typeorm`](https://www.npmjs.com/package/@nestjs-transactional/typeorm)
16
+ alongside it, which also makes injected repositories transaction-aware
17
+ automatically. For event delivery that survives a crash, add
18
+ [`@nestjs-transactional/outbox`](https://www.npmjs.com/package/@nestjs-transactional/outbox);
19
+ for `@nestjs/cqrs` handlers,
20
+ [`@nestjs-transactional/cqrs`](https://www.npmjs.com/package/@nestjs-transactional/cqrs).
21
+
22
+ ## Install
38
23
 
39
24
  ```bash
40
- pnpm add @nestjs-transactional/core reflect-metadata
25
+ pnpm add @nestjs-transactional/core @nestjs-transactional/typeorm reflect-metadata
41
26
  ```
42
27
 
43
- Load `reflect-metadata` once at the application entry point (same as
44
- for NestJS itself).
28
+ Load `reflect-metadata` once at your entry point, as NestJS itself
29
+ requires.
45
30
 
46
31
  ## Quick start
47
32
 
48
- In typical use this package is imported via an integration package
49
- (like `@nestjs-transactional/typeorm`) which registers the adapter
50
- into the `AdapterRegistry` automatically. The minimal application
51
- shape is:
52
-
53
33
  ```ts
54
34
  import { Module } from '@nestjs/common';
55
35
  import { TransactionalModule } from '@nestjs-transactional/core';
56
36
  import { TypeOrmTransactionalModule } from '@nestjs-transactional/typeorm';
57
- // ...your TypeORM config
58
37
 
59
38
  @Module({
60
39
  imports: [
61
- TypeOrmModule.forRoot({ /* ... */ }),
40
+ TypeOrmModule.forRoot({
41
+ /* ... */
42
+ }),
62
43
 
63
- // Infrastructure-only forRoot registers TransactionManager,
64
- // AdapterRegistry, and the interceptor. No `adapter` here; the
65
- // integration package below registers it.
44
+ // Infrastructure only: TransactionManager, AdapterRegistry, the
45
+ // interceptor. `isGlobal` matters the adapter package below
46
+ // needs to see the registry from its own DI scope.
66
47
  TransactionalModule.forRoot({ isGlobal: true }),
67
48
 
68
- // Integration package registers `TypeOrmTransactionAdapter`
69
- // for the default dataSource.
49
+ // Registers the TypeORM adapter for the default dataSource.
70
50
  TypeOrmTransactionalModule.forRoot(),
71
51
  ],
72
52
  })
73
53
  export class AppModule {}
74
54
  ```
75
55
 
76
- `@Transactional()` on any controller handler, query handler, or
77
- service method is then wrapped in a transaction automatically:
56
+ That is the whole setup. Now any method a controller handler, a
57
+ service method, a CQRS handler becomes transactional by decoration:
78
58
 
79
59
  ```ts
80
- import { Controller, Get, Param } from '@nestjs/common';
60
+ import { Injectable } from '@nestjs/common';
81
61
  import { Transactional } from '@nestjs-transactional/core';
82
62
 
83
- @Controller('orders')
84
- export class OrdersController {
85
- constructor(private readonly orders: OrdersService) {}
86
-
87
- @Get(':id')
63
+ @Injectable()
64
+ export class OrdersService {
88
65
  @Transactional()
89
- async findOne(@Param('id') id: string) {
90
- return this.orders.findById(id);
66
+ async placeOrder(dto: PlaceOrderDto): Promise<Order> {
67
+ const order = await this.orders.save(dto);
68
+ await this.stock.reserve(order); // same transaction
69
+ return order; // commits here; a throw rolls both back
91
70
  }
92
71
  }
93
72
  ```
94
73
 
95
- ### Direct adapter registration (custom backends)
74
+ ## Propagation
96
75
 
97
- When implementing a new `TransactionAdapter` (Prisma, Mongoose, ...),
98
- pass it to `forRoot` directly:
76
+ `@Transactional({ propagation })` decides what happens when a
77
+ transactional method is called from inside another one. The default,
78
+ `REQUIRED`, joins the caller — which is what you want almost always.
99
79
 
100
- ```ts
101
- import { TransactionalModule, type TransactionAdapter } from '@nestjs-transactional/core';
102
-
103
- const myAdapter: TransactionAdapter = /* ... */;
104
-
105
- @Module({
106
- imports: [
107
- TransactionalModule.forRoot({
108
- isGlobal: true,
109
- adapter: myAdapter,
110
- }),
111
- ],
112
- })
113
- export class AppModule {}
114
- ```
115
-
116
- For multi-dataSource setups, call `forRoot` once per dataSource —
117
- each call registers exactly one adapter under its dataSource name.
118
-
119
- ## Decorator options
80
+ | Mode | Caller has a transaction | Caller has none |
81
+ | --- | --- | --- |
82
+ | `REQUIRED` *(default)* | join it | start one |
83
+ | `REQUIRES_NEW` | suspend it, run independently, resume | start one |
84
+ | `NESTED` | run in a savepoint | start one |
85
+ | `SUPPORTS` | join it | run without a transaction |
86
+ | `NOT_SUPPORTED` | suspend it, run without one, resume | run without one |
87
+ | `NEVER` | throw `IllegalTransactionStateError` | run without one |
88
+ | `MANDATORY` | join it | throw `IllegalTransactionStateError` |
89
+
90
+ `REQUIRES_NEW` is how you make a side effect survive the caller's
91
+ rollback — an audit row that must persist even when the operation
92
+ fails. `NESTED` gives you a partial rollback inside one transaction;
93
+ it needs a driver with savepoint support, and the TypeORM adapter
94
+ raises a clear error rather than silently degrading if the driver has
95
+ none.
96
+
97
+ ## Options
120
98
 
121
99
  ```ts
122
- import {
123
- Transactional,
124
- ReadOnly,
125
- TransactionalOn,
126
- PropagationMode,
127
- } from '@nestjs-transactional/core';
128
-
129
100
  class ReportsService {
130
- // Explicit propagation + isolation.
131
101
  @Transactional({
132
102
  propagation: PropagationMode.REQUIRES_NEW,
133
103
  isolation: 'SERIALIZABLE',
134
- timeout: 10_000,
135
104
  })
136
- async rebuildReport() { /* ... */ }
105
+ async rebuild() {}
106
+
107
+ // Roll back on anything except ValidationError.
108
+ @Transactional({ noRollbackFor: [ValidationError] })
109
+ async processBatch() {}
137
110
 
138
111
  // Shorthand for { readOnly: true }.
139
112
  @ReadOnly()
140
- async exportCsv() { /* ... */ }
141
-
142
- // Rollback rules — commit on `ValidationError`, roll back on others.
143
- @Transactional({ noRollbackFor: [ValidationError] })
144
- async processBatch() { /* ... */ }
113
+ async exportCsv() {}
145
114
 
146
- // Target a specific dataSource in multi-DataSource setups.
115
+ // Target one dataSource in a multi-dataSource application.
147
116
  @TransactionalOn('billing')
148
- async chargeCard() { /* ... */ }
117
+ async chargeCard() {}
149
118
  }
150
119
  ```
151
120
 
152
- Propagation semantics:
121
+ Two options carry caveats worth knowing before you rely on them:
153
122
 
154
- | Mode | Active outer transaction | No outer transaction |
155
- | --- | --- | --- |
156
- | `REQUIRED` (default) | join | start new |
157
- | `REQUIRES_NEW` | suspend + start new, then resume | start new |
158
- | `NESTED` | run inside a savepoint | start new |
159
- | `SUPPORTS` | join | run without transaction |
160
- | `NOT_SUPPORTED` | suspend + run without transaction, then resume | run without transaction |
161
- | `NEVER` | throw `IllegalTransactionStateError` | run without transaction |
162
- | `MANDATORY` | join | throw `IllegalTransactionStateError` |
163
-
164
- ## Async module configuration
165
-
166
- ```ts
167
- import { TransactionalModule } from '@nestjs-transactional/core';
168
-
169
- @Module({
170
- imports: [
171
- TransactionalModule.forRootAsync({
172
- imports: [ConfigModule],
173
- inject: [ConfigService],
174
- useFactory: (config: ConfigService) => ({
175
- adapter: buildAdapterFromConfig(config),
176
- }),
177
- }),
178
- ],
179
- })
180
- export class AppModule {}
181
- ```
182
-
183
- `isGlobal` and `registerInterceptor` remain static top-level flags —
184
- they must be known at module definition time. The async factory
185
- returns the per-call configuration (`adapter` and any other
186
- runtime-resolved options).
123
+ - **`readOnly`** is enforced by the database only on Postgres-family
124
+ dialects, where the adapter issues `SET TRANSACTION READ ONLY`.
125
+ Elsewhere it documents intent and nothing rejects a write. Spring
126
+ treats it as a hint too. See
127
+ [DD-027](https://github.com/igorgolovanov/nestjs-transactional/blob/main/docs/dd/027-readonly-and-timeout-semantics.md).
128
+ - **`timeout`** is accepted by the type but **not implemented** by the
129
+ TypeORM adapter. It is deliberately not approximated: Postgres'
130
+ `statement_timeout` bounds each statement rather than the
131
+ transaction, so `timeout: 5000` on a method issuing four queries
132
+ would allow twenty seconds. It stays in the surface for adapters
133
+ whose driver exposes a real transaction budget.
187
134
 
188
- ## Lifecycle hooks
135
+ ## Commit and rollback hooks
189
136
 
190
- Register hooks from inside a transactional method they fire on the
191
- current transaction:
137
+ Register from inside a transactional method; the hook binds to the
138
+ transaction currently running.
192
139
 
193
140
  ```ts
194
- import { TransactionManager } from '@nestjs-transactional/core';
195
-
196
- export class OrdersService {
197
- constructor(private readonly manager: TransactionManager) {}
198
-
199
- @Transactional()
200
- async placeOrder(payload: PlaceOrderDto) {
201
- const order = await this.orders.insert(payload);
141
+ @Transactional()
142
+ async placeOrder(dto: PlaceOrderDto) {
143
+ const order = await this.orders.save(dto);
202
144
 
203
- this.manager.registerAfterCommit(async () => {
204
- // Fires only after the adapter commits. Never on rollback.
205
- await this.analytics.trackOrderPlaced(order.id);
206
- });
145
+ // Runs only after the commit succeeds — never on rollback.
146
+ this.manager.registerAfterCommit(() => this.analytics.track(order.id));
207
147
 
208
- this.manager.registerAfterRollback(async (error) => {
209
- // Receives the error that caused the rollback.
210
- await this.metrics.recordFailedOrder(order.id, error);
211
- });
148
+ // Receives the error that caused the rollback.
149
+ this.manager.registerAfterRollback((error) => this.metrics.failed(error));
212
150
 
213
- return order;
214
- }
151
+ return order;
215
152
  }
216
153
  ```
217
154
 
218
- Hook errors are caught and logged via NestJS `Logger` they do not
219
- affect the transaction outcome or prevent sibling hooks from running.
155
+ A throwing hook is logged and swallowed: it changes neither the
156
+ transaction's outcome nor its sibling hooks. For event handlers with
157
+ these semantics as first-class decorators, see the `cqrs` package.
220
158
 
221
159
  ## Testing
222
160
 
223
- `InMemoryTransactionAdapter` from the `/testing` subpath gives
224
- adapter-level observability without a real database:
161
+ `InMemoryTransactionAdapter` from the `/testing` subpath records
162
+ commits, rollbacks and savepoints without a database:
225
163
 
226
164
  ```ts
227
165
  import { InMemoryTransactionAdapter } from '@nestjs-transactional/core/testing';
228
- import { TransactionalModule } from '@nestjs-transactional/core';
229
166
 
230
167
  const adapter = new InMemoryTransactionAdapter();
231
168
 
232
- const moduleRef = await Test.createTestingModule({
233
- imports: [
234
- TransactionalModule.forRoot({ isGlobal: true, adapter }),
235
- ],
169
+ await Test.createTestingModule({
170
+ imports: [TransactionalModule.forRoot({ isGlobal: true, adapter })],
236
171
  }).compile();
237
172
 
238
- // After exercising the code under test:
239
173
  expect(adapter.committedTransactions).toHaveLength(1);
240
174
  expect(adapter.rolledBackTransactions).toHaveLength(0);
241
- expect(adapter.savepointsReleased).toHaveLength(0);
242
175
  ```
243
176
 
244
- `adapter.reset()` clears all observation arrays between tests when
245
- you keep a single adapter instance across cases. For multi-DS test
246
- setups, pass distinct dataSource names to the constructor:
177
+ `adapter.reset()` clears the arrays between cases. Pass a dataSource
178
+ name to the constructor for multi-dataSource tests.
179
+
180
+ ## Custom adapters
181
+
182
+ To support another ORM, implement `TransactionAdapter<THandle>` and
183
+ hand it to `forRoot` directly:
247
184
 
248
185
  ```ts
249
- const billing = new InMemoryTransactionAdapter('billing');
250
- const inventory = new InMemoryTransactionAdapter('inventory');
186
+ TransactionalModule.forRoot({ isGlobal: true, adapter: myAdapter });
251
187
  ```
252
188
 
253
- ## Worked examples
189
+ One `forRoot` call registers one adapter. Multi-dataSource
190
+ applications call it once per dataSource.
254
191
 
255
- - [`basic-transactional`](../../examples/basic-transactional) —
256
- `@Transactional()` on a plain service.
257
- - [`testing-patterns`](../../examples/testing-patterns) —
258
- `InMemoryTransactionAdapter` from `core/testing` plus the outbox /
259
- integration test layers.
192
+ ## Documentation
260
193
 
261
- Full catalogue: [examples/README.md](../../examples/README.md).
194
+ - [Getting started and full docs](https://github.com/igorgolovanov/nestjs-transactional#readme)
195
+ - [Architecture: core design](https://github.com/igorgolovanov/nestjs-transactional/blob/main/docs/architecture/core-design.md)
196
+ - [How methods get wrapped (ADR-005)](https://github.com/igorgolovanov/nestjs-transactional/blob/main/docs/adr/005-method-wrapping-strategy.md)
197
+ - [Known limitations](https://github.com/igorgolovanov/nestjs-transactional/blob/main/docs/known-limitations.md)
198
+ - Runnable examples:
199
+ [`basic-transactional`](https://github.com/igorgolovanov/nestjs-transactional/tree/main/examples/basic-transactional),
200
+ [`testing-patterns`](https://github.com/igorgolovanov/nestjs-transactional/tree/main/examples/testing-patterns)
262
201
 
263
- ## Status
202
+ ## License
264
203
 
265
- Alpha. Public API may change between 0.x releases.
204
+ MIT
@@ -1 +1 @@
1
- {"version":3,"file":"transaction-context-view.js","sourceRoot":"","sources":["../../src/context/transaction-context-view.ts"],"names":[],"mappings":";;;AAAA,+DAG+B;AAE/B;;;;;;;;;;;;;;;GAeG;AACH,MAAa,sBAAsB;IAKZ;IAJrB;;;OAGG;IACH,YAAqB,UAAkB;QAAlB,eAAU,GAAV,UAAU,CAAQ;IAAG,CAAC;IAE3C;;;;OAIG;IACH,oBAAoB;QAClB,OAAO,wCAAkB,CAAC,gCAAgC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9E,CAAC;IAED;;;;OAIG;IACH,oBAAoB;QAClB,OAAO,IAAI,CAAC,oBAAoB,EAAE,KAAK,SAAS,CAAC;IACnD,CAAC;CACF;AAxBD,wDAwBC"}
1
+ {"version":3,"file":"transaction-context-view.js","sourceRoot":"","sources":["../../src/context/transaction-context-view.ts"],"names":[],"mappings":";;;AAAA,+DAAmF;AAEnF;;;;;;;;;;;;;;;GAeG;AACH,MAAa,sBAAsB;IAKZ;IAJrB;;;OAGG;IACH,YAAqB,UAAkB;QAAlB,eAAU,GAAV,UAAU,CAAQ;IAAG,CAAC;IAE3C;;;;OAIG;IACH,oBAAoB;QAClB,OAAO,wCAAkB,CAAC,gCAAgC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9E,CAAC;IAED;;;;OAIG;IACH,oBAAoB;QAClB,OAAO,IAAI,CAAC,oBAAoB,EAAE,KAAK,SAAS,CAAC;IACnD,CAAC;CACF;AAxBD,wDAwBC"}
@@ -55,7 +55,7 @@ export interface TransactionContextStore {
55
55
  *
56
56
  * **Public dataSource-name access**:
57
57
  * {@link getActiveTransactionByDataSource} provides dataSource-name
58
- * lookup for Phase 14.2+ multi-adapter consumers — it scans the Map
58
+ * lookup for multi-adapter consumers — it scans the Map
59
59
  * for the entry whose `adapterInstanceName === dataSource`. Both
60
60
  * access patterns coexist; future cleanup is possible once
61
61
  * cross-package consumers migrate to the dataSource-name lookup and
@@ -19,7 +19,7 @@ const als = new node_async_hooks_1.AsyncLocalStorage();
19
19
  *
20
20
  * **Public dataSource-name access**:
21
21
  * {@link getActiveTransactionByDataSource} provides dataSource-name
22
- * lookup for Phase 14.2+ multi-adapter consumers — it scans the Map
22
+ * lookup for multi-adapter consumers — it scans the Map
23
23
  * for the entry whose `adapterInstanceName === dataSource`. Both
24
24
  * access patterns coexist; future cleanup is possible once
25
25
  * cross-package consumers migrate to the dataSource-name lookup and
@@ -1 +1 @@
1
- {"version":3,"file":"transaction.context.js","sourceRoot":"","sources":["../../src/context/transaction.context.ts"],"names":[],"mappings":";;;AAAA,uDAAqD;AAErD,4CAA+D;AAwD/D,MAAM,GAAG,GAAG,IAAI,oCAAiB,EAA2B,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,kBAAkB;IAC7B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,GAAG,CAAI,aAAqB,EAAE,EAAoB;QACvD,IAAI,GAAG,CAAC,QAAQ,EAAE,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAA4B;YACrC,kBAAkB,EAAE,IAAI,GAAG,EAA6B;YACxD,aAAa;YACb,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;QACF,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,iFAAiF;IACjF,MAAM,CAAC,QAAQ;QACb,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAED,4FAA4F;IAC5F,MAAM,CAAC,oBAAoB,CAAC,mBAA2B;QACrD,OAAO,GAAG,CAAC,QAAQ,EAAE,EAAE,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,gCAAgC,CACrC,UAAkB;QAElB,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;YACnD,IAAI,EAAE,CAAC,mBAAmB,KAAK,UAAU,EAAE,CAAC;gBAC1C,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,oBAAoB,CAAC,mBAA2B,EAAE,EAAqB;QAC5E,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,qCAA4B,CACpC,mEAAmE,CACpE,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACxD,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,uBAAuB,CAAC,mBAA2B;QACxD,GAAG,CAAC,QAAQ,EAAE,EAAE,kBAAkB,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACjE,CAAC;CACF;AA3FD,gDA2FC"}
1
+ {"version":3,"file":"transaction.context.js","sourceRoot":"","sources":["../../src/context/transaction.context.ts"],"names":[],"mappings":";;;AAAA,uDAAqD;AAErD,4CAA+D;AAwD/D,MAAM,GAAG,GAAG,IAAI,oCAAiB,EAA2B,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAa,kBAAkB;IAC7B;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,GAAG,CAAI,aAAqB,EAAE,EAAoB;QACvD,IAAI,GAAG,CAAC,QAAQ,EAAE,KAAK,SAAS,EAAE,CAAC;YACjC,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;QACD,MAAM,KAAK,GAA4B;YACrC,kBAAkB,EAAE,IAAI,GAAG,EAA6B;YACxD,aAAa;YACb,SAAS,EAAE,IAAI,IAAI,EAAE;SACtB,CAAC;QACF,OAAO,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,iFAAiF;IACjF,MAAM,CAAC,QAAQ;QACb,OAAO,GAAG,CAAC,QAAQ,EAAE,CAAC;IACxB,CAAC;IAED,4FAA4F;IAC5F,MAAM,CAAC,oBAAoB,CAAC,mBAA2B;QACrD,OAAO,GAAG,CAAC,QAAQ,EAAE,EAAE,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IACrE,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,gCAAgC,CAAC,UAAkB;QACxD,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,KAAK,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;YACnD,IAAI,EAAE,CAAC,mBAAmB,KAAK,UAAU,EAAE,CAAC;gBAC1C,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,oBAAoB,CAAC,mBAA2B,EAAE,EAAqB;QAC5E,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,IAAI,qCAA4B,CACpC,mEAAmE,CACpE,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACxD,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,uBAAuB,CAAC,mBAA2B;QACxD,GAAG,CAAC,QAAQ,EAAE,EAAE,kBAAkB,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACjE,CAAC;CACF;AAzFD,gDAyFC"}
@@ -38,6 +38,11 @@ export declare function Transactional(options?: Partial<TransactionalMetadata>):
38
38
  * must not mutate state. Options are applied first and the `readOnly: true`
39
39
  * flag is overlaid on top, so callers cannot turn it off from here — use
40
40
  * `@Transactional` directly if that is the intent.
41
+ *
42
+ * Enforcement is per-dialect (DD-027). On Postgres-family databases
43
+ * `TypeOrmTransactionAdapter` issues `SET TRANSACTION READ ONLY`, so a
44
+ * stray write fails at the database. Elsewhere — MySQL, SQLite, ... —
45
+ * the flag documents intent but nothing stops the write.
41
46
  */
42
47
  export declare const ReadOnly: (options?: Partial<TransactionalMetadata>) => MethodDecorator & ClassDecorator;
43
48
  /**
@@ -51,6 +51,11 @@ function Transactional(options = {}) {
51
51
  * must not mutate state. Options are applied first and the `readOnly: true`
52
52
  * flag is overlaid on top, so callers cannot turn it off from here — use
53
53
  * `@Transactional` directly if that is the intent.
54
+ *
55
+ * Enforcement is per-dialect (DD-027). On Postgres-family databases
56
+ * `TypeOrmTransactionAdapter` issues `SET TRANSACTION READ ONLY`, so a
57
+ * stray write fails at the database. Elsewhere — MySQL, SQLite, ... —
58
+ * the flag documents intent but nothing stops the write.
54
59
  */
55
60
  const ReadOnly = (options = {}) => Transactional({ ...options, readOnly: true });
56
61
  exports.ReadOnly = ReadOnly;
@@ -1 +1 @@
1
- {"version":3,"file":"transactional.decorator.js","sourceRoot":"","sources":["../../src/decorators/transactional.decorator.ts"],"names":[],"mappings":";;;AAsCA,sCAsBC;AAoCD,4DAGC;AAnGD,sDAAuD;AAGvD;;;;;GAKG;AACU,QAAA,sBAAsB,GAAG,MAAM,CAAC,wBAAwB,CAAC,CAAC;AAUvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,aAAa,CAC3B,UAA0C,EAAE;IAE5C,MAAM,QAAQ,GAA0B;QACtC,WAAW,EAAE,6BAAe,CAAC,QAAQ;QACrC,GAAG,OAAO;KACX,CAAC;IAEF,MAAM,SAAS,GAAqC,CAClD,MAAc,EACd,YAA8B,EAC9B,UAA+B,EACzB,EAAE;QACR,MAAM,YAAY,GAAY,UAAU,EAAE,KAAK,CAAC;QAChD,IAAI,OAAO,YAAY,KAAK,UAAU,EAAE,CAAC;YACvC,OAAO,CAAC,cAAc,CAAC,8BAAsB,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,cAAc,CAAC,8BAAsB,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnE,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACI,MAAM,QAAQ,GAAG,CACtB,UAA0C,EAAE,EACV,EAAE,CAAC,aAAa,CAAC,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAFxE,QAAA,QAAQ,YAEgE;AAErF;;;;;;;;;;;GAWG;AACI,MAAM,eAAe,GAAG,CAC7B,eAAuB,EACvB,UAA0C,EAAE,EACV,EAAE,CAAC,aAAa,CAAC,EAAE,GAAG,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;AAHzE,QAAA,eAAe,mBAG0D;AAEtF;;;;;;GAMG;AACH,SAAgB,wBAAwB,CAAC,MAAc;IACrD,MAAM,KAAK,GAAY,OAAO,CAAC,WAAW,CAAC,8BAAsB,EAAE,MAAM,CAAC,CAAC;IAC3E,OAAO,KAA0C,CAAC;AACpD,CAAC"}
1
+ {"version":3,"file":"transactional.decorator.js","sourceRoot":"","sources":["../../src/decorators/transactional.decorator.ts"],"names":[],"mappings":";;;AAsCA,sCAsBC;AAyCD,4DAGC;AAxGD,sDAAuD;AAGvD;;;;;GAKG;AACU,QAAA,sBAAsB,GAAG,MAAM,CAAC,wBAAwB,CAAC,CAAC;AAUvE;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,aAAa,CAC3B,UAA0C,EAAE;IAE5C,MAAM,QAAQ,GAA0B;QACtC,WAAW,EAAE,6BAAe,CAAC,QAAQ;QACrC,GAAG,OAAO;KACX,CAAC;IAEF,MAAM,SAAS,GAAqC,CAClD,MAAc,EACd,YAA8B,EAC9B,UAA+B,EACzB,EAAE;QACR,MAAM,YAAY,GAAY,UAAU,EAAE,KAAK,CAAC;QAChD,IAAI,OAAO,YAAY,KAAK,UAAU,EAAE,CAAC;YACvC,OAAO,CAAC,cAAc,CAAC,8BAAsB,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,cAAc,CAAC,8BAAsB,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACnE,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;GAUG;AACI,MAAM,QAAQ,GAAG,CACtB,UAA0C,EAAE,EACV,EAAE,CAAC,aAAa,CAAC,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;AAFxE,QAAA,QAAQ,YAEgE;AAErF;;;;;;;;;;;GAWG;AACI,MAAM,eAAe,GAAG,CAC7B,eAAuB,EACvB,UAA0C,EAAE,EACV,EAAE,CAAC,aAAa,CAAC,EAAE,GAAG,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;AAHzE,QAAA,eAAe,mBAG0D;AAEtF;;;;;;GAMG;AACH,SAAgB,wBAAwB,CAAC,MAAc;IACrD,MAAM,KAAK,GAAY,OAAO,CAAC,WAAW,CAAC,8BAAsB,EAAE,MAAM,CAAC,CAAC;IAC3E,OAAO,KAA0C,CAAC;AACpD,CAAC"}
@@ -14,7 +14,7 @@ import type { TransactionAdapter } from '../types/transaction-adapter';
14
14
  *
15
15
  * Matches NestJS conventions (`TypeOrmModule`, `MongooseModule`,
16
16
  * `ClientsModule`) and aligns with `OutboxModule.forRoot` from
17
- * Phase 14.3.2 (ADR-019). Cross-call coordination of singletons
17
+ * ADR-019. Cross-call coordination of singletons
18
18
  * (`AdapterRegistry`, `TransactionManager`, `APP_INTERCEPTOR`,
19
19
  * `TransactionalMethodsBootstrap`, `TRANSACTION_OBSERVERS`) lives in
20
20
  * static class storage on {@link TransactionalModule}, mirroring
@@ -51,7 +51,7 @@ export interface TransactionalModuleOptions {
51
51
  */
52
52
  readonly adapter?: TransactionAdapter;
53
53
  /**
54
- * When `true` (default — Phase 14.10), the module is registered as
54
+ * When `true` (default), the module is registered as
55
55
  * `@Global()` — its exports are available app-wide without being
56
56
  * re-imported. Honored per call (each `forRoot` builds its own
57
57
  * `DynamicModule` with its own `global` flag). Multi-call setups
@@ -123,7 +123,7 @@ export interface TransactionalModuleAsyncOptions extends Pick<ModuleMetadata, 'i
123
123
  * default) the global {@link TransactionalInterceptor}. ADR-018
124
124
  * shape — multi-dataSource deployments call {@link forRoot} once per
125
125
  * dataSource. Static class storage coordinates singletons across
126
- * calls (mirrors Phase 14.3.2 `OutboxModule` per ADR-019).
126
+ * calls (mirrors `OutboxModule` per ADR-019).
127
127
  *
128
128
  * The first call registers the process-wide infrastructure; subsequent
129
129
  * calls only contribute per-dataSource providers. Adapter-specific
@@ -25,7 +25,7 @@ const ASYNC_REGISTRATION_TOKEN = (id) => Symbol(`TRANSACTIONAL_ASYNC_REGISTRATIO
25
25
  * default) the global {@link TransactionalInterceptor}. ADR-018
26
26
  * shape — multi-dataSource deployments call {@link forRoot} once per
27
27
  * dataSource. Static class storage coordinates singletons across
28
- * calls (mirrors Phase 14.3.2 `OutboxModule` per ADR-019).
28
+ * calls (mirrors `OutboxModule` per ADR-019).
29
29
  *
30
30
  * The first call registers the process-wide infrastructure; subsequent
31
31
  * calls only contribute per-dataSource providers. Adapter-specific
@@ -149,7 +149,7 @@ let TransactionalModule = class TransactionalModule {
149
149
  // ADAPTER_REGISTRY factory closes over the static `registrations`
150
150
  // Map. By the time NestJS resolves this factory, every synchronous
151
151
  // `forRoot` body has run and the Map is fully populated. Pattern
152
- // mirrors Phase 14.3.2 `OutboxModule` per ADR-019.
152
+ // mirrors `OutboxModule` per ADR-019.
153
153
  providers.push({
154
154
  provide: adapter_registry_1.ADAPTER_REGISTRY,
155
155
  useFactory: () => buildRegistryFromStaticStorage(TransactionalModule_1),
@@ -245,10 +245,7 @@ let TransactionalModule = class TransactionalModule {
245
245
  },
246
246
  inject: [asyncToken, adapter_registry_1.ADAPTER_REGISTRY],
247
247
  };
248
- const providers = [
249
- asyncOptionsProvider,
250
- adapterEagerRegistrationProvider,
251
- ];
248
+ const providers = [asyncOptionsProvider, adapterEagerRegistrationProvider];
252
249
  const exportTokens = [];
253
250
  if (isFirst) {
254
251
  this.infrastructureRegistered = true;
@@ -274,7 +271,7 @@ let TransactionalModule = class TransactionalModule {
274
271
  // after the factory runs).
275
272
  providers.push({
276
273
  provide: transaction_observer_1.TRANSACTION_OBSERVERS,
277
- useFactory: (opts) => opts.observers ? [...opts.observers] : [],
274
+ useFactory: (opts) => (opts.observers ? [...opts.observers] : []),
278
275
  inject: [asyncToken],
279
276
  });
280
277
  if (options.registerInterceptor !== false) {
@@ -351,7 +348,7 @@ function buildPerDataSourceProviders(adapter) {
351
348
  * `registrations` Map on {@link TransactionalModule}. Called by the
352
349
  * first-`forRoot`'s `ADAPTER_REGISTRY` factory at provider-resolution
353
350
  * time — by then every synchronous `forRoot` body has populated the
354
- * Map. Pattern mirrors Phase 14.3.2 `OutboxModule` per ADR-019.
351
+ * Map. Pattern mirrors `OutboxModule` per ADR-019.
355
352
  *
356
353
  * @internal
357
354
  */
@@ -1 +1 @@
1
- {"version":3,"file":"transactional.module.js","sourceRoot":"","sources":["../../src/module/transactional.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAOwB;AACxB,uCAAgE;AAEhE,kGAA6F;AAC7F,kFAA6E;AAC7E,wFAAoF;AACpF,kEAIqC;AACrC,wEAAoE;AACpE,gFAG+C;AAC/C,uDAI+B;AAgI/B,MAAM,mBAAmB,GAAG,CAAC,EAAU,EAAU,EAAE,CACjD,MAAM,CAAC,+BAA+B,EAAE,GAAG,CAAC,CAAC;AAC/C,MAAM,wBAAwB,GAAG,CAAC,EAAU,EAAU,EAAE,CACtD,MAAM,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAC;AAEpD;;;;;;;;;;;;;GAaG;AAEI,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;;IAC9B;;;;;;;;;;;OAWG;IACK,MAAM,CAAU,aAAa,GAAG,IAAI,GAAG,EAA+B,CAAC;IAE/E;;;;;;;;;;;;;OAaG;IACK,MAAM,CAAC,wBAAwB,GAAG,KAAK,CAAC;IAEhD;;;;;;OAMG;IACK,MAAM,CAAC,YAAY,GAAG,CAAC,CAAC;IAEhC;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,eAAe;QACpB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,wBAAwB,GAAG,KAAK,CAAC;QACtC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IACxB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,MAAM,CAAC,OAAO,CAAC,UAAsC,EAAE;QACrD,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,wBAAwB,CAAC;QAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAEhC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;YAClC,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CACb,6CAA6C,EAAE,wBAAwB;oBACrE,wDAAwD;oBACxD,8EAA8E,CACjF,CAAC;YACJ,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,EAAE;gBACzB,WAAW,EAAE,OAAO,CAAC,IAAI;gBACzB,YAAY,EAAE,EAAE;gBAChB,OAAO;aACR,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CACb,6EAA6E;gBAC3E,6EAA6E;gBAC7E,iEAAiE;gBACjE,8EAA8E,CACjF,CAAC;QACJ,CAAC;QAED,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CACb,+EAA+E;gBAC7E,yEAAyE,CAC5E,CAAC;QACJ,CAAC;QAED,MAAM,SAAS,GAAe,EAAE,CAAC;QACjC,MAAM,YAAY,GAAqB,EAAE,CAAC;QAE1C,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,SAAS,CAAC,IAAI,CAAC,GAAG,2BAA2B,CAAC,OAAO,CAAC,CAAC,CAAC;YACxD,YAAY,CAAC,IAAI,CAAC,GAAG,yBAAyB,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC;QAC1E,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC;YAErC,kEAAkE;YAClE,mEAAmE;YACnE,iEAAiE;YACjE,mDAAmD;YACnD,SAAS,CAAC,IAAI,CAAC;gBACb,OAAO,EAAE,mCAAgB;gBACzB,UAAU,EAAE,GAAoB,EAAE,CAChC,8BAA8B,CAAC,qBAAmB,CAAC;aACtD,CAAC,CAAC;YACH,SAAS,CAAC,IAAI,CAAC;gBACb,OAAO,EAAE,kCAAe;gBACxB,WAAW,EAAE,mCAAgB;aAC9B,CAAC,CAAC;YACH,SAAS,CAAC,IAAI,CAAC,wCAAkB,CAAC,CAAC;YAEnC,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;gBACpC,SAAS,CAAC,IAAI,CAAC;oBACb,OAAO,EAAE,4CAAqB;oBAC9B,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,SAAS,CAAC;iBACjC,CAAC,CAAC;YACL,CAAC;YAED,IAAI,OAAO,CAAC,mBAAmB,KAAK,KAAK,EAAE,CAAC;gBAC1C,SAAS,CAAC,IAAI,CAAC;oBACb,OAAO,EAAE,sBAAe;oBACxB,QAAQ,EAAE,oDAAwB;iBACnC,CAAC,CAAC;YACL,CAAC;YAED,IAAI,OAAO,CAAC,wBAAwB,KAAK,KAAK,EAAE,CAAC;gBAC/C,SAAS,CAAC,IAAI,CAAC,+DAA6B,CAAC,CAAC;YAChD,CAAC;YAED,YAAY,CAAC,IAAI,CAAC,wCAAkB,EAAE,mCAAgB,EAAE,kCAAe,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO;YACL,MAAM,EAAE,qBAAmB;YAC3B,MAAM,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;YAChC,OAAO,EAAE,CAAC,sBAAe,CAAC;YAC1B,SAAS;YACT,OAAO,EAAE,YAAY;SACtB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,MAAM,CAAC,YAAY,CAAC,OAAwC;QAC1D,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,wBAAwB,CAAC;QAC/C,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,mBAAmB,CAAC,EAAE,CAAC,CAAC;QAC3C,MAAM,iBAAiB,GAAG,wBAAwB,CAAC,EAAE,CAAC,CAAC;QAEvD,kEAAkE;QAClE,kEAAkE;QAClE,kEAAkE;QAClE,gEAAgE;QAChE,+DAA+D;QAC/D,iEAAiE;QAEjE,MAAM,oBAAoB,GAAoB;YAC5C,OAAO,EAAE,UAAU;YACnB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;SACzD,CAAC;QAEF,MAAM,gCAAgC,GAAoB;YACxD,OAAO,EAAE,iBAAiB;YAC1B,UAAU,EAAE,CACV,IAA2C,EAC3C,QAAyB,EACnB,EAAE;gBACR,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;oBAC/B,QAAQ,CAAC,QAAQ,CAAC;wBAChB,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI;wBAC9B,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,cAAc;wBACzC,OAAO,EAAE,IAAI,CAAC,OAAO;qBACtB,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC;YACD,MAAM,EAAE,CAAC,UAAU,EAAE,mCAAgB,CAAC;SACvC,CAAC;QAEF,MAAM,SAAS,GAAe;YAC5B,oBAAoB;YACpB,gCAAgC;SACjC,CAAC;QACF,MAAM,YAAY,GAAqB,EAAE,CAAC;QAE1C,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC,wBAAwB,GAAG,IAAI,CAAC;YAErC,0DAA0D;YAC1D,kDAAkD;YAClD,0DAA0D;YAC1D,8DAA8D;YAC9D,8DAA8D;YAC9D,qCAAqC;YACrC,SAAS,CAAC,IAAI,CAAC;gBACb,OAAO,EAAE,mCAAgB;gBACzB,UAAU,EAAE,GAAoB,EAAE,CAAC,IAAI,kCAAe,EAAE;aACzD,CAAC,CAAC;YACH,SAAS,CAAC,IAAI,CAAC;gBACb,OAAO,EAAE,kCAAe;gBACxB,WAAW,EAAE,mCAAgB;aAC9B,CAAC,CAAC;YACH,SAAS,CAAC,IAAI,CAAC,wCAAkB,CAAC,CAAC;YAEnC,+DAA+D;YAC/D,iEAAiE;YACjE,+DAA+D;YAC/D,gEAAgE;YAChE,2BAA2B;YAC3B,SAAS,CAAC,IAAI,CAAC;gBACb,OAAO,EAAE,4CAAqB;gBAC9B,UAAU,EAAE,CAAC,IAA2C,EAAkC,EAAE,CAC1F,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;gBAC3C,MAAM,EAAE,CAAC,UAAU,CAAC;aACrB,CAAC,CAAC;YAEH,IAAI,OAAO,CAAC,mBAAmB,KAAK,KAAK,EAAE,CAAC;gBAC1C,SAAS,CAAC,IAAI,CAAC;oBACb,OAAO,EAAE,sBAAe;oBACxB,QAAQ,EAAE,oDAAwB;iBACnC,CAAC,CAAC;YACL,CAAC;YAED,IAAI,OAAO,CAAC,wBAAwB,KAAK,KAAK,EAAE,CAAC;gBAC/C,SAAS,CAAC,IAAI,CAAC,+DAA6B,CAAC,CAAC;YAChD,CAAC;YAED,YAAY,CAAC,IAAI,CAAC,wCAAkB,EAAE,mCAAgB,EAAE,kCAAe,CAAC,CAAC;QAC3E,CAAC;QAED,OAAO;YACL,MAAM,EAAE,qBAAmB;YAC3B,MAAM,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;YAChC,OAAO,EAAE,CAAC,sBAAe,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YACtD,SAAS;YACT,OAAO,EAAE,YAAY;SACtB,CAAC;IACJ,CAAC;;AA1SU,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,mBAAmB,CA2S/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,SAAS,2BAA2B,CAAC,OAA2B;IAC9D,MAAM,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAClC,OAAO;QACL;YACE,OAAO,EAAE,IAAA,0CAA4B,EAAC,EAAE,CAAC;YACzC,QAAQ,EAAE,OAAO;SAClB;QACD;YACE,OAAO,EAAE,IAAA,wCAA0B,EAAC,EAAE,CAAC;YACvC,QAAQ,EAAE,IAAI,iDAAsB,CAAC,EAAE,CAAC;SACzC;QACD;YACE,OAAO,EAAE,IAAA,wCAA0B,EAAC,EAAE,CAAC;YACvC,WAAW,EAAE,wCAAkB;SAChC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,8BAA8B,CACrC,WAAuC;IAEvC,MAAM,QAAQ,GAAG,IAAI,kCAAe,EAAE,CAAC;IACvC,mEAAmE;IACnE,MAAM,aAAa,GACjB,WACD,CAAC,aAAa,CAAC;IAChB,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC;QACzC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,yBAAyB,CAAC,EAAU;IAC3C,OAAO;QACL,IAAA,0CAA4B,EAAC,EAAE,CAAC;QAChC,IAAA,wCAA0B,EAAC,EAAE,CAAC;QAC9B,IAAA,wCAA0B,EAAC,EAAE,CAAC;KAC/B,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"transactional.module.js","sourceRoot":"","sources":["../../src/module/transactional.module.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"token-utils.js","sourceRoot":"","sources":["../../src/tokens/token-utils.ts"],"names":[],"mappings":";;AAiCA,gEAIC;AAQD,gEAIC;AAOD,oEAIC;AAQD,gFAEC;AAtED,2CAAuD;AAEvD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;GAQG;AACH,SAAgB,0BAA0B,CACxC,aAAqB,oCAAwB;IAE7C,OAAO,GAAG,UAAU,oBAAoB,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,0BAA0B,CACxC,aAAqB,oCAAwB;IAE7C,OAAO,GAAG,UAAU,oBAAoB,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,SAAgB,4BAA4B,CAC1C,aAAqB,oCAAwB;IAE7C,OAAO,GAAG,UAAU,sBAAsB,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kCAAkC;IAChD,OAAO,4BAA4B,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"token-utils.js","sourceRoot":"","sources":["../../src/tokens/token-utils.ts"],"names":[],"mappings":";;AAiCA,gEAEC;AAQD,gEAEC;AAOD,oEAIC;AAQD,gFAEC;AAlED,2CAAuD;AAEvD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;;GAQG;AACH,SAAgB,0BAA0B,CAAC,aAAqB,oCAAwB;IACtF,OAAO,GAAG,UAAU,oBAAoB,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,0BAA0B,CAAC,aAAqB,oCAAwB;IACtF,OAAO,GAAG,UAAU,oBAAoB,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,SAAgB,4BAA4B,CAC1C,aAAqB,oCAAwB;IAE7C,OAAO,GAAG,UAAU,sBAAsB,CAAC;AAC7C,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kCAAkC;IAChD,OAAO,4BAA4B,CAAC;AACtC,CAAC"}
@@ -16,16 +16,39 @@ export interface TransactionOptions {
16
16
  */
17
17
  readonly isolation?: IsolationLevel;
18
18
  /**
19
- * Hint that the transaction will only issue reads. Adapters may use this
20
- * to route to a read replica or to issue `SET TRANSACTION READ ONLY`.
21
- * It is a hint, not an enforcement writes may still be attempted and
22
- * may be rejected by the database.
19
+ * Hint that the transaction will only issue reads. A hint by design,
20
+ * matching Spring's semantics: adapters honour it where the underlying
21
+ * database allows, and ignore it where it cannot be expressed
22
+ * (DD-027).
23
+ *
24
+ * `TypeOrmTransactionAdapter` issues `SET TRANSACTION READ ONLY` on
25
+ * Postgres-family dialects (`postgres`, `cockroachdb`,
26
+ * `aurora-postgres`), so a write inside the transaction is refused by
27
+ * the database. On every other dialect it is a silent no-op — notably
28
+ * MySQL, where the access mode can only be set as
29
+ * `START TRANSACTION READ ONLY` and TypeORM does not expose that
30
+ * moment.
31
+ *
32
+ * Only applies when the adapter actually starts the transaction: a
33
+ * `REQUIRED` call joining an existing read-write transaction cannot
34
+ * make it read-only after the fact.
23
35
  */
24
36
  readonly readOnly?: boolean;
25
37
  /**
26
- * Transaction timeout in milliseconds. If the adapter supports
27
- * transaction-level timeouts (e.g. `statement_timeout` on Postgres),
28
- * exceeding this triggers a rollback. Omit for no timeout.
38
+ * Budget for the whole transaction, in milliseconds. Omit for no
39
+ * timeout.
40
+ *
41
+ * NOT IMPLEMENTED by `TypeOrmTransactionAdapter`, and deliberately not
42
+ * approximated (DD-027). TypeORM exposes no transaction-level timeout,
43
+ * and the nearest dialect feature — Postgres' `statement_timeout` —
44
+ * bounds each statement rather than the transaction, so
45
+ * `timeout: 5000` on a method issuing four queries would allow twenty
46
+ * seconds, not five. A wrong meaning under a familiar name is worse
47
+ * than a documented gap.
48
+ *
49
+ * The option stays in the surface as the extension point for adapters
50
+ * whose driver has a real transaction budget: Prisma's `$transaction`
51
+ * accepts exactly this.
29
52
  */
30
53
  readonly timeout?: number;
31
54
  }
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "@nestjs-transactional/core",
3
- "version": "1.0.0-alpha.3",
3
+ "version": "1.0.0",
4
4
  "description": "Declarative transaction management for NestJS — core primitives (AsyncLocalStorage context, TransactionManager, @Transactional decorator, adapter port)",
5
5
  "license": "MIT",
6
+ "type": "commonjs",
7
+ "sideEffects": false,
6
8
  "author": "Igor Golovanov",
7
9
  "repository": {
8
10
  "type": "git",
9
- "url": "https://github.com/igorgolovanov/nestjs-transactional.git",
11
+ "url": "git+https://github.com/igorgolovanov/nestjs-transactional.git",
10
12
  "directory": "packages/core"
11
13
  },
12
14
  "bugs": {
@@ -42,9 +44,15 @@
42
44
  "default": "./dist/testing/index.js"
43
45
  }
44
46
  },
47
+ "typesVersions": {
48
+ "*": {
49
+ "testing": [
50
+ "./dist/testing/index.d.ts"
51
+ ]
52
+ }
53
+ },
45
54
  "publishConfig": {
46
55
  "access": "public",
47
- "tag": "alpha",
48
56
  "provenance": true
49
57
  },
50
58
  "peerDependencies": {
@@ -70,6 +78,9 @@
70
78
  "test:watch": "jest --watch",
71
79
  "test:cov": "jest --coverage",
72
80
  "type-check": "tsc --noEmit",
73
- "lint": "eslint \"src/**/*.ts\""
81
+ "lint": "eslint \"src/**/*.ts\"",
82
+ "api:check": "api-extractor run && api-extractor run -c api-extractor.testing.json",
83
+ "api:update": "api-extractor run --local && api-extractor run --local -c api-extractor.testing.json",
84
+ "publish:check": "publint && attw --pack ."
74
85
  }
75
86
  }