drizzle-multitenant 1.0.1 → 1.0.3

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.
@@ -8,7 +8,9 @@
8
8
  "Bash(tree:*)",
9
9
  "Bash(find:*)",
10
10
  "Bash(mkdir:*)",
11
- "Bash(node ./bin/drizzle-multitenant.js:*)"
11
+ "Bash(node ./bin/drizzle-multitenant.js:*)",
12
+ "Bash(ls:*)",
13
+ "Bash(npm run test:*)"
12
14
  ]
13
15
  }
14
16
  }
package/README.md CHANGED
@@ -134,7 +134,7 @@ import { TenantModule, InjectTenantDb } from 'drizzle-multitenant/nestjs';
134
134
  })
135
135
  export class AppModule {}
136
136
 
137
- @Injectable()
137
+ @Injectable({ scope: Scope.REQUEST })
138
138
  export class UserService {
139
139
  constructor(@InjectTenantDb() private readonly db: TenantDb) {}
140
140
 
@@ -144,6 +144,59 @@ export class UserService {
144
144
  }
145
145
  ```
146
146
 
147
+ #### Singleton Services (Cron Jobs, Event Handlers)
148
+
149
+ Use `TenantDbFactory` when you need to access tenant databases from singleton services:
150
+
151
+ ```typescript
152
+ import { TenantDbFactory, InjectTenantDbFactory } from 'drizzle-multitenant/nestjs';
153
+
154
+ @Injectable() // Singleton - no scope needed
155
+ export class ReportService {
156
+ constructor(@InjectTenantDbFactory() private dbFactory: TenantDbFactory) {}
157
+
158
+ async generateReport(tenantId: string) {
159
+ const db = this.dbFactory.getDb(tenantId);
160
+ return db.select().from(reports);
161
+ }
162
+ }
163
+
164
+ // Cron job example
165
+ @Injectable()
166
+ export class DailyReportCron {
167
+ constructor(@InjectTenantDbFactory() private dbFactory: TenantDbFactory) {}
168
+
169
+ @Cron('0 8 * * *')
170
+ async run() {
171
+ const tenants = await this.getTenantIds();
172
+ for (const tenantId of tenants) {
173
+ const db = this.dbFactory.getDb(tenantId);
174
+ await this.processReports(db);
175
+ }
176
+ }
177
+ }
178
+ ```
179
+
180
+ #### Debugging
181
+
182
+ The injected `TenantDb` provides debug utilities:
183
+
184
+ ```typescript
185
+ // Console output shows useful info
186
+ console.log(tenantDb);
187
+ // [TenantDb] tenant=123 schema=empresa_123
188
+
189
+ // Access debug information
190
+ console.log(tenantDb.__debug);
191
+ // { tenantId: '123', schemaName: 'empresa_123', isProxy: true, poolCount: 5 }
192
+
193
+ // Quick access
194
+ console.log(tenantDb.__tenantId); // '123'
195
+
196
+ // In tests
197
+ expect(tenantDb.__tenantId).toBe('expected-tenant');
198
+ ```
199
+
147
200
  ## CLI Commands
148
201
 
149
202
  ```bash
@@ -222,13 +275,24 @@ const result = await query
222
275
 
223
276
  | Decorator | Description |
224
277
  |-----------|-------------|
225
- | `@InjectTenantDb()` | Inject tenant database |
278
+ | `@InjectTenantDb()` | Inject tenant database (request-scoped) |
279
+ | `@InjectTenantDbFactory()` | Inject factory for singleton services |
226
280
  | `@InjectSharedDb()` | Inject shared database |
227
281
  | `@InjectTenantContext()` | Inject tenant context |
228
282
  | `@InjectTenantManager()` | Inject tenant manager |
229
283
  | `@RequiresTenant()` | Mark route as requiring tenant |
230
284
  | `@PublicRoute()` | Mark route as public |
231
285
 
286
+ ### TenantDbFactory Methods
287
+
288
+ | Method | Description |
289
+ |--------|-------------|
290
+ | `getDb(tenantId)` | Get Drizzle instance for tenant |
291
+ | `getSharedDb()` | Get shared database instance |
292
+ | `getSchemaName(tenantId)` | Get schema name for tenant |
293
+ | `getDebugInfo(tenantId)` | Get debug info (tenantId, schema, pool stats) |
294
+ | `getManager()` | Get underlying TenantManager |
295
+
232
296
  ## Requirements
233
297
 
234
298
  - Node.js 18+
@@ -1,8 +1,7 @@
1
1
  import * as _nestjs_common from '@nestjs/common';
2
2
  import { ModuleMetadata, Type, InjectionToken, DynamicModule, CanActivate, ExecutionContext, NestInterceptor, CallHandler, Provider } from '@nestjs/common';
3
3
  import { Request } from 'express';
4
- import { C as Config, T as TenantManager } from '../../types-DKVaTaIb.js';
5
- export { S as SharedDb, a as TenantDb } from '../../types-DKVaTaIb.js';
4
+ import { C as Config, a as TenantDb, T as TenantManager, S as SharedDb } from '../../types-DKVaTaIb.js';
6
5
  import { Reflector } from '@nestjs/core';
7
6
  import { Observable } from 'rxjs';
8
7
  import 'pg';
@@ -70,6 +69,32 @@ interface TenantRequest extends Request {
70
69
  tenantContext?: NestTenantContext;
71
70
  tenantId?: string;
72
71
  }
72
+ /**
73
+ * Debug information available on TenantDb proxy
74
+ */
75
+ interface TenantDbDebugInfo$1 {
76
+ /** Current tenant ID (null if not resolved) */
77
+ tenantId: string | null;
78
+ /** Schema name for the tenant (null if not resolved) */
79
+ schemaName: string | null;
80
+ /** Whether this is a proxy object */
81
+ isProxy: boolean;
82
+ /** Number of active connection pools */
83
+ poolCount: number;
84
+ }
85
+ /**
86
+ * Extended TenantDb interface with debug utilities
87
+ *
88
+ * Available when using @InjectTenantDb() - provides debugging helpers
89
+ */
90
+ interface TenantDbWithDebug<T extends Record<string, unknown> = Record<string, unknown>> extends TenantDb<T> {
91
+ /** Debug information about the current tenant connection */
92
+ __debug: TenantDbDebugInfo$1;
93
+ /** Current tenant ID (null if not resolved) */
94
+ __tenantId: string | null;
95
+ /** Whether this is a proxy object */
96
+ __isProxy: true;
97
+ }
73
98
 
74
99
  /**
75
100
  * NestJS module for multi-tenant support
@@ -127,6 +152,95 @@ declare class TenantModule {
127
152
  */
128
153
  declare const DrizzleMultitenantModule: typeof TenantModule;
129
154
 
155
+ /**
156
+ * Debug information for tenant database connections
157
+ */
158
+ interface TenantDbDebugInfo {
159
+ tenantId: string;
160
+ schemaName: string;
161
+ isProxy: boolean;
162
+ poolCount: number;
163
+ }
164
+ /**
165
+ * Factory for creating tenant database connections
166
+ *
167
+ * Use this when you need to access tenant databases in singleton services
168
+ * (cron jobs, event handlers, background workers, etc.)
169
+ *
170
+ * @example
171
+ * ```typescript
172
+ * // Service stays singleton - no scope change needed
173
+ * @Injectable()
174
+ * export class ReportService {
175
+ * constructor(private dbFactory: TenantDbFactory) {}
176
+ *
177
+ * async generateReport(tenantId: string) {
178
+ * const db = this.dbFactory.getDb(tenantId);
179
+ * return db.select().from(reports);
180
+ * }
181
+ * }
182
+ * ```
183
+ *
184
+ * @example
185
+ * ```typescript
186
+ * // Cron job usage
187
+ * @Injectable()
188
+ * export class DailyReportCron {
189
+ * constructor(private dbFactory: TenantDbFactory) {}
190
+ *
191
+ * @Cron('0 8 * * *')
192
+ * async generateDailyReports() {
193
+ * const tenants = await this.getTenantIds();
194
+ * for (const tenantId of tenants) {
195
+ * const db = this.dbFactory.getDb(tenantId);
196
+ * await this.processReports(db);
197
+ * }
198
+ * }
199
+ * }
200
+ * ```
201
+ */
202
+ declare class TenantDbFactory<TTenantSchema extends Record<string, unknown> = Record<string, unknown>, TSharedSchema extends Record<string, unknown> = Record<string, unknown>> {
203
+ private readonly manager;
204
+ constructor(manager: TenantManager<TTenantSchema, TSharedSchema>);
205
+ /**
206
+ * Get a tenant database connection by tenant ID
207
+ *
208
+ * @param tenantId - The tenant identifier
209
+ * @returns The tenant-scoped Drizzle database instance
210
+ *
211
+ * @throws Error if tenantId is empty or invalid
212
+ */
213
+ getDb(tenantId: string): TenantDb<TTenantSchema>;
214
+ /**
215
+ * Get the shared database connection
216
+ *
217
+ * @returns The shared Drizzle database instance
218
+ */
219
+ getSharedDb(): SharedDb<TSharedSchema>;
220
+ /**
221
+ * Get the schema name for a tenant
222
+ *
223
+ * @param tenantId - The tenant identifier
224
+ * @returns The schema name for the tenant
225
+ */
226
+ getSchemaName(tenantId: string): string;
227
+ /**
228
+ * Get debug information for a tenant database
229
+ *
230
+ * @param tenantId - The tenant identifier
231
+ * @returns Debug information including schema name and pool stats
232
+ */
233
+ getDebugInfo(tenantId: string): TenantDbDebugInfo;
234
+ /**
235
+ * Get the underlying TenantManager instance
236
+ *
237
+ * Use this for advanced operations like pool management
238
+ *
239
+ * @returns The TenantManager instance
240
+ */
241
+ getManager(): TenantManager<TTenantSchema, TSharedSchema>;
242
+ }
243
+
130
244
  /**
131
245
  * Inject the tenant database for the current request
132
246
  *
@@ -256,6 +370,46 @@ declare const RequiresTenant: () => ClassDecorator & MethodDecorator;
256
370
  * ```
257
371
  */
258
372
  declare const PublicRoute: () => MethodDecorator;
373
+ /**
374
+ * Inject the TenantDbFactory for singleton services
375
+ *
376
+ * Use this when you need to access tenant databases in singleton services
377
+ * (cron jobs, event handlers, background workers, etc.) without requiring
378
+ * request scope.
379
+ *
380
+ * @example
381
+ * ```typescript
382
+ * // Service stays singleton - no scope change needed
383
+ * @Injectable()
384
+ * export class ReportService {
385
+ * constructor(@InjectTenantDbFactory() private dbFactory: TenantDbFactory) {}
386
+ *
387
+ * async generateReport(tenantId: string) {
388
+ * const db = this.dbFactory.getDb(tenantId);
389
+ * return db.select().from(reports);
390
+ * }
391
+ * }
392
+ * ```
393
+ *
394
+ * @example
395
+ * ```typescript
396
+ * // Cron job usage
397
+ * @Injectable()
398
+ * export class DailyReportCron {
399
+ * constructor(@InjectTenantDbFactory() private dbFactory: TenantDbFactory) {}
400
+ *
401
+ * @Cron('0 8 * * *')
402
+ * async generateDailyReports() {
403
+ * const tenants = await this.getTenantIds();
404
+ * for (const tenantId of tenants) {
405
+ * const db = this.dbFactory.getDb(tenantId);
406
+ * await this.processReports(db);
407
+ * }
408
+ * }
409
+ * }
410
+ * ```
411
+ */
412
+ declare const InjectTenantDbFactory: () => ParameterDecorator;
259
413
 
260
414
  /**
261
415
  * Guard that extracts and validates tenant ID from requests
@@ -382,5 +536,7 @@ declare const TENANT_ID_EXTRACTOR: unique symbol;
382
536
  declare const REQUIRES_TENANT_KEY = "requires_tenant";
383
537
  /** Metadata key for public routes (no tenant required) */
384
538
  declare const IS_PUBLIC_KEY = "is_public_tenant";
539
+ /** Token for injecting the TenantDbFactory */
540
+ declare const TENANT_DB_FACTORY: unique symbol;
385
541
 
386
- export { Config, DrizzleMultitenantModule, IS_PUBLIC_KEY, InjectSharedDb, InjectTenantContext, InjectTenantDb, InjectTenantManager, type NestTenantContext, PublicRoute, REQUIRES_TENANT_KEY, RequireTenantGuard, RequiresTenant, SHARED_DB, TENANT_CONTEXT, TENANT_DB, TENANT_ID_EXTRACTOR, TENANT_MANAGER, TENANT_MODULE_OPTIONS, TenantContextInterceptor, TenantCtx, TenantGuard, TenantId, type TenantIdExtractor, TenantLoggingInterceptor, TenantManager, TenantModule, type TenantModuleAsyncOptions, type TenantModuleOptions, type TenantModuleOptionsFactory, type TenantRequest, type TenantValidator, createAsyncProviders, createTenantProviders };
542
+ export { Config, DrizzleMultitenantModule, IS_PUBLIC_KEY, InjectSharedDb, InjectTenantContext, InjectTenantDb, InjectTenantDbFactory, InjectTenantManager, type NestTenantContext, PublicRoute, REQUIRES_TENANT_KEY, RequireTenantGuard, RequiresTenant, SHARED_DB, SharedDb, TENANT_CONTEXT, TENANT_DB, TENANT_DB_FACTORY, TENANT_ID_EXTRACTOR, TENANT_MANAGER, TENANT_MODULE_OPTIONS, TenantContextInterceptor, TenantCtx, TenantDb, type TenantDbDebugInfo$1 as TenantDbDebugInfo, TenantDbFactory, type TenantDbWithDebug, TenantGuard, TenantId, type TenantIdExtractor, TenantLoggingInterceptor, TenantManager, TenantModule, type TenantModuleAsyncOptions, type TenantModuleOptions, type TenantModuleOptionsFactory, type TenantRequest, type TenantValidator, createAsyncProviders, createTenantProviders };
@@ -9212,6 +9212,7 @@ var TENANT_MODULE_OPTIONS = /* @__PURE__ */ Symbol("TENANT_MODULE_OPTIONS");
9212
9212
  var TENANT_ID_EXTRACTOR = /* @__PURE__ */ Symbol("TENANT_ID_EXTRACTOR");
9213
9213
  var REQUIRES_TENANT_KEY = "requires_tenant";
9214
9214
  var IS_PUBLIC_KEY = "is_public_tenant";
9215
+ var TENANT_DB_FACTORY = /* @__PURE__ */ Symbol("TENANT_DB_FACTORY");
9215
9216
 
9216
9217
  // src/types.ts
9217
9218
  var DEFAULT_CONFIG = {
@@ -9478,18 +9479,85 @@ function createTenantProviders() {
9478
9479
  },
9479
9480
  inject: [TENANT_MODULE_OPTIONS]
9480
9481
  },
9481
- // TenantDb - request scoped
9482
+ // TenantDb - request scoped with lazy resolution via Proxy
9483
+ // This fixes the timing issue where TENANT_DB is resolved before TenantGuard executes
9482
9484
  {
9483
9485
  provide: TENANT_DB,
9484
9486
  scope: Scope.REQUEST,
9485
- useFactory: (request, manager) => {
9486
- const tenantId = request.tenantContext?.tenantId ?? request.tenantId;
9487
- if (!tenantId) {
9488
- return null;
9489
- }
9490
- return manager.getDb(tenantId);
9487
+ useFactory: (request, manager, options) => {
9488
+ const resolveTenantId = () => {
9489
+ let tenantId = request.tenantContext?.tenantId ?? request.tenantId;
9490
+ if (!tenantId && options.extractTenantId) {
9491
+ const extracted = options.extractTenantId(request);
9492
+ if (typeof extracted === "string") {
9493
+ tenantId = extracted;
9494
+ }
9495
+ }
9496
+ return tenantId;
9497
+ };
9498
+ const inspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
9499
+ const debugProps = ["__debug", "__tenantId", "__isProxy"];
9500
+ return new Proxy({}, {
9501
+ get(_target, prop) {
9502
+ if (prop === Symbol.toStringTag) return "TenantDb";
9503
+ const resolvedTenantId = resolveTenantId();
9504
+ if (prop === inspectSymbol || prop === "toString") {
9505
+ return () => {
9506
+ if (resolvedTenantId) {
9507
+ return `[TenantDb] tenant=${resolvedTenantId} schema=${manager.getSchemaName(resolvedTenantId)}`;
9508
+ }
9509
+ return "[TenantDb] (no tenant context)";
9510
+ };
9511
+ }
9512
+ if (prop === "__debug") {
9513
+ return {
9514
+ tenantId: resolvedTenantId ?? null,
9515
+ schemaName: resolvedTenantId ? manager.getSchemaName(resolvedTenantId) : null,
9516
+ isProxy: true,
9517
+ poolCount: manager.getPoolCount()
9518
+ };
9519
+ }
9520
+ if (prop === "__tenantId") {
9521
+ return resolvedTenantId ?? null;
9522
+ }
9523
+ if (prop === "__isProxy") {
9524
+ return true;
9525
+ }
9526
+ if (!resolvedTenantId) {
9527
+ throw new Error(
9528
+ "[drizzle-multitenant] No tenant context found. Ensure the route has a tenant ID or use @PublicRoute() decorator."
9529
+ );
9530
+ }
9531
+ const db = manager.getDb(resolvedTenantId);
9532
+ return db[prop];
9533
+ },
9534
+ has(_target, prop) {
9535
+ if (debugProps.includes(prop)) return true;
9536
+ const tenantId = request.tenantContext?.tenantId ?? request.tenantId;
9537
+ if (!tenantId) return false;
9538
+ const db = manager.getDb(tenantId);
9539
+ return prop in db;
9540
+ },
9541
+ ownKeys() {
9542
+ const tenantId = request.tenantContext?.tenantId ?? request.tenantId;
9543
+ if (!tenantId) {
9544
+ return [...debugProps];
9545
+ }
9546
+ const db = manager.getDb(tenantId);
9547
+ return [.../* @__PURE__ */ new Set([...debugProps, ...Reflect.ownKeys(db)])];
9548
+ },
9549
+ getOwnPropertyDescriptor(_target, prop) {
9550
+ if (debugProps.includes(prop)) {
9551
+ return { configurable: true, enumerable: true, writable: false };
9552
+ }
9553
+ const tenantId = request.tenantContext?.tenantId ?? request.tenantId;
9554
+ if (!tenantId) return void 0;
9555
+ const db = manager.getDb(tenantId);
9556
+ return Object.getOwnPropertyDescriptor(db, prop);
9557
+ }
9558
+ });
9491
9559
  },
9492
- inject: [REQUEST, TENANT_MANAGER]
9560
+ inject: [REQUEST, TENANT_MANAGER, TENANT_MODULE_OPTIONS]
9493
9561
  },
9494
9562
  // SharedDb - singleton (doesn't need request scope)
9495
9563
  {
@@ -9499,14 +9567,97 @@ function createTenantProviders() {
9499
9567
  },
9500
9568
  inject: [TENANT_MANAGER]
9501
9569
  },
9502
- // TenantContext - request scoped
9570
+ // TenantContext - request scoped with lazy resolution via Proxy
9571
+ // This fixes the timing issue where TENANT_CONTEXT is resolved before TenantGuard executes
9503
9572
  {
9504
9573
  provide: TENANT_CONTEXT,
9505
9574
  scope: Scope.REQUEST,
9506
- useFactory: (request) => {
9507
- return request.tenantContext ?? null;
9575
+ useFactory: (request, manager, options) => {
9576
+ const inspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
9577
+ const resolveContext = () => {
9578
+ if (request.tenantContext) {
9579
+ return {
9580
+ tenantId: request.tenantContext.tenantId,
9581
+ schemaName: request.tenantContext.schemaName
9582
+ };
9583
+ }
9584
+ let tenantId = request.tenantId;
9585
+ if (!tenantId && options.extractTenantId) {
9586
+ const extracted = options.extractTenantId(request);
9587
+ if (typeof extracted === "string") {
9588
+ tenantId = extracted;
9589
+ }
9590
+ }
9591
+ if (!tenantId) return null;
9592
+ return {
9593
+ tenantId,
9594
+ schemaName: manager.getSchemaName(tenantId)
9595
+ };
9596
+ };
9597
+ return new Proxy({}, {
9598
+ get(_target, prop) {
9599
+ if (prop === Symbol.toStringTag) return "TenantContext";
9600
+ const ctx = resolveContext();
9601
+ if (prop === inspectSymbol || prop === "toString") {
9602
+ return () => {
9603
+ if (ctx) {
9604
+ return `[TenantContext] tenant=${ctx.tenantId} schema=${ctx.schemaName}`;
9605
+ }
9606
+ return "[TenantContext] (no tenant context)";
9607
+ };
9608
+ }
9609
+ if (prop === "__debug") {
9610
+ return {
9611
+ tenantId: ctx?.tenantId ?? null,
9612
+ schemaName: ctx?.schemaName ?? null,
9613
+ isProxy: true,
9614
+ hasContext: !!request.tenantContext
9615
+ };
9616
+ }
9617
+ if (prop === "__isProxy") {
9618
+ return true;
9619
+ }
9620
+ if (!ctx) {
9621
+ throw new Error(
9622
+ "[drizzle-multitenant] No tenant context found. Ensure the route has a tenant ID or use @PublicRoute() decorator."
9623
+ );
9624
+ }
9625
+ if (prop === "tenantId") return ctx.tenantId;
9626
+ if (prop === "schemaName") return ctx.schemaName;
9627
+ if (request.tenantContext) {
9628
+ return request.tenantContext[prop];
9629
+ }
9630
+ return void 0;
9631
+ },
9632
+ has(_target, prop) {
9633
+ if (prop === "__debug" || prop === "__isProxy") return true;
9634
+ if (request.tenantContext) {
9635
+ return prop in request.tenantContext;
9636
+ }
9637
+ return prop === "tenantId" || prop === "schemaName";
9638
+ },
9639
+ ownKeys() {
9640
+ const baseKeys = ["tenantId", "schemaName", "__debug", "__isProxy"];
9641
+ if (request.tenantContext) {
9642
+ return [.../* @__PURE__ */ new Set([...baseKeys, ...Reflect.ownKeys(request.tenantContext)])];
9643
+ }
9644
+ return baseKeys;
9645
+ },
9646
+ getOwnPropertyDescriptor(_target, prop) {
9647
+ if (prop === "__debug" || prop === "__isProxy") {
9648
+ return { configurable: true, enumerable: true, writable: false };
9649
+ }
9650
+ if (request.tenantContext) {
9651
+ return Object.getOwnPropertyDescriptor(request.tenantContext, prop);
9652
+ }
9653
+ if (prop === "tenantId" || prop === "schemaName") {
9654
+ return { configurable: true, enumerable: true, writable: true };
9655
+ }
9656
+ return void 0;
9657
+ }
9658
+ });
9508
9659
  },
9509
- inject: [REQUEST]
9660
+ inject: [REQUEST, TENANT_MANAGER, TENANT_MODULE_OPTIONS]
9510
9661
  }
9511
9662
  ];
9512
9663
  }
@@ -9713,6 +9864,73 @@ var TenantLoggingInterceptor = class {
9713
9864
  TenantLoggingInterceptor = __decorateClass([
9714
9865
  Injectable()
9715
9866
  ], TenantLoggingInterceptor);
9867
+ var TenantDbFactory = class {
9868
+ constructor(manager) {
9869
+ this.manager = manager;
9870
+ }
9871
+ /**
9872
+ * Get a tenant database connection by tenant ID
9873
+ *
9874
+ * @param tenantId - The tenant identifier
9875
+ * @returns The tenant-scoped Drizzle database instance
9876
+ *
9877
+ * @throws Error if tenantId is empty or invalid
9878
+ */
9879
+ getDb(tenantId) {
9880
+ if (!tenantId || typeof tenantId !== "string") {
9881
+ throw new Error(
9882
+ "[drizzle-multitenant] TenantDbFactory.getDb() requires a valid tenantId string."
9883
+ );
9884
+ }
9885
+ return this.manager.getDb(tenantId);
9886
+ }
9887
+ /**
9888
+ * Get the shared database connection
9889
+ *
9890
+ * @returns The shared Drizzle database instance
9891
+ */
9892
+ getSharedDb() {
9893
+ return this.manager.getSharedDb();
9894
+ }
9895
+ /**
9896
+ * Get the schema name for a tenant
9897
+ *
9898
+ * @param tenantId - The tenant identifier
9899
+ * @returns The schema name for the tenant
9900
+ */
9901
+ getSchemaName(tenantId) {
9902
+ return this.manager.getSchemaName(tenantId);
9903
+ }
9904
+ /**
9905
+ * Get debug information for a tenant database
9906
+ *
9907
+ * @param tenantId - The tenant identifier
9908
+ * @returns Debug information including schema name and pool stats
9909
+ */
9910
+ getDebugInfo(tenantId) {
9911
+ return {
9912
+ tenantId,
9913
+ schemaName: this.manager.getSchemaName(tenantId),
9914
+ isProxy: false,
9915
+ // Factory returns direct db, not proxy
9916
+ poolCount: this.manager.getPoolCount()
9917
+ };
9918
+ }
9919
+ /**
9920
+ * Get the underlying TenantManager instance
9921
+ *
9922
+ * Use this for advanced operations like pool management
9923
+ *
9924
+ * @returns The TenantManager instance
9925
+ */
9926
+ getManager() {
9927
+ return this.manager;
9928
+ }
9929
+ };
9930
+ TenantDbFactory = __decorateClass([
9931
+ Injectable(),
9932
+ __decorateParam(0, Inject(TENANT_MANAGER))
9933
+ ], TenantDbFactory);
9716
9934
 
9717
9935
  // src/integrations/nestjs/tenant.module.ts
9718
9936
  var TenantModule = class {
@@ -9728,7 +9946,8 @@ var TenantModule = class {
9728
9946
  ...createTenantProviders(),
9729
9947
  Reflector,
9730
9948
  TenantGuard,
9731
- TenantContextInterceptor
9949
+ TenantContextInterceptor,
9950
+ TenantDbFactory
9732
9951
  ];
9733
9952
  if (options.isGlobal) {
9734
9953
  providers.push(
@@ -9749,7 +9968,8 @@ var TenantModule = class {
9749
9968
  TENANT_MODULE_OPTIONS,
9750
9969
  ...createTenantProviders(),
9751
9970
  TenantGuard,
9752
- TenantContextInterceptor
9971
+ TenantContextInterceptor,
9972
+ TenantDbFactory
9753
9973
  ]
9754
9974
  };
9755
9975
  if (options.isGlobal) {
@@ -9770,7 +9990,8 @@ var TenantModule = class {
9770
9990
  ...createTenantProviders(),
9771
9991
  Reflector,
9772
9992
  TenantGuard,
9773
- TenantContextInterceptor
9993
+ TenantContextInterceptor,
9994
+ TenantDbFactory
9774
9995
  ];
9775
9996
  const module = {
9776
9997
  module: TenantModule,
@@ -9780,7 +10001,8 @@ var TenantModule = class {
9780
10001
  TENANT_MODULE_OPTIONS,
9781
10002
  ...createTenantProviders(),
9782
10003
  TenantGuard,
9783
- TenantContextInterceptor
10004
+ TenantContextInterceptor,
10005
+ TenantDbFactory
9784
10006
  ]
9785
10007
  };
9786
10008
  if (options.isGlobal) {
@@ -9822,7 +10044,8 @@ var TenantId = createParamDecorator(
9822
10044
  );
9823
10045
  var RequiresTenant = () => SetMetadata(REQUIRES_TENANT_KEY, true);
9824
10046
  var PublicRoute = () => SetMetadata(IS_PUBLIC_KEY, true);
10047
+ var InjectTenantDbFactory = () => Inject(TenantDbFactory);
9825
10048
 
9826
- export { DrizzleMultitenantModule, IS_PUBLIC_KEY, InjectSharedDb, InjectTenantContext, InjectTenantDb, InjectTenantManager, PublicRoute, REQUIRES_TENANT_KEY, RequireTenantGuard, RequiresTenant, SHARED_DB, TENANT_CONTEXT, TENANT_DB, TENANT_ID_EXTRACTOR, TENANT_MANAGER, TENANT_MODULE_OPTIONS, TenantContextInterceptor, TenantCtx, TenantGuard, TenantId, TenantLoggingInterceptor, TenantModule, createAsyncProviders, createTenantProviders };
10049
+ export { DrizzleMultitenantModule, IS_PUBLIC_KEY, InjectSharedDb, InjectTenantContext, InjectTenantDb, InjectTenantDbFactory, InjectTenantManager, PublicRoute, REQUIRES_TENANT_KEY, RequireTenantGuard, RequiresTenant, SHARED_DB, TENANT_CONTEXT, TENANT_DB, TENANT_DB_FACTORY, TENANT_ID_EXTRACTOR, TENANT_MANAGER, TENANT_MODULE_OPTIONS, TenantContextInterceptor, TenantCtx, TenantDbFactory, TenantGuard, TenantId, TenantLoggingInterceptor, TenantModule, createAsyncProviders, createTenantProviders };
9827
10050
  //# sourceMappingURL=index.js.map
9828
10051
  //# sourceMappingURL=index.js.map