@nestjs-transactional/typeorm 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 +361 -0
- package/dist/adapter/typeorm.adapter.d.ts +39 -0
- package/dist/adapter/typeorm.adapter.js +79 -0
- package/dist/adapter/typeorm.adapter.js.map +1 -0
- package/dist/helpers/get-entity-manager.d.ts +27 -0
- package/dist/helpers/get-entity-manager.js +52 -0
- package/dist/helpers/get-entity-manager.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/module/typeorm-transactional.module.d.ts +157 -0
- package/dist/module/typeorm-transactional.module.js +289 -0
- package/dist/module/typeorm-transactional.module.js.map +1 -0
- package/dist/patching/data-source-patches.d.ts +48 -0
- package/dist/patching/data-source-patches.js +139 -0
- package/dist/patching/data-source-patches.js.map +1 -0
- package/dist/patching/entity-manager-patches.d.ts +31 -0
- package/dist/patching/entity-manager-patches.js +86 -0
- package/dist/patching/entity-manager-patches.js.map +1 -0
- package/dist/patching/index.d.ts +49 -0
- package/dist/patching/index.js +75 -0
- package/dist/patching/index.js.map +1 -0
- package/dist/patching/managed-registry.d.ts +59 -0
- package/dist/patching/managed-registry.js +112 -0
- package/dist/patching/managed-registry.js.map +1 -0
- package/dist/patching/repository-patches.d.ts +56 -0
- package/dist/patching/repository-patches.js +150 -0
- package/dist/patching/repository-patches.js.map +1 -0
- package/dist/patching/symbols.d.ts +53 -0
- package/dist/patching/symbols.js +56 -0
- package/dist/patching/symbols.js.map +1 -0
- package/dist/types/typeorm-transaction-handle.d.ts +17 -0
- package/dist/types/typeorm-transaction-handle.js +3 -0
- package/dist/types/typeorm-transaction-handle.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { type DynamicModule, type InjectionToken, type ModuleMetadata } from '@nestjs/common';
|
|
2
|
+
/**
|
|
3
|
+
* Options accepted by {@link TypeOrmTransactionalModule.forRoot}.
|
|
4
|
+
*
|
|
5
|
+
* Phase 14.20 reshape: this module now resolves the actual TypeORM
|
|
6
|
+
* `DataSource` via DI (using `getDataSourceToken` from
|
|
7
|
+
* `@nestjs/typeorm`) instead of taking it as a constructor argument.
|
|
8
|
+
* The new contract is "TypeORM is configured by `@nestjs/typeorm`'s
|
|
9
|
+
* `TypeOrmModule.forRoot(...)`; we just bind to it by name."
|
|
10
|
+
*/
|
|
11
|
+
export interface TypeOrmTransactionalOptions {
|
|
12
|
+
/**
|
|
13
|
+
* DataSource name as used by `@nestjs/typeorm`'s
|
|
14
|
+
* `TypeOrmModule.forRoot({ name })`. Defaults to `'default'`. The
|
|
15
|
+
* actual `DataSource` instance is resolved from DI under
|
|
16
|
+
* `getDataSourceToken(this.dataSource)`.
|
|
17
|
+
*/
|
|
18
|
+
readonly dataSource?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Mark this adapter as the registry-level default. Affects
|
|
21
|
+
* `@Transactional()` calls that omit the `dataSource` option.
|
|
22
|
+
* Defaults to `false`; the first registered adapter becomes the
|
|
23
|
+
* default automatically (per {@link AdapterRegistry.register}).
|
|
24
|
+
*/
|
|
25
|
+
readonly isDefault?: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Asynchronous flavour of {@link TypeOrmTransactionalOptions}.
|
|
29
|
+
*
|
|
30
|
+
* **Per-DS DI token limitation**: the per-dataSource adapter token
|
|
31
|
+
* (`getTransactionalAdapterToken(ds)`) is NOT registered for
|
|
32
|
+
* `forRootAsync` because the dataSource name is only known after
|
|
33
|
+
* the async factory runs, while NestJS provider tokens must be
|
|
34
|
+
* declared statically. If per-DS injection of the adapter matters,
|
|
35
|
+
* use sync `forRoot({ dataSource })` instead. The
|
|
36
|
+
* `AdapterRegistry`-based access path
|
|
37
|
+
* (`@Transactional({ dataSource })`,
|
|
38
|
+
* `getCurrentEntityManager(dataSource)`,
|
|
39
|
+
* `manager.run({ dataSource })`) is unaffected — those route
|
|
40
|
+
* through the registry, which the eager-registration factory
|
|
41
|
+
* populates as a side effect.
|
|
42
|
+
*
|
|
43
|
+
* Mirrors the documented limitation on
|
|
44
|
+
* `TransactionalModule.forRootAsync` (Phase 14.10).
|
|
45
|
+
*/
|
|
46
|
+
export interface TypeOrmTransactionalAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
|
|
47
|
+
readonly useFactory: (...args: never[]) => Promise<TypeOrmTransactionalOptions> | TypeOrmTransactionalOptions;
|
|
48
|
+
readonly inject?: readonly InjectionToken[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* NestJS module that binds a TypeORM {@link DataSource} to the core
|
|
52
|
+
* {@link AdapterRegistry} as a transactional adapter AND activates
|
|
53
|
+
* the transparent transactional patching machinery (Phase 14.20).
|
|
54
|
+
* Once registered:
|
|
55
|
+
*
|
|
56
|
+
* - Every `Repository` reachable via `@InjectRepository`,
|
|
57
|
+
* `dataSource.getRepository(...)`, `entityManager.getRepository(...)`,
|
|
58
|
+
* or `repo.extend(...)` automatically dispatches inside the active
|
|
59
|
+
* `@Transactional()` scope.
|
|
60
|
+
* - `dataSource.query(...)` and `dataSource.createQueryBuilder(...)`
|
|
61
|
+
* pick up the transactional `QueryRunner`.
|
|
62
|
+
* - `@InjectEntityManager() em.getRepository(E).save(...)` works
|
|
63
|
+
* transactionally (the wrapped `EntityManager.prototype.getRepository`
|
|
64
|
+
* stamps the manager reference). Direct
|
|
65
|
+
* `@InjectEntityManager() em.save(E, ...)` is a documented
|
|
66
|
+
* limitation — use the Repository pattern or
|
|
67
|
+
* `getCurrentEntityManager()` as escape hatch.
|
|
68
|
+
*
|
|
69
|
+
* Multi-dataSource deployments call {@link forRoot} once per
|
|
70
|
+
* dataSource (mirrors `OutboxModule` per ADR-019 and
|
|
71
|
+
* `TransactionalModule` per ADR-018):
|
|
72
|
+
*
|
|
73
|
+
* ```ts
|
|
74
|
+
* @Module({
|
|
75
|
+
* imports: [
|
|
76
|
+
* TypeOrmModule.forRoot({ type: 'postgres', ... }),
|
|
77
|
+
* TypeOrmModule.forRoot({ type: 'postgres', name: 'billing', ... }),
|
|
78
|
+
*
|
|
79
|
+
* TransactionalModule.forRoot({}), // infra
|
|
80
|
+
* TypeOrmTransactionalModule.forRoot(), // default
|
|
81
|
+
* TypeOrmTransactionalModule.forRoot({ dataSource: 'billing' }),
|
|
82
|
+
* ],
|
|
83
|
+
* })
|
|
84
|
+
* export class AppModule {}
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* Patches are applied process-wide on the first `forRoot`/`forRootAsync`
|
|
88
|
+
* call (idempotent on re-entry). DataSource instances are tracked in
|
|
89
|
+
* a `WeakSet`; non-managed DataSources are never touched by the
|
|
90
|
+
* patches — they continue to behave as TypeORM does normally.
|
|
91
|
+
*/
|
|
92
|
+
export declare class TypeOrmTransactionalModule {
|
|
93
|
+
/**
|
|
94
|
+
* @internal
|
|
95
|
+
* Counter for `forRootAsync`-only token uniqueness. Mirrors the
|
|
96
|
+
* pattern used in `TransactionalModule.forRootAsync` — every
|
|
97
|
+
* async call gets a unique provider symbol so consecutive calls
|
|
98
|
+
* don't collide.
|
|
99
|
+
*/
|
|
100
|
+
private static asyncCounter;
|
|
101
|
+
/**
|
|
102
|
+
* Test-only — drop the managed-DataSources `WeakSet` so cached
|
|
103
|
+
* repositories from a prior test fall through to their original
|
|
104
|
+
* (autocommit) manager. Prototype-level patches are NOT removed;
|
|
105
|
+
* they were installed once-and-stay, by design (see
|
|
106
|
+
* `repository-patches.ts` JSDoc). Per-instance `DataSource`
|
|
107
|
+
* patches survive on those `DataSource` instances — tests that
|
|
108
|
+
* destroy and recreate the `DataSource` between cases (the
|
|
109
|
+
* typical pattern) are unaffected.
|
|
110
|
+
*
|
|
111
|
+
* Re-registering the SAME `DataSource` after a reset is safe:
|
|
112
|
+
* `patchDataSourceInstance` is idempotent via a marker symbol,
|
|
113
|
+
* and `markAsManaged` re-stamps the same name harmlessly.
|
|
114
|
+
*
|
|
115
|
+
* Production code should never call this.
|
|
116
|
+
*
|
|
117
|
+
* @internal
|
|
118
|
+
*/
|
|
119
|
+
static resetForTesting(): void;
|
|
120
|
+
/**
|
|
121
|
+
* Synchronous registration. Each call binds one DataSource (by
|
|
122
|
+
* name) to the transactional infrastructure. Patches are
|
|
123
|
+
* activated idempotently on the first call.
|
|
124
|
+
*
|
|
125
|
+
* @example Default DataSource
|
|
126
|
+
* ```ts
|
|
127
|
+
* TypeOrmTransactionalModule.forRoot()
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @example Named DataSource
|
|
131
|
+
* ```ts
|
|
132
|
+
* TypeOrmTransactionalModule.forRoot({ dataSource: 'billing' })
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
static forRoot(options?: TypeOrmTransactionalOptions): DynamicModule;
|
|
136
|
+
/**
|
|
137
|
+
* Asynchronous registration. Resolves
|
|
138
|
+
* {@link TypeOrmTransactionalOptions} via a NestJS-style async
|
|
139
|
+
* factory before binding the adapter. See
|
|
140
|
+
* {@link TypeOrmTransactionalAsyncOptions} for the per-DS-token
|
|
141
|
+
* limitation.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```ts
|
|
145
|
+
* TypeOrmTransactionalModule.forRootAsync({
|
|
146
|
+
* imports: [ConfigModule],
|
|
147
|
+
* inject: [ConfigService],
|
|
148
|
+
* useFactory: (cfg: ConfigService) => ({
|
|
149
|
+
* dataSource: cfg.get('DATA_SOURCE_NAME'),
|
|
150
|
+
* isDefault: true,
|
|
151
|
+
* }),
|
|
152
|
+
* });
|
|
153
|
+
* ```
|
|
154
|
+
*/
|
|
155
|
+
static forRootAsync(options: TypeOrmTransactionalAsyncOptions): DynamicModule;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=typeorm-transactional.module.d.ts.map
|
|
@@ -0,0 +1,289 @@
|
|
|
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
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var TypeOrmTransactionalModule_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.TypeOrmTransactionalModule = void 0;
|
|
17
|
+
const common_1 = require("@nestjs/common");
|
|
18
|
+
const core_1 = require("@nestjs/core");
|
|
19
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
20
|
+
const core_2 = require("@nestjs-transactional/core");
|
|
21
|
+
const typeorm_adapter_1 = require("../adapter/typeorm.adapter");
|
|
22
|
+
const patching_1 = require("../patching");
|
|
23
|
+
// ---------------------------------------------------------------
|
|
24
|
+
// Apply Repository / EntityManager prototype patches at MODULE-LOAD
|
|
25
|
+
// time, NOT at `forRoot` factory time.
|
|
26
|
+
//
|
|
27
|
+
// Why module-load: NestJS resolves providers in dependency order
|
|
28
|
+
// during `compile()`. A `useFactory` provider that calls
|
|
29
|
+
// `dataSource.getRepository(Entity)` (e.g. `@InjectRepository`'s
|
|
30
|
+
// internal factory) runs BEFORE `TypeOrmTransactionalModule.forRoot`'s
|
|
31
|
+
// factory if it has no DI dependency on the latter. A Repository
|
|
32
|
+
// constructed before the patches are installed gets its
|
|
33
|
+
// `this.manager = manager` assignment as an own-property, which
|
|
34
|
+
// permanently shadows the prototype getter — that Repository
|
|
35
|
+
// instance can never dispatch through the active transactional
|
|
36
|
+
// EntityManager.
|
|
37
|
+
//
|
|
38
|
+
// Installing the patches as a side effect of importing this file
|
|
39
|
+
// guarantees they're in place before any DI factory could ever
|
|
40
|
+
// observe an unpatched `Repository.prototype`. Idempotent: a second
|
|
41
|
+
// import (e.g. a stale duplicate copy on disk under pnpm hoist
|
|
42
|
+
// glitches) is a no-op via the install-once flag inside each patch.
|
|
43
|
+
// ---------------------------------------------------------------
|
|
44
|
+
(0, patching_1.applyAllPatches)();
|
|
45
|
+
const ASYNC_OPTIONS_TOKEN = (id) => Symbol(`TYPEORM_TRANSACTIONAL_ASYNC_OPTIONS[${id}]`);
|
|
46
|
+
/**
|
|
47
|
+
* NestJS module that binds a TypeORM {@link DataSource} to the core
|
|
48
|
+
* {@link AdapterRegistry} as a transactional adapter AND activates
|
|
49
|
+
* the transparent transactional patching machinery (Phase 14.20).
|
|
50
|
+
* Once registered:
|
|
51
|
+
*
|
|
52
|
+
* - Every `Repository` reachable via `@InjectRepository`,
|
|
53
|
+
* `dataSource.getRepository(...)`, `entityManager.getRepository(...)`,
|
|
54
|
+
* or `repo.extend(...)` automatically dispatches inside the active
|
|
55
|
+
* `@Transactional()` scope.
|
|
56
|
+
* - `dataSource.query(...)` and `dataSource.createQueryBuilder(...)`
|
|
57
|
+
* pick up the transactional `QueryRunner`.
|
|
58
|
+
* - `@InjectEntityManager() em.getRepository(E).save(...)` works
|
|
59
|
+
* transactionally (the wrapped `EntityManager.prototype.getRepository`
|
|
60
|
+
* stamps the manager reference). Direct
|
|
61
|
+
* `@InjectEntityManager() em.save(E, ...)` is a documented
|
|
62
|
+
* limitation — use the Repository pattern or
|
|
63
|
+
* `getCurrentEntityManager()` as escape hatch.
|
|
64
|
+
*
|
|
65
|
+
* Multi-dataSource deployments call {@link forRoot} once per
|
|
66
|
+
* dataSource (mirrors `OutboxModule` per ADR-019 and
|
|
67
|
+
* `TransactionalModule` per ADR-018):
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* @Module({
|
|
71
|
+
* imports: [
|
|
72
|
+
* TypeOrmModule.forRoot({ type: 'postgres', ... }),
|
|
73
|
+
* TypeOrmModule.forRoot({ type: 'postgres', name: 'billing', ... }),
|
|
74
|
+
*
|
|
75
|
+
* TransactionalModule.forRoot({}), // infra
|
|
76
|
+
* TypeOrmTransactionalModule.forRoot(), // default
|
|
77
|
+
* TypeOrmTransactionalModule.forRoot({ dataSource: 'billing' }),
|
|
78
|
+
* ],
|
|
79
|
+
* })
|
|
80
|
+
* export class AppModule {}
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* Patches are applied process-wide on the first `forRoot`/`forRootAsync`
|
|
84
|
+
* call (idempotent on re-entry). DataSource instances are tracked in
|
|
85
|
+
* a `WeakSet`; non-managed DataSources are never touched by the
|
|
86
|
+
* patches — they continue to behave as TypeORM does normally.
|
|
87
|
+
*/
|
|
88
|
+
let TypeOrmTransactionalModule = class TypeOrmTransactionalModule {
|
|
89
|
+
static { TypeOrmTransactionalModule_1 = this; }
|
|
90
|
+
/**
|
|
91
|
+
* @internal
|
|
92
|
+
* Counter for `forRootAsync`-only token uniqueness. Mirrors the
|
|
93
|
+
* pattern used in `TransactionalModule.forRootAsync` — every
|
|
94
|
+
* async call gets a unique provider symbol so consecutive calls
|
|
95
|
+
* don't collide.
|
|
96
|
+
*/
|
|
97
|
+
static asyncCounter = 0;
|
|
98
|
+
/**
|
|
99
|
+
* Test-only — drop the managed-DataSources `WeakSet` so cached
|
|
100
|
+
* repositories from a prior test fall through to their original
|
|
101
|
+
* (autocommit) manager. Prototype-level patches are NOT removed;
|
|
102
|
+
* they were installed once-and-stay, by design (see
|
|
103
|
+
* `repository-patches.ts` JSDoc). Per-instance `DataSource`
|
|
104
|
+
* patches survive on those `DataSource` instances — tests that
|
|
105
|
+
* destroy and recreate the `DataSource` between cases (the
|
|
106
|
+
* typical pattern) are unaffected.
|
|
107
|
+
*
|
|
108
|
+
* Re-registering the SAME `DataSource` after a reset is safe:
|
|
109
|
+
* `patchDataSourceInstance` is idempotent via a marker symbol,
|
|
110
|
+
* and `markAsManaged` re-stamps the same name harmlessly.
|
|
111
|
+
*
|
|
112
|
+
* Production code should never call this.
|
|
113
|
+
*
|
|
114
|
+
* @internal
|
|
115
|
+
*/
|
|
116
|
+
static resetForTesting() {
|
|
117
|
+
(0, patching_1.resetPatchingForTesting)();
|
|
118
|
+
this.asyncCounter = 0;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Synchronous registration. Each call binds one DataSource (by
|
|
122
|
+
* name) to the transactional infrastructure. Patches are
|
|
123
|
+
* activated idempotently on the first call.
|
|
124
|
+
*
|
|
125
|
+
* @example Default DataSource
|
|
126
|
+
* ```ts
|
|
127
|
+
* TypeOrmTransactionalModule.forRoot()
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @example Named DataSource
|
|
131
|
+
* ```ts
|
|
132
|
+
* TypeOrmTransactionalModule.forRoot({ dataSource: 'billing' })
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
static forRoot(options = {}) {
|
|
136
|
+
const dataSourceName = options.dataSource ?? 'default';
|
|
137
|
+
const dataSourceToken = (0, typeorm_1.getDataSourceToken)(dataSourceName);
|
|
138
|
+
const adapterToken = (0, core_2.getTransactionalAdapterToken)(dataSourceName);
|
|
139
|
+
const adapterProvider = {
|
|
140
|
+
provide: adapterToken,
|
|
141
|
+
useFactory: (ds, registry) => registerManagedDataSource({
|
|
142
|
+
dataSource: ds,
|
|
143
|
+
dataSourceName,
|
|
144
|
+
isDefault: options.isDefault ?? false,
|
|
145
|
+
registry,
|
|
146
|
+
}),
|
|
147
|
+
inject: [dataSourceToken, core_2.ADAPTER_REGISTRY],
|
|
148
|
+
};
|
|
149
|
+
return {
|
|
150
|
+
module: TypeOrmTransactionalModule_1,
|
|
151
|
+
providers: [adapterProvider],
|
|
152
|
+
exports: [adapterToken],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Asynchronous registration. Resolves
|
|
157
|
+
* {@link TypeOrmTransactionalOptions} via a NestJS-style async
|
|
158
|
+
* factory before binding the adapter. See
|
|
159
|
+
* {@link TypeOrmTransactionalAsyncOptions} for the per-DS-token
|
|
160
|
+
* limitation.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```ts
|
|
164
|
+
* TypeOrmTransactionalModule.forRootAsync({
|
|
165
|
+
* imports: [ConfigModule],
|
|
166
|
+
* inject: [ConfigService],
|
|
167
|
+
* useFactory: (cfg: ConfigService) => ({
|
|
168
|
+
* dataSource: cfg.get('DATA_SOURCE_NAME'),
|
|
169
|
+
* isDefault: true,
|
|
170
|
+
* }),
|
|
171
|
+
* });
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
static forRootAsync(options) {
|
|
175
|
+
const id = this.asyncCounter++;
|
|
176
|
+
const asyncToken = ASYNC_OPTIONS_TOKEN(id);
|
|
177
|
+
const asyncOptionsProvider = {
|
|
178
|
+
provide: asyncToken,
|
|
179
|
+
useFactory: options.useFactory,
|
|
180
|
+
inject: options.inject ? [...options.inject] : undefined,
|
|
181
|
+
};
|
|
182
|
+
// The DataSource token depends on the async-resolved name, so
|
|
183
|
+
// we cannot put `getDataSourceToken(...)` into the registration
|
|
184
|
+
// provider's `inject` array statically. We also cannot resolve
|
|
185
|
+
// it inside a `useFactory` provider via `ModuleRef` — at the
|
|
186
|
+
// time `useFactory` providers run, NestJS has not yet
|
|
187
|
+
// initialised siblings whose DI dependencies do not point at
|
|
188
|
+
// them, so `@nestjs/typeorm`'s DataSource provider may still be
|
|
189
|
+
// a pending Promise. The historical use of `moduleRef.resolve`
|
|
190
|
+
// (or even `moduleRef.get`) cascaded into a hard-to-diagnose
|
|
191
|
+
// `Invalid value used in weak set` followed by
|
|
192
|
+
// `this.postgres.Pool is not a constructor` when paired with
|
|
193
|
+
// `TypeOrmModule.forRootAsync` (Phase 14.8e Convention #22).
|
|
194
|
+
//
|
|
195
|
+
// The robust pattern is `OnModuleInit`: by the time the hook
|
|
196
|
+
// runs, every provider in the module tree has been instantiated
|
|
197
|
+
// (including async DataSource factories from `@nestjs/typeorm`).
|
|
198
|
+
// `moduleRef.get(...)` then returns the real DataSource
|
|
199
|
+
// instance, and `registerManagedDataSource` succeeds.
|
|
200
|
+
const RegistrationCls = createAsyncRegistrationClass(id, asyncToken);
|
|
201
|
+
const providers = [asyncOptionsProvider, RegistrationCls];
|
|
202
|
+
return {
|
|
203
|
+
module: TypeOrmTransactionalModule_1,
|
|
204
|
+
imports: options.imports ?? [],
|
|
205
|
+
providers,
|
|
206
|
+
// Nothing exports `registrationToken` for this path — the
|
|
207
|
+
// service runs side-effect-only via OnModuleInit. Export
|
|
208
|
+
// the registration class so consumers wanting explicit
|
|
209
|
+
// ordering can depend on it being initialised.
|
|
210
|
+
exports: [RegistrationCls],
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
exports.TypeOrmTransactionalModule = TypeOrmTransactionalModule;
|
|
215
|
+
exports.TypeOrmTransactionalModule = TypeOrmTransactionalModule = TypeOrmTransactionalModule_1 = __decorate([
|
|
216
|
+
(0, common_1.Module)({})
|
|
217
|
+
], TypeOrmTransactionalModule);
|
|
218
|
+
/**
|
|
219
|
+
* Generate a unique `OnModuleInit` registration class per
|
|
220
|
+
* `forRootAsync` call. The class injects the async-resolved
|
|
221
|
+
* `TypeOrmTransactionalOptions`, the global `AdapterRegistry`, and
|
|
222
|
+
* `ModuleRef`. In `onModuleInit()` it resolves the actual
|
|
223
|
+
* `DataSource` (every DI provider is ready by then) and calls
|
|
224
|
+
* {@link registerManagedDataSource}.
|
|
225
|
+
*
|
|
226
|
+
* Uniqueness per `id` matters because each `forRootAsync` call
|
|
227
|
+
* registers its OWN provider class — multiple async registrations
|
|
228
|
+
* in the same app must not collide on the same constructor token.
|
|
229
|
+
*
|
|
230
|
+
* Module-level `Reflect` metadata required by NestJS DI is set up
|
|
231
|
+
* via `@Inject(asyncToken)` on the constructor parameter.
|
|
232
|
+
*/
|
|
233
|
+
function createAsyncRegistrationClass(id, asyncToken) {
|
|
234
|
+
let TypeOrmTransactionalAsyncRegistration = class TypeOrmTransactionalAsyncRegistration {
|
|
235
|
+
resolved;
|
|
236
|
+
registry;
|
|
237
|
+
moduleRef;
|
|
238
|
+
constructor(resolved, registry, moduleRef) {
|
|
239
|
+
this.resolved = resolved;
|
|
240
|
+
this.registry = registry;
|
|
241
|
+
this.moduleRef = moduleRef;
|
|
242
|
+
}
|
|
243
|
+
onModuleInit() {
|
|
244
|
+
const dataSourceName = this.resolved.dataSource ?? 'default';
|
|
245
|
+
const dataSourceToken = (0, typeorm_1.getDataSourceToken)(dataSourceName);
|
|
246
|
+
const ds = this.moduleRef.get(dataSourceToken, {
|
|
247
|
+
strict: false,
|
|
248
|
+
});
|
|
249
|
+
registerManagedDataSource({
|
|
250
|
+
dataSource: ds,
|
|
251
|
+
dataSourceName,
|
|
252
|
+
isDefault: this.resolved.isDefault ?? false,
|
|
253
|
+
registry: this.registry,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
TypeOrmTransactionalAsyncRegistration = __decorate([
|
|
258
|
+
(0, common_1.Injectable)(),
|
|
259
|
+
__param(0, (0, common_1.Inject)(asyncToken)),
|
|
260
|
+
__param(1, (0, common_1.Inject)(core_2.ADAPTER_REGISTRY)),
|
|
261
|
+
__metadata("design:paramtypes", [Object, core_2.AdapterRegistry,
|
|
262
|
+
core_1.ModuleRef])
|
|
263
|
+
], TypeOrmTransactionalAsyncRegistration);
|
|
264
|
+
// Distinguish each generated class so a TypeScript reflection /
|
|
265
|
+
// logging consumer can tell them apart. Class identity itself is
|
|
266
|
+
// already unique per call (each `class` expression yields a fresh
|
|
267
|
+
// constructor), but a meaningful `name` helps with stack traces.
|
|
268
|
+
Object.defineProperty(TypeOrmTransactionalAsyncRegistration, 'name', {
|
|
269
|
+
value: `TypeOrmTransactionalAsyncRegistration_${id}`,
|
|
270
|
+
});
|
|
271
|
+
return TypeOrmTransactionalAsyncRegistration;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Common registration path used by both `forRoot`'s factory
|
|
275
|
+
* provider and the `forRootAsync` `OnModuleInit` registration
|
|
276
|
+
* class. Centralises the four-step dance of patch-on-first-use,
|
|
277
|
+
* mark-as-managed, instance-patch, and register-with-AdapterRegistry
|
|
278
|
+
* so the two entry points cannot drift out of step.
|
|
279
|
+
*/
|
|
280
|
+
function registerManagedDataSource(args) {
|
|
281
|
+
const { dataSource, dataSourceName, isDefault, registry } = args;
|
|
282
|
+
(0, patching_1.applyAllPatches)();
|
|
283
|
+
(0, patching_1.markAsManaged)(dataSource, dataSourceName);
|
|
284
|
+
(0, patching_1.patchDataSourceInstance)(dataSource);
|
|
285
|
+
const adapter = new typeorm_adapter_1.TypeOrmTransactionAdapter(dataSource, dataSourceName);
|
|
286
|
+
registry.register({ adapterName: 'typeorm', instanceName: dataSourceName, adapter }, isDefault);
|
|
287
|
+
return adapter;
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=typeorm-transactional.module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"typeorm-transactional.module.js","sourceRoot":"","sources":["../../src/module/typeorm-transactional.module.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { DataSource } from 'typeorm';
|
|
2
|
+
/**
|
|
3
|
+
* Apply per-instance patches to a single `DataSource` at the time
|
|
4
|
+
* it's registered as managed. Three patches go on the instance
|
|
5
|
+
* itself (NOT the prototype) because TypeORM sets the affected
|
|
6
|
+
* properties as own-properties in the `DataSource` constructor —
|
|
7
|
+
* patching `DataSource.prototype` would be shadowed by every
|
|
8
|
+
* instance.
|
|
9
|
+
*
|
|
10
|
+
* Patches applied:
|
|
11
|
+
*
|
|
12
|
+
* 1. `dataSource.manager` — replaced with a getter/setter pair.
|
|
13
|
+
* The getter returns the active transactional `EntityManager`
|
|
14
|
+
* when one is registered for this dataSource's name; otherwise
|
|
15
|
+
* falls back to the original (closure-captured) manager. The
|
|
16
|
+
* setter is preserved so any TypeORM-internal reassignment
|
|
17
|
+
* updates the captured original.
|
|
18
|
+
*
|
|
19
|
+
* 2. `dataSource.query(sql, params, queryRunner?)` — wrapped to
|
|
20
|
+
* default the `queryRunner` argument from the active
|
|
21
|
+
* transactional EntityManager when one is available. Without
|
|
22
|
+
* this wrap, raw SQL via `dataSource.query(...)` would always
|
|
23
|
+
* run on the autocommit pool, even inside a `@Transactional()`.
|
|
24
|
+
*
|
|
25
|
+
* 3. `dataSource.createQueryBuilder(entity?, alias?, queryRunner?)`
|
|
26
|
+
* — wrapped likewise, so query builders created via the
|
|
27
|
+
* DataSource (rather than via a Repository) also pick up the
|
|
28
|
+
* transactional QueryRunner.
|
|
29
|
+
*
|
|
30
|
+
* `dataSource.transaction(...)` is NOT patched — it delegates to
|
|
31
|
+
* `manager.transaction(...)` internally (which already uses the
|
|
32
|
+
* patched `manager` getter), and re-routing it through any of our
|
|
33
|
+
* machinery would just be a no-op forward.
|
|
34
|
+
*
|
|
35
|
+
* **Idempotent**: a marker symbol ({@link TYPEORM_DATA_SOURCE_PATCHED})
|
|
36
|
+
* is stamped on each patched DataSource so that double registration
|
|
37
|
+
* (e.g. test reset followed by re-registration of the same
|
|
38
|
+
* DataSource) does not stack getter/setter pairs. Calling this
|
|
39
|
+
* function on an already-patched DataSource is a no-op.
|
|
40
|
+
*
|
|
41
|
+
* Note: the patches are applied to a specific `DataSource` instance
|
|
42
|
+
* and survive on that instance until garbage collection. There is
|
|
43
|
+
* no per-instance revert API; tests that need a clean slate
|
|
44
|
+
* destroy the DataSource and create a fresh one (the standard
|
|
45
|
+
* pattern; integration tests already do this in `afterAll`).
|
|
46
|
+
*/
|
|
47
|
+
export declare function patchDataSourceInstance(dataSource: DataSource): void;
|
|
48
|
+
//# sourceMappingURL=data-source-patches.d.ts.map
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-assignment */
|
|
3
|
+
// The patching machinery overrides instance-level methods on
|
|
4
|
+
// TypeORM `DataSource` objects (`manager` getter/setter,
|
|
5
|
+
// `query`, `createQueryBuilder`) via runtime property descriptors.
|
|
6
|
+
// The inputs and outputs are intentionally typed as `any` because
|
|
7
|
+
// TypeORM's generic signatures don't survive the wrap; the runtime
|
|
8
|
+
// contract is documented in JSDoc above each patch. File-level
|
|
9
|
+
// disable keeps the patch code readable.
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.patchDataSourceInstance = patchDataSourceInstance;
|
|
12
|
+
const managed_registry_1 = require("./managed-registry");
|
|
13
|
+
const symbols_1 = require("./symbols");
|
|
14
|
+
/**
|
|
15
|
+
* Apply per-instance patches to a single `DataSource` at the time
|
|
16
|
+
* it's registered as managed. Three patches go on the instance
|
|
17
|
+
* itself (NOT the prototype) because TypeORM sets the affected
|
|
18
|
+
* properties as own-properties in the `DataSource` constructor —
|
|
19
|
+
* patching `DataSource.prototype` would be shadowed by every
|
|
20
|
+
* instance.
|
|
21
|
+
*
|
|
22
|
+
* Patches applied:
|
|
23
|
+
*
|
|
24
|
+
* 1. `dataSource.manager` — replaced with a getter/setter pair.
|
|
25
|
+
* The getter returns the active transactional `EntityManager`
|
|
26
|
+
* when one is registered for this dataSource's name; otherwise
|
|
27
|
+
* falls back to the original (closure-captured) manager. The
|
|
28
|
+
* setter is preserved so any TypeORM-internal reassignment
|
|
29
|
+
* updates the captured original.
|
|
30
|
+
*
|
|
31
|
+
* 2. `dataSource.query(sql, params, queryRunner?)` — wrapped to
|
|
32
|
+
* default the `queryRunner` argument from the active
|
|
33
|
+
* transactional EntityManager when one is available. Without
|
|
34
|
+
* this wrap, raw SQL via `dataSource.query(...)` would always
|
|
35
|
+
* run on the autocommit pool, even inside a `@Transactional()`.
|
|
36
|
+
*
|
|
37
|
+
* 3. `dataSource.createQueryBuilder(entity?, alias?, queryRunner?)`
|
|
38
|
+
* — wrapped likewise, so query builders created via the
|
|
39
|
+
* DataSource (rather than via a Repository) also pick up the
|
|
40
|
+
* transactional QueryRunner.
|
|
41
|
+
*
|
|
42
|
+
* `dataSource.transaction(...)` is NOT patched — it delegates to
|
|
43
|
+
* `manager.transaction(...)` internally (which already uses the
|
|
44
|
+
* patched `manager` getter), and re-routing it through any of our
|
|
45
|
+
* machinery would just be a no-op forward.
|
|
46
|
+
*
|
|
47
|
+
* **Idempotent**: a marker symbol ({@link TYPEORM_DATA_SOURCE_PATCHED})
|
|
48
|
+
* is stamped on each patched DataSource so that double registration
|
|
49
|
+
* (e.g. test reset followed by re-registration of the same
|
|
50
|
+
* DataSource) does not stack getter/setter pairs. Calling this
|
|
51
|
+
* function on an already-patched DataSource is a no-op.
|
|
52
|
+
*
|
|
53
|
+
* Note: the patches are applied to a specific `DataSource` instance
|
|
54
|
+
* and survive on that instance until garbage collection. There is
|
|
55
|
+
* no per-instance revert API; tests that need a clean slate
|
|
56
|
+
* destroy the DataSource and create a fresh one (the standard
|
|
57
|
+
* pattern; integration tests already do this in `afterAll`).
|
|
58
|
+
*/
|
|
59
|
+
function patchDataSourceInstance(dataSource) {
|
|
60
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
61
|
+
if (dataSource[symbols_1.TYPEORM_DATA_SOURCE_PATCHED] === true) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// (1) `manager` — getter/setter on the instance.
|
|
65
|
+
let originalManager = dataSource.manager;
|
|
66
|
+
Object.defineProperty(dataSource, 'manager', {
|
|
67
|
+
configurable: true,
|
|
68
|
+
get() {
|
|
69
|
+
const dsName = (0, managed_registry_1.getManagedDataSourceName)(dataSource);
|
|
70
|
+
if (dsName === undefined) {
|
|
71
|
+
return originalManager;
|
|
72
|
+
}
|
|
73
|
+
const active = (0, managed_registry_1.getActiveEntityManager)(dsName);
|
|
74
|
+
return active ?? originalManager;
|
|
75
|
+
},
|
|
76
|
+
set(manager) {
|
|
77
|
+
originalManager = manager;
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
// (2) `query(sql, params, queryRunner?)` — pick up the active QR
|
|
81
|
+
// when none is supplied. The wrapper bypasses the generic type
|
|
82
|
+
// shape of `DataSource.query` via `any` casts; the runtime
|
|
83
|
+
// contract is unchanged (sql first, params second, qr third).
|
|
84
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
+
const originalQuery = dataSource.query.bind(dataSource);
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
|
+
dataSource.query = function patchedQuery(
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
89
|
+
...args) {
|
|
90
|
+
if (args.length >= 3) {
|
|
91
|
+
// Caller passed a queryRunner explicitly — respect it.
|
|
92
|
+
return originalQuery(...args);
|
|
93
|
+
}
|
|
94
|
+
const activeQueryRunner = pickActiveQueryRunner(this);
|
|
95
|
+
if (activeQueryRunner !== undefined) {
|
|
96
|
+
return originalQuery(args[0], args[1], activeQueryRunner);
|
|
97
|
+
}
|
|
98
|
+
return originalQuery(...args);
|
|
99
|
+
};
|
|
100
|
+
// (3) `createQueryBuilder(entity?, alias?, queryRunner?)` —
|
|
101
|
+
// mirror logic for QB creation.
|
|
102
|
+
const originalCreateQueryBuilder = dataSource.createQueryBuilder.bind(dataSource);
|
|
103
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
104
|
+
dataSource.createQueryBuilder = function patchedCreateQueryBuilder(
|
|
105
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
106
|
+
...args) {
|
|
107
|
+
const activeQueryRunner = pickActiveQueryRunner(this);
|
|
108
|
+
if (args.length === 0) {
|
|
109
|
+
return activeQueryRunner !== undefined
|
|
110
|
+
? originalCreateQueryBuilder(activeQueryRunner)
|
|
111
|
+
: originalCreateQueryBuilder();
|
|
112
|
+
}
|
|
113
|
+
if (args.length >= 3) {
|
|
114
|
+
return originalCreateQueryBuilder(...args);
|
|
115
|
+
}
|
|
116
|
+
if (activeQueryRunner !== undefined) {
|
|
117
|
+
return originalCreateQueryBuilder(args[0], args[1], activeQueryRunner);
|
|
118
|
+
}
|
|
119
|
+
return originalCreateQueryBuilder(...args);
|
|
120
|
+
};
|
|
121
|
+
// Stamp marker so re-entry is a no-op.
|
|
122
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
123
|
+
dataSource[symbols_1.TYPEORM_DATA_SOURCE_PATCHED] = true;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Helper — look up the active transactional EntityManager for this
|
|
127
|
+
* DataSource and return its `queryRunner` (or `undefined` if no
|
|
128
|
+
* transaction is active). Centralised so the `query` and
|
|
129
|
+
* `createQueryBuilder` patches share one resolution rule.
|
|
130
|
+
*/
|
|
131
|
+
function pickActiveQueryRunner(ds) {
|
|
132
|
+
const dsName = (0, managed_registry_1.getManagedDataSourceName)(ds);
|
|
133
|
+
if (dsName === undefined) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
const active = (0, managed_registry_1.getActiveEntityManager)(dsName);
|
|
137
|
+
return active?.queryRunner;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=data-source-patches.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-source-patches.js","sourceRoot":"","sources":["../../src/patching/data-source-patches.ts"],"names":[],"mappings":"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"}
|