UNPKG

@nestdevx/database

Version:

Database module designed to work with mongodb for multi-tenant NestJS applications.

113 lines 5.17 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); 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; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var DatabaseModule_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.DatabaseModule = void 0; const common_1 = require("@nestjs/common"); const core_1 = require("@nestjs/core"); const mongoose_1 = require("mongoose"); const constants_1 = require("./constants"); const config_1 = require("@nestjs/config"); const request_context_1 = require("../../shared/src/hooks/request-context"); const connectionPool = new Map(); const tenantPlugin = (schema) => { const tenantId = (0, request_context_1.currentTenantId)(); common_1.Logger.debug(`Current tenant ID: ${tenantId}`, 'DatabaseModule'); if (!tenantId) return; schema.add({ tenantId: { type: mongoose_1.default.Types.ObjectId, ref: 'Tenant', default: null, index: true, }, }); common_1.Logger.debug(`Applying tenant plugin with tenantId: ${tenantId}`, 'DatabaseModule'); schema.pre('save', function (next) { this.tenantId = tenantId; next(); }); }; let DatabaseModule = DatabaseModule_1 = class DatabaseModule { static getConnectionProvider() { const connectionProvider = { provide: constants_1.TENANT_CONNECTION, scope: common_1.Scope.REQUEST, inject: [core_1.REQUEST, config_1.ConfigService], useFactory: async (req, configService) => { const { id, dbUri } = req?.tenant || { id: null, dbUri: 'shared' }; if (!id) { if (connectionPool.has('host')) { DatabaseModule_1.logger.log('Using existing connection for Host tenant.'); return connectionPool.get('host'); } DatabaseModule_1.logger.warn('No tenant ID found in request, using default connection for Host.'); const defaultDbUri = configService.getOrThrow('MONGODB_URI'); const conn = mongoose_1.default.createConnection(defaultDbUri); conn.plugin(tenantPlugin); connectionPool.set('host', conn); return connectionPool.get('host'); } if (!connectionPool.has(id)) { if (dbUri == "shared") { const defaultDbUri = configService.getOrThrow('MONGODB_URI'); DatabaseModule_1.logger.log(`Creating new connection for tenant: ${id} with shared dbUri!`); const conn = mongoose_1.default.createConnection(defaultDbUri); connectionPool.set(id, conn); } else { DatabaseModule_1.logger.log(`Creating new connection for tenant: ${id} with dbUri!`); const conn = mongoose_1.default.createConnection(dbUri); connectionPool.set(id, conn); } } DatabaseModule_1.logger.log(`Using existing connection for tenant: ${id}`); const c = connectionPool.get(id); c.plugin(tenantPlugin); return c; }, }; return connectionProvider; } static forMongoDbModels() { const connectionProvider = DatabaseModule_1.getConnectionProvider(); return { module: DatabaseModule_1, imports: [], providers: [connectionProvider], global: true, }; } static forFeature(models) { const connectionProvider = DatabaseModule_1.getConnectionProvider(); const modelProviders = models.map(({ name, schema }) => { DatabaseModule_1.logger.log(`Registering model: ${name} with schema: ${schema}`); if (name !== 'Tenant') { schema.plugin(tenantPlugin); } return { provide: name, scope: common_1.Scope.REQUEST, inject: [constants_1.TENANT_CONNECTION], useFactory: (conn) => conn.model(name, schema), }; }); return { module: DatabaseModule_1, providers: [connectionProvider, ...modelProviders], exports: modelProviders, }; } }; exports.DatabaseModule = DatabaseModule; DatabaseModule.logger = new common_1.Logger(DatabaseModule_1.name); exports.DatabaseModule = DatabaseModule = DatabaseModule_1 = __decorate([ (0, common_1.Module)({}) ], DatabaseModule); //# sourceMappingURL=database.module.js.map