@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 +117 -178
- package/dist/context/transaction-context-view.js.map +1 -1
- package/dist/context/transaction.context.d.ts +1 -1
- package/dist/context/transaction.context.js +1 -1
- package/dist/context/transaction.context.js.map +1 -1
- package/dist/decorators/transactional.decorator.d.ts +5 -0
- package/dist/decorators/transactional.decorator.js +5 -0
- package/dist/decorators/transactional.decorator.js.map +1 -1
- package/dist/module/transactional.module.d.ts +3 -3
- package/dist/module/transactional.module.js +5 -8
- package/dist/module/transactional.module.js.map +1 -1
- package/dist/tokens/token-utils.js.map +1 -1
- package/dist/types/transaction-options.d.ts +30 -7
- package/package.json +15 -4
package/README.md
CHANGED
|
@@ -1,265 +1,204 @@
|
|
|
1
1
|
# @nestjs-transactional/core
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@nestjs-transactional/core)
|
|
4
4
|
[](https://github.com/igorgolovanov/nestjs-transactional/blob/main/LICENSE)
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
|
44
|
-
|
|
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
|
|
64
|
-
//
|
|
65
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
77
|
-
service method
|
|
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 {
|
|
60
|
+
import { Injectable } from '@nestjs/common';
|
|
81
61
|
import { Transactional } from '@nestjs-transactional/core';
|
|
82
62
|
|
|
83
|
-
@
|
|
84
|
-
export class
|
|
85
|
-
constructor(private readonly orders: OrdersService) {}
|
|
86
|
-
|
|
87
|
-
@Get(':id')
|
|
63
|
+
@Injectable()
|
|
64
|
+
export class OrdersService {
|
|
88
65
|
@Transactional()
|
|
89
|
-
async
|
|
90
|
-
|
|
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
|
-
|
|
74
|
+
## Propagation
|
|
96
75
|
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
121
|
+
Two options carry caveats worth knowing before you rely on them:
|
|
153
122
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
##
|
|
135
|
+
## Commit and rollback hooks
|
|
189
136
|
|
|
190
|
-
Register
|
|
191
|
-
|
|
137
|
+
Register from inside a transactional method; the hook binds to the
|
|
138
|
+
transaction currently running.
|
|
192
139
|
|
|
193
140
|
```ts
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
-
|
|
204
|
-
|
|
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
|
-
|
|
209
|
-
|
|
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
|
-
|
|
214
|
-
}
|
|
151
|
+
return order;
|
|
215
152
|
}
|
|
216
153
|
```
|
|
217
154
|
|
|
218
|
-
|
|
219
|
-
|
|
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
|
|
224
|
-
|
|
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
|
-
|
|
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
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
|
|
250
|
-
const inventory = new InMemoryTransactionAdapter('inventory');
|
|
186
|
+
TransactionalModule.forRoot({ isGlobal: true, adapter: myAdapter });
|
|
251
187
|
```
|
|
252
188
|
|
|
253
|
-
|
|
189
|
+
One `forRoot` call registers one adapter. Multi-dataSource
|
|
190
|
+
applications call it once per dataSource.
|
|
254
191
|
|
|
255
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
202
|
+
## License
|
|
264
203
|
|
|
265
|
-
|
|
204
|
+
MIT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transaction-context-view.js","sourceRoot":"","sources":["../../src/context/transaction-context-view.ts"],"names":[],"mappings":";;;AAAA,+
|
|
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
|
|
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
|
|
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,
|
|
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;
|
|
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
|
-
*
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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,
|
|
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.
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
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
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
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
|
|
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
|
}
|