@nestjs-transactional/core 1.0.0-alpha.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/LICENSE +21 -0
- package/README.md +265 -0
- package/dist/bootstrap/transactional-methods.bootstrap.d.ts +42 -0
- package/dist/bootstrap/transactional-methods.bootstrap.js +129 -0
- package/dist/bootstrap/transactional-methods.bootstrap.js.map +1 -0
- package/dist/context/transaction-context-view.d.ts +38 -0
- package/dist/context/transaction-context-view.js +48 -0
- package/dist/context/transaction-context-view.js.map +1 -0
- package/dist/context/transaction.context.d.ts +114 -0
- package/dist/context/transaction.context.js +112 -0
- package/dist/context/transaction.context.js.map +1 -0
- package/dist/decorators/inject-decorators.d.ts +36 -0
- package/dist/decorators/inject-decorators.js +45 -0
- package/dist/decorators/inject-decorators.js.map +1 -0
- package/dist/decorators/transactional.decorator.d.ts +64 -0
- package/dist/decorators/transactional.decorator.js +82 -0
- package/dist/decorators/transactional.decorator.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/interceptor/transactional.interceptor.d.ts +28 -0
- package/dist/interceptor/transactional.interceptor.js +56 -0
- package/dist/interceptor/transactional.interceptor.js.map +1 -0
- package/dist/internal/markers.d.ts +15 -0
- package/dist/internal/markers.js +18 -0
- package/dist/internal/markers.js.map +1 -0
- package/dist/manager/adapter.registry.d.ts +103 -0
- package/dist/manager/adapter.registry.js +179 -0
- package/dist/manager/adapter.registry.js.map +1 -0
- package/dist/manager/transaction.manager.d.ts +129 -0
- package/dist/manager/transaction.manager.js +412 -0
- package/dist/manager/transaction.manager.js.map +1 -0
- package/dist/module/transactional.module.d.ts +242 -0
- package/dist/module/transactional.module.js +374 -0
- package/dist/module/transactional.module.js.map +1 -0
- package/dist/observability/transaction-observer.d.ts +78 -0
- package/dist/observability/transaction-observer.js +18 -0
- package/dist/observability/transaction-observer.js.map +1 -0
- package/dist/testing/in-memory.adapter.d.ts +66 -0
- package/dist/testing/in-memory.adapter.js +83 -0
- package/dist/testing/in-memory.adapter.js.map +1 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +18 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/tokens/constants.d.ts +14 -0
- package/dist/tokens/constants.js +17 -0
- package/dist/tokens/constants.js.map +1 -0
- package/dist/tokens/index.d.ts +3 -0
- package/dist/tokens/index.js +11 -0
- package/dist/tokens/index.js.map +1 -0
- package/dist/tokens/token-utils.d.ts +52 -0
- package/dist/tokens/token-utils.js +67 -0
- package/dist/tokens/token-utils.js.map +1 -0
- package/dist/types/domain-event.d.ts +18 -0
- package/dist/types/domain-event.js +3 -0
- package/dist/types/domain-event.js.map +1 -0
- package/dist/types/errors.d.ts +50 -0
- package/dist/types/errors.js +61 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/isolation.d.ts +11 -0
- package/dist/types/isolation.js +3 -0
- package/dist/types/isolation.js.map +1 -0
- package/dist/types/propagation.d.ts +63 -0
- package/dist/types/propagation.js +67 -0
- package/dist/types/propagation.js.map +1 -0
- package/dist/types/transaction-adapter.d.ts +72 -0
- package/dist/types/transaction-adapter.js +3 -0
- package/dist/types/transaction-adapter.js.map +1 -0
- package/dist/types/transaction-handle.d.ts +23 -0
- package/dist/types/transaction-handle.js +3 -0
- package/dist/types/transaction-handle.js.map +1 -0
- package/dist/types/transaction-options.d.ts +88 -0
- package/dist/types/transaction-options.js +3 -0
- package/dist/types/transaction-options.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransactionContext = void 0;
|
|
4
|
+
const node_async_hooks_1 = require("node:async_hooks");
|
|
5
|
+
const errors_1 = require("../types/errors");
|
|
6
|
+
const als = new node_async_hooks_1.AsyncLocalStorage();
|
|
7
|
+
/**
|
|
8
|
+
* Thin façade over `AsyncLocalStorage` that carries the active
|
|
9
|
+
* {@link TransactionContextStore} across async boundaries. This is the
|
|
10
|
+
* foundation of the module — every decorator, interceptor, and adapter helper
|
|
11
|
+
* ultimately asks this class whether a transaction is live on the current
|
|
12
|
+
* async chain.
|
|
13
|
+
*
|
|
14
|
+
* **Internal Map key format**: `${adapterName}:${instanceName}` (composite)
|
|
15
|
+
* for historical reasons and cross-package compatibility — typeorm
|
|
16
|
+
* helpers, the CQRS dispatcher, and the outbox publisher all consume
|
|
17
|
+
* this format directly via {@link getActiveTransaction}. The composite
|
|
18
|
+
* key is also the format `TransactionManager` writes under.
|
|
19
|
+
*
|
|
20
|
+
* **Public dataSource-name access**:
|
|
21
|
+
* {@link getActiveTransactionByDataSource} provides dataSource-name
|
|
22
|
+
* lookup for Phase 14.2+ multi-adapter consumers — it scans the Map
|
|
23
|
+
* for the entry whose `adapterInstanceName === dataSource`. Both
|
|
24
|
+
* access patterns coexist; future cleanup is possible once
|
|
25
|
+
* cross-package consumers migrate to the dataSource-name lookup and
|
|
26
|
+
* no backwards-compatibility constraints remain.
|
|
27
|
+
*/
|
|
28
|
+
class TransactionContext {
|
|
29
|
+
/**
|
|
30
|
+
* Run `fn` inside a transaction context scope.
|
|
31
|
+
*
|
|
32
|
+
* - If there is no active store on the current async chain, a new store is
|
|
33
|
+
* created (empty active-transaction map, `correlationId`, current time)
|
|
34
|
+
* and installed for the duration of `fn`.
|
|
35
|
+
* - If there is already an active store, `fn` is executed directly — the
|
|
36
|
+
* existing store is reused. The `correlationId` argument is ignored in
|
|
37
|
+
* that case; the outermost scope owns the correlation id.
|
|
38
|
+
*
|
|
39
|
+
* Propagates the value resolved (or error thrown) by `fn`.
|
|
40
|
+
*/
|
|
41
|
+
static run(correlationId, fn) {
|
|
42
|
+
if (als.getStore() !== undefined) {
|
|
43
|
+
return fn();
|
|
44
|
+
}
|
|
45
|
+
const store = {
|
|
46
|
+
activeTransactions: new Map(),
|
|
47
|
+
correlationId,
|
|
48
|
+
startedAt: new Date(),
|
|
49
|
+
};
|
|
50
|
+
return als.run(store, fn);
|
|
51
|
+
}
|
|
52
|
+
/** Return the active store, or `undefined` if called outside any run() scope. */
|
|
53
|
+
static getStore() {
|
|
54
|
+
return als.getStore();
|
|
55
|
+
}
|
|
56
|
+
/** Return the active transaction registered under `adapterInstanceName`, or `undefined`. */
|
|
57
|
+
static getActiveTransaction(adapterInstanceName) {
|
|
58
|
+
return als.getStore()?.activeTransactions.get(adapterInstanceName);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Return the active transaction whose adapter instance was
|
|
62
|
+
* registered under the given dataSource name (DD-020 / DD-023).
|
|
63
|
+
* Scans the active-transactions Map for the entry whose
|
|
64
|
+
* `adapterInstanceName === dataSource`.
|
|
65
|
+
*
|
|
66
|
+
* Returns the first match — there is exactly one active transaction
|
|
67
|
+
* per dataSource by construction (multiple adapters sharing the
|
|
68
|
+
* same dataSource name is rejected at the registry level by
|
|
69
|
+
* {@link AdapterRegistry.getByDataSource}).
|
|
70
|
+
*
|
|
71
|
+
* Used by {@link TransactionContextView} and by smart-facade
|
|
72
|
+
* publishers to answer "is there an active transaction for *my*
|
|
73
|
+
* dataSource?" without needing to know the adapter type that owns
|
|
74
|
+
* the dataSource.
|
|
75
|
+
*/
|
|
76
|
+
static getActiveTransactionByDataSource(dataSource) {
|
|
77
|
+
const store = als.getStore();
|
|
78
|
+
if (store === undefined) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
for (const tx of store.activeTransactions.values()) {
|
|
82
|
+
if (tx.adapterInstanceName === dataSource) {
|
|
83
|
+
return tx;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Register `tx` under `adapterInstanceName` on the current store.
|
|
90
|
+
*
|
|
91
|
+
* @throws {IllegalTransactionStateError} If called outside of a run() scope.
|
|
92
|
+
* Adapters must not attempt to register a transaction without a
|
|
93
|
+
* surrounding context — doing so would leak the transaction state.
|
|
94
|
+
*/
|
|
95
|
+
static setActiveTransaction(adapterInstanceName, tx) {
|
|
96
|
+
const store = als.getStore();
|
|
97
|
+
if (store === undefined) {
|
|
98
|
+
throw new errors_1.IllegalTransactionStateError('Cannot set active transaction outside of TransactionContext.run()');
|
|
99
|
+
}
|
|
100
|
+
store.activeTransactions.set(adapterInstanceName, tx);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Remove the active transaction registered under `adapterInstanceName`.
|
|
104
|
+
* Idempotent: a no-op when no store is active or the instance is not
|
|
105
|
+
* registered, so that adapter cleanup paths can call it unconditionally.
|
|
106
|
+
*/
|
|
107
|
+
static removeActiveTransaction(adapterInstanceName) {
|
|
108
|
+
als.getStore()?.activeTransactions.delete(adapterInstanceName);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.TransactionContext = TransactionContext;
|
|
112
|
+
//# sourceMappingURL=transaction.context.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inject the per-dataSource `TransactionManager`. Sugar over
|
|
3
|
+
* `@Inject(getTransactionManagerToken(dataSource))` for IDE
|
|
4
|
+
* discoverability — matches `@nestjs/typeorm`'s
|
|
5
|
+
* `@InjectRepository(Entity, dataSource?)` ergonomics (DD-022).
|
|
6
|
+
*
|
|
7
|
+
* Default `dataSource` is `'default'`, so single-adapter consumers
|
|
8
|
+
* write `@InjectTransactionManager()` exactly where they would have
|
|
9
|
+
* written `@Inject(TransactionManager)` before.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* class BillingService {
|
|
14
|
+
* constructor(
|
|
15
|
+
* @InjectTransactionManager()
|
|
16
|
+
* private readonly txManager: TransactionManager,
|
|
17
|
+
* @InjectTransactionManager('billing')
|
|
18
|
+
* private readonly billingTxManager: TransactionManager,
|
|
19
|
+
* ) {}
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare const InjectTransactionManager: (dataSource?: string) => ParameterDecorator;
|
|
24
|
+
/**
|
|
25
|
+
* Inject the per-dataSource `TransactionContext`. See
|
|
26
|
+
* {@link InjectTransactionManager} for ergonomics.
|
|
27
|
+
*/
|
|
28
|
+
export declare const InjectTransactionContext: (dataSource?: string) => ParameterDecorator;
|
|
29
|
+
/**
|
|
30
|
+
* Inject the per-dataSource `TransactionAdapter` instance. Useful
|
|
31
|
+
* for advanced consumers that need to call adapter-specific methods
|
|
32
|
+
* not exposed through `TransactionManager`. See
|
|
33
|
+
* {@link InjectTransactionManager} for ergonomics.
|
|
34
|
+
*/
|
|
35
|
+
export declare const InjectTransactionalAdapter: (dataSource?: string) => ParameterDecorator;
|
|
36
|
+
//# sourceMappingURL=inject-decorators.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InjectTransactionalAdapter = exports.InjectTransactionContext = exports.InjectTransactionManager = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
const constants_1 = require("../tokens/constants");
|
|
6
|
+
const token_utils_1 = require("../tokens/token-utils");
|
|
7
|
+
/**
|
|
8
|
+
* Inject the per-dataSource `TransactionManager`. Sugar over
|
|
9
|
+
* `@Inject(getTransactionManagerToken(dataSource))` for IDE
|
|
10
|
+
* discoverability — matches `@nestjs/typeorm`'s
|
|
11
|
+
* `@InjectRepository(Entity, dataSource?)` ergonomics (DD-022).
|
|
12
|
+
*
|
|
13
|
+
* Default `dataSource` is `'default'`, so single-adapter consumers
|
|
14
|
+
* write `@InjectTransactionManager()` exactly where they would have
|
|
15
|
+
* written `@Inject(TransactionManager)` before.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* class BillingService {
|
|
20
|
+
* constructor(
|
|
21
|
+
* @InjectTransactionManager()
|
|
22
|
+
* private readonly txManager: TransactionManager,
|
|
23
|
+
* @InjectTransactionManager('billing')
|
|
24
|
+
* private readonly billingTxManager: TransactionManager,
|
|
25
|
+
* ) {}
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
const InjectTransactionManager = (dataSource = constants_1.DEFAULT_DATA_SOURCE_NAME) => (0, common_1.Inject)((0, token_utils_1.getTransactionManagerToken)(dataSource));
|
|
30
|
+
exports.InjectTransactionManager = InjectTransactionManager;
|
|
31
|
+
/**
|
|
32
|
+
* Inject the per-dataSource `TransactionContext`. See
|
|
33
|
+
* {@link InjectTransactionManager} for ergonomics.
|
|
34
|
+
*/
|
|
35
|
+
const InjectTransactionContext = (dataSource = constants_1.DEFAULT_DATA_SOURCE_NAME) => (0, common_1.Inject)((0, token_utils_1.getTransactionContextToken)(dataSource));
|
|
36
|
+
exports.InjectTransactionContext = InjectTransactionContext;
|
|
37
|
+
/**
|
|
38
|
+
* Inject the per-dataSource `TransactionAdapter` instance. Useful
|
|
39
|
+
* for advanced consumers that need to call adapter-specific methods
|
|
40
|
+
* not exposed through `TransactionManager`. See
|
|
41
|
+
* {@link InjectTransactionManager} for ergonomics.
|
|
42
|
+
*/
|
|
43
|
+
const InjectTransactionalAdapter = (dataSource = constants_1.DEFAULT_DATA_SOURCE_NAME) => (0, common_1.Inject)((0, token_utils_1.getTransactionalAdapterToken)(dataSource));
|
|
44
|
+
exports.InjectTransactionalAdapter = InjectTransactionalAdapter;
|
|
45
|
+
//# sourceMappingURL=inject-decorators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inject-decorators.js","sourceRoot":"","sources":["../../src/decorators/inject-decorators.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AAExC,mDAA+D;AAC/D,uDAI+B;AAE/B;;;;;;;;;;;;;;;;;;;;;GAqBG;AACI,MAAM,wBAAwB,GAAG,CACtC,aAAqB,oCAAwB,EACzB,EAAE,CAAC,IAAA,eAAM,EAAC,IAAA,wCAA0B,EAAC,UAAU,CAAC,CAAC,CAAC;AAF3D,QAAA,wBAAwB,4BAEmC;AAExE;;;GAGG;AACI,MAAM,wBAAwB,GAAG,CACtC,aAAqB,oCAAwB,EACzB,EAAE,CAAC,IAAA,eAAM,EAAC,IAAA,wCAA0B,EAAC,UAAU,CAAC,CAAC,CAAC;AAF3D,QAAA,wBAAwB,4BAEmC;AAExE;;;;;GAKG;AACI,MAAM,0BAA0B,GAAG,CACxC,aAAqB,oCAAwB,EACzB,EAAE,CAAC,IAAA,eAAM,EAAC,IAAA,0CAA4B,EAAC,UAAU,CAAC,CAAC,CAAC;AAF7D,QAAA,0BAA0B,8BAEmC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ExtendedTransactionOptions } from '../types/transaction-options';
|
|
2
|
+
/**
|
|
3
|
+
* Metadata key under which {@link Transactional} stores its options on a
|
|
4
|
+
* target (a method's function object or a class constructor). Exposed for
|
|
5
|
+
* advanced introspection; most code should use
|
|
6
|
+
* {@link getTransactionalMetadata}.
|
|
7
|
+
*/
|
|
8
|
+
export declare const TRANSACTIONAL_METADATA: unique symbol;
|
|
9
|
+
/**
|
|
10
|
+
* Shape of the metadata attached by {@link Transactional}. Currently an
|
|
11
|
+
* alias for {@link ExtendedTransactionOptions} — kept as a distinct name so
|
|
12
|
+
* the decorator's public surface is self-documenting and so decorator-only
|
|
13
|
+
* options can be added later without touching the manager's options type.
|
|
14
|
+
*/
|
|
15
|
+
export type TransactionalMetadata = ExtendedTransactionOptions;
|
|
16
|
+
/**
|
|
17
|
+
* Mark a method or a class as transactional.
|
|
18
|
+
*
|
|
19
|
+
* **Metadata-only**: this decorator does NOT wrap the method at decoration
|
|
20
|
+
* time. The actual wrapping is performed at runtime by the three coordinated
|
|
21
|
+
* mechanisms described in ADR-005 — `TransactionalInterceptor` for
|
|
22
|
+
* request-boundary handlers, `TransactionalMethodsBootstrap` for regular
|
|
23
|
+
* `@Injectable` providers, and `CqrsHandlerWrapper` for CQRS handlers.
|
|
24
|
+
*
|
|
25
|
+
* Usage:
|
|
26
|
+
* - As a method decorator, the metadata is written onto `descriptor.value`
|
|
27
|
+
* (the method function).
|
|
28
|
+
* - As a class decorator, the metadata is written onto the class
|
|
29
|
+
* constructor. Downstream wrapping mechanisms treat every method of the
|
|
30
|
+
* class as transactional with these options (unless a method has its own
|
|
31
|
+
* `@Transactional` which overrides).
|
|
32
|
+
*
|
|
33
|
+
* Default propagation is {@link PropagationMode.REQUIRED}.
|
|
34
|
+
*/
|
|
35
|
+
export declare function Transactional(options?: Partial<TransactionalMetadata>): MethodDecorator & ClassDecorator;
|
|
36
|
+
/**
|
|
37
|
+
* Alias for `@Transactional({ readOnly: true })`. Use on query methods that
|
|
38
|
+
* must not mutate state. Options are applied first and the `readOnly: true`
|
|
39
|
+
* flag is overlaid on top, so callers cannot turn it off from here — use
|
|
40
|
+
* `@Transactional` directly if that is the intent.
|
|
41
|
+
*/
|
|
42
|
+
export declare const ReadOnly: (options?: Partial<TransactionalMetadata>) => MethodDecorator & ClassDecorator;
|
|
43
|
+
/**
|
|
44
|
+
* Alias for `@Transactional({ adapterInstance })`. Targets a specific
|
|
45
|
+
* adapter instance, for multi-datasource setups:
|
|
46
|
+
*
|
|
47
|
+
* ```ts
|
|
48
|
+
* @TransactionalOn('billing')
|
|
49
|
+
* async issueInvoice() { ... }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* The `adapterInstance` argument overrides any `adapterInstance` set in the
|
|
53
|
+
* options object.
|
|
54
|
+
*/
|
|
55
|
+
export declare const TransactionalOn: (adapterInstance: string, options?: Partial<TransactionalMetadata>) => MethodDecorator & ClassDecorator;
|
|
56
|
+
/**
|
|
57
|
+
* Read the {@link TransactionalMetadata} stored by {@link Transactional} on
|
|
58
|
+
* `target`. Returns `undefined` when the target was not decorated.
|
|
59
|
+
*
|
|
60
|
+
* @param target - A class constructor (for class-level metadata) or a
|
|
61
|
+
* method function (for method-level metadata).
|
|
62
|
+
*/
|
|
63
|
+
export declare function getTransactionalMetadata(target: object): TransactionalMetadata | undefined;
|
|
64
|
+
//# sourceMappingURL=transactional.decorator.d.ts.map
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TransactionalOn = exports.ReadOnly = exports.TRANSACTIONAL_METADATA = void 0;
|
|
4
|
+
exports.Transactional = Transactional;
|
|
5
|
+
exports.getTransactionalMetadata = getTransactionalMetadata;
|
|
6
|
+
const propagation_1 = require("../types/propagation");
|
|
7
|
+
/**
|
|
8
|
+
* Metadata key under which {@link Transactional} stores its options on a
|
|
9
|
+
* target (a method's function object or a class constructor). Exposed for
|
|
10
|
+
* advanced introspection; most code should use
|
|
11
|
+
* {@link getTransactionalMetadata}.
|
|
12
|
+
*/
|
|
13
|
+
exports.TRANSACTIONAL_METADATA = Symbol('TRANSACTIONAL_METADATA');
|
|
14
|
+
/**
|
|
15
|
+
* Mark a method or a class as transactional.
|
|
16
|
+
*
|
|
17
|
+
* **Metadata-only**: this decorator does NOT wrap the method at decoration
|
|
18
|
+
* time. The actual wrapping is performed at runtime by the three coordinated
|
|
19
|
+
* mechanisms described in ADR-005 — `TransactionalInterceptor` for
|
|
20
|
+
* request-boundary handlers, `TransactionalMethodsBootstrap` for regular
|
|
21
|
+
* `@Injectable` providers, and `CqrsHandlerWrapper` for CQRS handlers.
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
* - As a method decorator, the metadata is written onto `descriptor.value`
|
|
25
|
+
* (the method function).
|
|
26
|
+
* - As a class decorator, the metadata is written onto the class
|
|
27
|
+
* constructor. Downstream wrapping mechanisms treat every method of the
|
|
28
|
+
* class as transactional with these options (unless a method has its own
|
|
29
|
+
* `@Transactional` which overrides).
|
|
30
|
+
*
|
|
31
|
+
* Default propagation is {@link PropagationMode.REQUIRED}.
|
|
32
|
+
*/
|
|
33
|
+
function Transactional(options = {}) {
|
|
34
|
+
const metadata = {
|
|
35
|
+
propagation: propagation_1.PropagationMode.REQUIRED,
|
|
36
|
+
...options,
|
|
37
|
+
};
|
|
38
|
+
const decorator = (target, _propertyKey, descriptor) => {
|
|
39
|
+
const methodTarget = descriptor?.value;
|
|
40
|
+
if (typeof methodTarget === 'function') {
|
|
41
|
+
Reflect.defineMetadata(exports.TRANSACTIONAL_METADATA, metadata, methodTarget);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
Reflect.defineMetadata(exports.TRANSACTIONAL_METADATA, metadata, target);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return decorator;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Alias for `@Transactional({ readOnly: true })`. Use on query methods that
|
|
51
|
+
* must not mutate state. Options are applied first and the `readOnly: true`
|
|
52
|
+
* flag is overlaid on top, so callers cannot turn it off from here — use
|
|
53
|
+
* `@Transactional` directly if that is the intent.
|
|
54
|
+
*/
|
|
55
|
+
const ReadOnly = (options = {}) => Transactional({ ...options, readOnly: true });
|
|
56
|
+
exports.ReadOnly = ReadOnly;
|
|
57
|
+
/**
|
|
58
|
+
* Alias for `@Transactional({ adapterInstance })`. Targets a specific
|
|
59
|
+
* adapter instance, for multi-datasource setups:
|
|
60
|
+
*
|
|
61
|
+
* ```ts
|
|
62
|
+
* @TransactionalOn('billing')
|
|
63
|
+
* async issueInvoice() { ... }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* The `adapterInstance` argument overrides any `adapterInstance` set in the
|
|
67
|
+
* options object.
|
|
68
|
+
*/
|
|
69
|
+
const TransactionalOn = (adapterInstance, options = {}) => Transactional({ ...options, adapterInstance });
|
|
70
|
+
exports.TransactionalOn = TransactionalOn;
|
|
71
|
+
/**
|
|
72
|
+
* Read the {@link TransactionalMetadata} stored by {@link Transactional} on
|
|
73
|
+
* `target`. Returns `undefined` when the target was not decorated.
|
|
74
|
+
*
|
|
75
|
+
* @param target - A class constructor (for class-level metadata) or a
|
|
76
|
+
* method function (for method-level metadata).
|
|
77
|
+
*/
|
|
78
|
+
function getTransactionalMetadata(target) {
|
|
79
|
+
const value = Reflect.getMetadata(exports.TRANSACTIONAL_METADATA, target);
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=transactional.decorator.js.map
|
|
@@ -0,0 +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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from './types/propagation';
|
|
2
|
+
export * from './types/isolation';
|
|
3
|
+
export * from './types/transaction-handle';
|
|
4
|
+
export * from './types/transaction-options';
|
|
5
|
+
export * from './types/transaction-adapter';
|
|
6
|
+
export * from './types/domain-event';
|
|
7
|
+
export * from './types/errors';
|
|
8
|
+
export * from './context/transaction.context';
|
|
9
|
+
export * from './context/transaction-context-view';
|
|
10
|
+
export * from './manager/adapter.registry';
|
|
11
|
+
export * from './manager/transaction.manager';
|
|
12
|
+
export * from './decorators/transactional.decorator';
|
|
13
|
+
export * from './decorators/inject-decorators';
|
|
14
|
+
export * from './tokens';
|
|
15
|
+
export * from './interceptor/transactional.interceptor';
|
|
16
|
+
export * from './bootstrap/transactional-methods.bootstrap';
|
|
17
|
+
export * from './module/transactional.module';
|
|
18
|
+
export * from './observability/transaction-observer';
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./types/propagation"), exports);
|
|
18
|
+
__exportStar(require("./types/isolation"), exports);
|
|
19
|
+
__exportStar(require("./types/transaction-handle"), exports);
|
|
20
|
+
__exportStar(require("./types/transaction-options"), exports);
|
|
21
|
+
__exportStar(require("./types/transaction-adapter"), exports);
|
|
22
|
+
__exportStar(require("./types/domain-event"), exports);
|
|
23
|
+
__exportStar(require("./types/errors"), exports);
|
|
24
|
+
__exportStar(require("./context/transaction.context"), exports);
|
|
25
|
+
__exportStar(require("./context/transaction-context-view"), exports);
|
|
26
|
+
__exportStar(require("./manager/adapter.registry"), exports);
|
|
27
|
+
__exportStar(require("./manager/transaction.manager"), exports);
|
|
28
|
+
__exportStar(require("./decorators/transactional.decorator"), exports);
|
|
29
|
+
__exportStar(require("./decorators/inject-decorators"), exports);
|
|
30
|
+
__exportStar(require("./tokens"), exports);
|
|
31
|
+
__exportStar(require("./interceptor/transactional.interceptor"), exports);
|
|
32
|
+
__exportStar(require("./bootstrap/transactional-methods.bootstrap"), exports);
|
|
33
|
+
__exportStar(require("./module/transactional.module"), exports);
|
|
34
|
+
__exportStar(require("./observability/transaction-observer"), exports);
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,sDAAoC;AACpC,oDAAkC;AAClC,6DAA2C;AAC3C,8DAA4C;AAC5C,8DAA4C;AAC5C,uDAAqC;AACrC,iDAA+B;AAE/B,gEAA8C;AAC9C,qEAAmD;AACnD,6DAA2C;AAC3C,gEAA8C;AAE9C,uEAAqD;AACrD,iEAA+C;AAE/C,2CAAyB;AAEzB,0EAAwD;AACxD,8EAA4D;AAC5D,gEAA8C;AAE9C,uEAAqD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type CallHandler, type ExecutionContext, type NestInterceptor } from '@nestjs/common';
|
|
2
|
+
import { Reflector } from '@nestjs/core';
|
|
3
|
+
import { type Observable } from 'rxjs';
|
|
4
|
+
import { TransactionManager } from '../manager/transaction.manager';
|
|
5
|
+
/**
|
|
6
|
+
* NestJS interceptor that wraps a request-boundary handler in a transaction
|
|
7
|
+
* when the handler (or its controller class) carries `@Transactional()`
|
|
8
|
+
* metadata.
|
|
9
|
+
*
|
|
10
|
+
* Registered at the request boundary via `APP_INTERCEPTOR`. It is one of
|
|
11
|
+
* the three coordinated wrapping mechanisms described in ADR-005 — the
|
|
12
|
+
* other two are `TransactionalMethodsBootstrap` (for plain `@Injectable`
|
|
13
|
+
* services) and `CqrsHandlerWrapper` (for CQRS handlers).
|
|
14
|
+
*
|
|
15
|
+
* Metadata lookup: method-level `@Transactional` overrides class-level.
|
|
16
|
+
* If neither is present the handler is passed through without any
|
|
17
|
+
* transactional wrapping.
|
|
18
|
+
*
|
|
19
|
+
* Not exported from the package's public API — consumers enable it via
|
|
20
|
+
* `TransactionalModule.forRoot`.
|
|
21
|
+
*/
|
|
22
|
+
export declare class TransactionalInterceptor implements NestInterceptor {
|
|
23
|
+
private readonly manager;
|
|
24
|
+
private readonly reflector;
|
|
25
|
+
constructor(manager: TransactionManager, reflector: Reflector);
|
|
26
|
+
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=transactional.interceptor.d.ts.map
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.TransactionalInterceptor = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const core_1 = require("@nestjs/core");
|
|
15
|
+
const rxjs_1 = require("rxjs");
|
|
16
|
+
const transactional_decorator_1 = require("../decorators/transactional.decorator");
|
|
17
|
+
const transaction_manager_1 = require("../manager/transaction.manager");
|
|
18
|
+
/**
|
|
19
|
+
* NestJS interceptor that wraps a request-boundary handler in a transaction
|
|
20
|
+
* when the handler (or its controller class) carries `@Transactional()`
|
|
21
|
+
* metadata.
|
|
22
|
+
*
|
|
23
|
+
* Registered at the request boundary via `APP_INTERCEPTOR`. It is one of
|
|
24
|
+
* the three coordinated wrapping mechanisms described in ADR-005 — the
|
|
25
|
+
* other two are `TransactionalMethodsBootstrap` (for plain `@Injectable`
|
|
26
|
+
* services) and `CqrsHandlerWrapper` (for CQRS handlers).
|
|
27
|
+
*
|
|
28
|
+
* Metadata lookup: method-level `@Transactional` overrides class-level.
|
|
29
|
+
* If neither is present the handler is passed through without any
|
|
30
|
+
* transactional wrapping.
|
|
31
|
+
*
|
|
32
|
+
* Not exported from the package's public API — consumers enable it via
|
|
33
|
+
* `TransactionalModule.forRoot`.
|
|
34
|
+
*/
|
|
35
|
+
let TransactionalInterceptor = class TransactionalInterceptor {
|
|
36
|
+
manager;
|
|
37
|
+
reflector;
|
|
38
|
+
constructor(manager, reflector) {
|
|
39
|
+
this.manager = manager;
|
|
40
|
+
this.reflector = reflector;
|
|
41
|
+
}
|
|
42
|
+
intercept(context, next) {
|
|
43
|
+
const metadata = this.reflector.getAllAndOverride(transactional_decorator_1.TRANSACTIONAL_METADATA, [context.getHandler(), context.getClass()]);
|
|
44
|
+
if (metadata === undefined) {
|
|
45
|
+
return next.handle();
|
|
46
|
+
}
|
|
47
|
+
return (0, rxjs_1.defer)(() => this.manager.run(metadata, () => (0, rxjs_1.firstValueFrom)(next.handle())));
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
exports.TransactionalInterceptor = TransactionalInterceptor;
|
|
51
|
+
exports.TransactionalInterceptor = TransactionalInterceptor = __decorate([
|
|
52
|
+
(0, common_1.Injectable)(),
|
|
53
|
+
__metadata("design:paramtypes", [transaction_manager_1.TransactionManager,
|
|
54
|
+
core_1.Reflector])
|
|
55
|
+
], TransactionalInterceptor);
|
|
56
|
+
//# sourceMappingURL=transactional.interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactional.interceptor.js","sourceRoot":"","sources":["../../src/interceptor/transactional.interceptor.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAKwB;AACxB,uCAAyC;AACzC,+BAA8D;AAE9D,mFAG+C;AAC/C,wEAAoE;AAEpE;;;;;;;;;;;;;;;;GAgBG;AAEI,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IAEhB;IACA;IAFnB,YACmB,OAA2B,EAC3B,SAAoB;QADpB,YAAO,GAAP,OAAO,CAAoB;QAC3B,cAAS,GAAT,SAAS,CAAW;IACpC,CAAC;IAEJ,SAAS,CAAC,OAAyB,EAAE,IAAiB;QACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAC/C,gDAAsB,EACtB,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAC3C,CAAC;QAEF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC;QAED,OAAO,IAAA,YAAK,EAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAA,qBAAc,EAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC;CACF,CAAA;AAlBY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,mBAAU,GAAE;qCAGiB,wCAAkB;QAChB,gBAAS;GAH5B,wBAAwB,CAkBpC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity marker placed via `Reflect.defineMetadata` on methods that have
|
|
3
|
+
* been wrapped by one of the coordinated wrapping mechanisms described in
|
|
4
|
+
* ADR-005 (`TransactionalInterceptor`, `TransactionalMethodsBootstrap`,
|
|
5
|
+
* and `CqrsHandlerWrapper`). Each mechanism checks this marker before
|
|
6
|
+
* wrapping so a method is never wrapped twice.
|
|
7
|
+
*
|
|
8
|
+
* `Symbol.for` gives a process-global symbol, so multiple copies of this
|
|
9
|
+
* package in the same dependency tree still resolve to the same identity.
|
|
10
|
+
*
|
|
11
|
+
* Internal: not re-exported from the public API. The three wrapping
|
|
12
|
+
* mechanisms are the only legitimate users.
|
|
13
|
+
*/
|
|
14
|
+
export declare const WRAPPED_MARKER: unique symbol;
|
|
15
|
+
//# sourceMappingURL=markers.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WRAPPED_MARKER = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Identity marker placed via `Reflect.defineMetadata` on methods that have
|
|
6
|
+
* been wrapped by one of the coordinated wrapping mechanisms described in
|
|
7
|
+
* ADR-005 (`TransactionalInterceptor`, `TransactionalMethodsBootstrap`,
|
|
8
|
+
* and `CqrsHandlerWrapper`). Each mechanism checks this marker before
|
|
9
|
+
* wrapping so a method is never wrapped twice.
|
|
10
|
+
*
|
|
11
|
+
* `Symbol.for` gives a process-global symbol, so multiple copies of this
|
|
12
|
+
* package in the same dependency tree still resolve to the same identity.
|
|
13
|
+
*
|
|
14
|
+
* Internal: not re-exported from the public API. The three wrapping
|
|
15
|
+
* mechanisms are the only legitimate users.
|
|
16
|
+
*/
|
|
17
|
+
exports.WRAPPED_MARKER = Symbol.for('@nestjs-transactional/wrapped');
|
|
18
|
+
//# sourceMappingURL=markers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markers.js","sourceRoot":"","sources":["../../src/internal/markers.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;GAYG;AACU,QAAA,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { TransactionAdapter } from '../types/transaction-adapter';
|
|
2
|
+
/**
|
|
3
|
+
* A single entry in the {@link AdapterRegistry}: an adapter instance bound to
|
|
4
|
+
* its type name and instance name. Used as both the input shape of
|
|
5
|
+
* {@link AdapterRegistry.register} and the element shape returned by
|
|
6
|
+
* {@link AdapterRegistry.getAll}.
|
|
7
|
+
*/
|
|
8
|
+
export interface AdapterRegistration {
|
|
9
|
+
/** Adapter type name, e.g. `'typeorm'`, `'prisma'`. */
|
|
10
|
+
readonly adapterName: string;
|
|
11
|
+
/** Instance name within the adapter type, e.g. `'primary'`, `'billing'`. */
|
|
12
|
+
readonly instanceName: string;
|
|
13
|
+
/** The adapter implementation registered under this (adapterName, instanceName) pair. */
|
|
14
|
+
readonly adapter: TransactionAdapter;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* DI token for the {@link AdapterRegistry}. Consumers who need to register
|
|
18
|
+
* adapters manually (for example, integration tests or custom modules)
|
|
19
|
+
* can inject this token and call {@link AdapterRegistry.register}.
|
|
20
|
+
*/
|
|
21
|
+
export declare const ADAPTER_REGISTRY: unique symbol;
|
|
22
|
+
/**
|
|
23
|
+
* In-memory registry of {@link TransactionAdapter} instances, keyed by
|
|
24
|
+
* `(adapterName, instanceName)`. Each adapter type (e.g. `'typeorm'`) may
|
|
25
|
+
* have multiple instances (e.g. `'primary'`, `'billing'`) — the registry
|
|
26
|
+
* keeps them separate so that `@Transactional({ adapterInstance: 'billing' })`
|
|
27
|
+
* can target a specific one.
|
|
28
|
+
*
|
|
29
|
+
* The first adapter registered becomes the default; any later registration
|
|
30
|
+
* can override the default by passing `isDefault = true`.
|
|
31
|
+
*
|
|
32
|
+
* Implementation note: the internal key format is `${adapterName}:${instanceName}`.
|
|
33
|
+
* Neither `adapterName` nor `instanceName` may contain `:` — enforced by
|
|
34
|
+
* convention, not at runtime.
|
|
35
|
+
*/
|
|
36
|
+
export declare class AdapterRegistry {
|
|
37
|
+
private readonly adapters;
|
|
38
|
+
private defaultAdapterName;
|
|
39
|
+
private defaultInstanceName;
|
|
40
|
+
/**
|
|
41
|
+
* Register an adapter under `(registration.adapterName, registration.instanceName)`.
|
|
42
|
+
*
|
|
43
|
+
* The first registration always becomes the default. Passing
|
|
44
|
+
* `isDefault = true` on any later registration switches the default to it.
|
|
45
|
+
*
|
|
46
|
+
* Re-registering the same pair overwrites the previously stored adapter;
|
|
47
|
+
* the default pointer is left unchanged unless `isDefault = true` is set.
|
|
48
|
+
*/
|
|
49
|
+
register(registration: AdapterRegistration, isDefault?: boolean): void;
|
|
50
|
+
/**
|
|
51
|
+
* Look up an adapter by `(adapterName, instanceName)`.
|
|
52
|
+
*
|
|
53
|
+
* @throws {TransactionAdapterNotFoundError} If no adapter is registered
|
|
54
|
+
* under that pair.
|
|
55
|
+
*/
|
|
56
|
+
get(adapterName: string, instanceName: string): TransactionAdapter;
|
|
57
|
+
/**
|
|
58
|
+
* Look up an adapter by its public dataSource name (DD-020). Iterates
|
|
59
|
+
* the registered entries and returns the one whose `instanceName`
|
|
60
|
+
* matches `dataSource` — there is exactly one per dataSource by
|
|
61
|
+
* convention.
|
|
62
|
+
*
|
|
63
|
+
* If multiple registrations share the same `instanceName` across
|
|
64
|
+
* different adapter types (e.g. `typeorm:billing` AND
|
|
65
|
+
* `prisma:billing`), throws — that configuration is ambiguous and
|
|
66
|
+
* the user must disambiguate via the `adapter` + `adapterInstance`
|
|
67
|
+
* options instead.
|
|
68
|
+
*
|
|
69
|
+
* @throws {IllegalTransactionStateError} If two or more adapters share
|
|
70
|
+
* the same dataSource name.
|
|
71
|
+
* @throws {TransactionAdapterNotFoundError} If no adapter is registered
|
|
72
|
+
* under this dataSource.
|
|
73
|
+
*/
|
|
74
|
+
getByDataSource(dataSource: string): TransactionAdapter;
|
|
75
|
+
/**
|
|
76
|
+
* Find the adapter type name (`'typeorm'`, `'prisma'`, ...) registered
|
|
77
|
+
* under the given dataSource. Used by the manager to compose the
|
|
78
|
+
* composite Map key when only the dataSource name is known.
|
|
79
|
+
*
|
|
80
|
+
* Same disambiguation rules as {@link getByDataSource}.
|
|
81
|
+
*/
|
|
82
|
+
getAdapterNameByDataSource(dataSource: string): string;
|
|
83
|
+
/**
|
|
84
|
+
* Return the name of the adapter type currently marked default.
|
|
85
|
+
*
|
|
86
|
+
* @throws {IllegalTransactionStateError} If no adapter has been registered
|
|
87
|
+
* yet — there is no default to choose.
|
|
88
|
+
*/
|
|
89
|
+
getDefaultAdapterName(): string;
|
|
90
|
+
/**
|
|
91
|
+
* Return the name of the default adapter instance. Defaults to `'default'`
|
|
92
|
+
* before any adapter is registered — matches the common convention in
|
|
93
|
+
* per-ORM `forFeature({ instanceName: 'default' })` helpers.
|
|
94
|
+
*/
|
|
95
|
+
getDefaultInstanceName(): string;
|
|
96
|
+
/**
|
|
97
|
+
* Return every registration as a new array. Used by bootstrap and
|
|
98
|
+
* observability code to enumerate configured adapters at runtime.
|
|
99
|
+
*/
|
|
100
|
+
getAll(): AdapterRegistration[];
|
|
101
|
+
private static keyFor;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=adapter.registry.d.ts.map
|