@nestdevx/database
Version:
Database module designed to work with mongodb for multi-tenant NestJS applications.
113 lines • 5.17 kB
JavaScript
;
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