@culturefy/shared 1.0.63 → 1.0.64
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/build/cjs/enums/secretKeys.enum.js +0 -1
- package/build/cjs/enums/secretKeys.enum.js.map +1 -1
- package/build/cjs/interfaces/user.js.map +1 -1
- package/build/cjs/middlewares/verify-middleware.js +72 -18
- package/build/cjs/middlewares/verify-middleware.js.map +1 -1
- package/build/cjs/repositories/multi-tenant.repository.js +24 -11
- package/build/cjs/repositories/multi-tenant.repository.js.map +1 -1
- package/build/cjs/repositories/tenant-base.repository.js +7 -1
- package/build/cjs/repositories/tenant-base.repository.js.map +1 -1
- package/build/cjs/utils/initializers.js +11 -5
- package/build/cjs/utils/initializers.js.map +1 -1
- package/build/esm/enums/secretKeys.enum.js +0 -1
- package/build/esm/enums/secretKeys.enum.js.map +1 -1
- package/build/esm/interfaces/user.js.map +1 -1
- package/build/esm/middlewares/verify-middleware.js +74 -20
- package/build/esm/middlewares/verify-middleware.js.map +1 -1
- package/build/esm/repositories/multi-tenant.repository.js +24 -11
- package/build/esm/repositories/multi-tenant.repository.js.map +1 -1
- package/build/esm/repositories/tenant-base.repository.js +7 -1
- package/build/esm/repositories/tenant-base.repository.js.map +1 -1
- package/build/esm/utils/initializers.js +11 -5
- package/build/esm/utils/initializers.js.map +1 -1
- package/build/src/enums/secretKeys.enum.d.ts +0 -1
- package/build/src/enums/secretKeys.enum.js +0 -1
- package/build/src/enums/secretKeys.enum.js.map +1 -1
- package/build/src/middlewares/verify-middleware.js +79 -36
- package/build/src/middlewares/verify-middleware.js.map +1 -1
- package/build/src/repositories/multi-tenant.repository.d.ts +1 -0
- package/build/src/repositories/multi-tenant.repository.js +24 -11
- package/build/src/repositories/multi-tenant.repository.js.map +1 -1
- package/build/src/repositories/tenant-base.repository.d.ts +1 -0
- package/build/src/repositories/tenant-base.repository.js +18 -0
- package/build/src/repositories/tenant-base.repository.js.map +1 -1
- package/build/src/utils/initializers.d.ts +1 -0
- package/build/src/utils/initializers.js +11 -5
- package/build/src/utils/initializers.js.map +1 -1
- package/package.json +1 -1
|
@@ -52,10 +52,21 @@ export let MultiTenantRepository = (_dec = Cacheable({
|
|
|
52
52
|
this.serviceDBType = serviceDBType != null ? serviceDBType : "main";
|
|
53
53
|
this.tenantBridgeConfig = _extends({
|
|
54
54
|
tenantBridgeEnvKey: "TENANT_BRIDGE_DB_URI",
|
|
55
|
-
tenantBridgeSecretKey: AzureSecretKeysEnum.
|
|
55
|
+
tenantBridgeSecretKey: AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE
|
|
56
56
|
}, config);
|
|
57
57
|
this.connectionPromise = this.ensureClientConnection();
|
|
58
58
|
}
|
|
59
|
+
getConnectionLogLabel(connectionString) {
|
|
60
|
+
const match = connectionString.match(/\/([^/?]+)(\?|$)/);
|
|
61
|
+
const dbName = (match == null ? void 0 : match[1]) || "unknown";
|
|
62
|
+
if (dbName.toLowerCase().includes("tenantbridge")) {
|
|
63
|
+
return "TenantBridge-DB";
|
|
64
|
+
}
|
|
65
|
+
if (dbName.toLowerCase().includes("user")) {
|
|
66
|
+
return "Auth-DB";
|
|
67
|
+
}
|
|
68
|
+
return `${dbName}-DB`;
|
|
69
|
+
}
|
|
59
70
|
getEncryptionIv() {
|
|
60
71
|
const iv = process.env.DB_CONNECTION_STRING_ENCRYPTION_IV;
|
|
61
72
|
if (!iv) {
|
|
@@ -83,7 +94,8 @@ export let MultiTenantRepository = (_dec = Cacheable({
|
|
|
83
94
|
if (existing && existing.connection.readyState === 1) {
|
|
84
95
|
return existing;
|
|
85
96
|
}
|
|
86
|
-
this.
|
|
97
|
+
const dbLabel = this.getConnectionLogLabel(connectionString);
|
|
98
|
+
this.context.info(`Initializing database connection (${dbLabel})...`);
|
|
87
99
|
const instance = new mongoose.Mongoose();
|
|
88
100
|
try {
|
|
89
101
|
await instance.connect(connectionString, {
|
|
@@ -91,11 +103,11 @@ export let MultiTenantRepository = (_dec = Cacheable({
|
|
|
91
103
|
connectTimeoutMS: 10000,
|
|
92
104
|
socketTimeoutMS: 45000
|
|
93
105
|
});
|
|
94
|
-
this.context.info(`✅ MongoDB connected successfully ${
|
|
106
|
+
this.context.info(`✅ MongoDB connected successfully (${dbLabel})`);
|
|
95
107
|
MultiTenantRepository.connections.set(connectionString, instance);
|
|
96
108
|
return instance;
|
|
97
109
|
} catch (err) {
|
|
98
|
-
this.context.error(`❌ MongoDB connection error for ${
|
|
110
|
+
this.context.error(`❌ MongoDB connection error for (${dbLabel})`, {
|
|
99
111
|
message: err.message,
|
|
100
112
|
name: err.name,
|
|
101
113
|
code: err.code,
|
|
@@ -117,7 +129,7 @@ export let MultiTenantRepository = (_dec = Cacheable({
|
|
|
117
129
|
return localUri;
|
|
118
130
|
}
|
|
119
131
|
const vault = process.env.AZURE_KEY_VAULT_NAME || "";
|
|
120
|
-
const secretKey = this.tenantBridgeConfig.tenantBridgeSecretKey || AzureSecretKeysEnum.
|
|
132
|
+
const secretKey = this.tenantBridgeConfig.tenantBridgeSecretKey || AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE;
|
|
121
133
|
const dbUrl = await getAzureVaultSecretByKey(this.context, vault, secretKey);
|
|
122
134
|
if (!dbUrl) {
|
|
123
135
|
throw new Error("TenantBridge database connection string not found");
|
|
@@ -174,6 +186,9 @@ export let MultiTenantRepository = (_dec = Cacheable({
|
|
|
174
186
|
throw new Error(`DB connection string encryption key must be 16 bytes for aes-128-cbc (got ${utf8Key.length})`);
|
|
175
187
|
}
|
|
176
188
|
async getClientDbConnectionString(businessId, appId, serviceDBType) {
|
|
189
|
+
if (!appId) {
|
|
190
|
+
throw new Error("appId is required to resolve tenant client database");
|
|
191
|
+
}
|
|
177
192
|
const resolvedServiceDbType = serviceDBType != null ? serviceDBType : "main";
|
|
178
193
|
const tenantBridgeUrl = await this.getTenantBridgeSrvDbConnectionString();
|
|
179
194
|
const connection = await this.getOrCreateCachedConnection(tenantBridgeUrl);
|
|
@@ -181,16 +196,14 @@ export let MultiTenantRepository = (_dec = Cacheable({
|
|
|
181
196
|
const filter = {
|
|
182
197
|
businessId: this.toObjectId(businessId, "businessId")
|
|
183
198
|
};
|
|
184
|
-
|
|
185
|
-
filter.appId = appId;
|
|
186
|
-
}
|
|
199
|
+
filter.appId = appId;
|
|
187
200
|
filter.serviceDBType = resolvedServiceDbType;
|
|
188
201
|
const configMapping = await ConfigMapping.findOne(filter).lean().exec();
|
|
189
202
|
if (!(configMapping != null && configMapping.connectionString)) {
|
|
190
203
|
throw new Error("Config mapping not found for this business");
|
|
191
204
|
}
|
|
192
205
|
const decryptedConnectionString = await this.decryptConnectionString(configMapping.connectionString);
|
|
193
|
-
this.context.info(
|
|
206
|
+
this.context.info("Resolved tenant database mapping from TenantBridge");
|
|
194
207
|
return decryptedConnectionString;
|
|
195
208
|
}
|
|
196
209
|
getConnection() {
|
|
@@ -217,9 +230,9 @@ export let MultiTenantRepository = (_dec = Cacheable({
|
|
|
217
230
|
if (!existing) return;
|
|
218
231
|
try {
|
|
219
232
|
await existing.disconnect();
|
|
220
|
-
this.context.info(`✅ Disconnected from database
|
|
233
|
+
this.context.info(`✅ Disconnected from database (${this.getConnectionLogLabel(connectionString)})`);
|
|
221
234
|
} catch (error) {
|
|
222
|
-
this.context.error(`❌ Error disconnecting from database
|
|
235
|
+
this.context.error(`❌ Error disconnecting from database (${this.getConnectionLogLabel(connectionString)})`, error);
|
|
223
236
|
} finally {
|
|
224
237
|
MultiTenantRepository.connections.delete(connectionString);
|
|
225
238
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi-tenant.repository.js","names":["mongoose","Types","crypto","DefaultAzureCredential","SecretClient","AzureSecretKeysEnum","Cacheable","createCache","getAzureVaultSecretByKey","CONFIG_MAPPING_COLLECTION_NAME","CONFIG_MAPPING_DOCUMENT_NAME","ConfigMappingModel","tenantDbCache","tenantBridgeCache","encryptionKeyCache","WithTenantDb","_target","_propertyKey","descriptor","value","originalMethod","args","ensureClientConnection","apply","MultiTenantRepository","_dec","cache","key","getContext","instance","context","_dec2","_dec3","businessId","appId","serviceDbType","_class","_MultiTenantRepository","constructor","config","serviceDBType","tenantBridgeConfig","dbConnectionEncryptionKey","clientConnectionString","connectionPromise","_extends","tenantBridgeEnvKey","tenantBridgeSecretKey","DB_CONNECTING_STRING_TENANT_BRIDGE","getEncryptionIv","iv","process","env","DB_CONNECTION_STRING_ENCRYPTION_IV","Buffer","alloc","normalizeFixedSize","label","utf8Value","from","length","base64Value","hexValue","Error","getOrCreateCachedConnection","connectionString","existing","connections","get","connection","readyState","info","Mongoose","connect","serverSelectionTimeoutMS","connectTimeoutMS","socketTimeoutMS","set","err","error","message","name","code","stack","toObjectId","id","fieldName","ObjectId","isValid","getTenantBridgeSrvDbConnectionString","envKey","localUri","undefined","vault","AZURE_KEY_VAULT_NAME","secretKey","dbUrl","getDbConnectionEncryptionKey","_secret$value","DB_CONNECTION_STRING_ENCRYPTION_KEY","vaultUrl","credential","client","secret","getSecret","decryptConnectionString","encryptedValue","keyBuffer","normalizeEncryptionKey","ivBuffer","decipher","createDecipheriv","decrypted","update","final","utf8Key","base64Key","hexKey","getClientDbConnectionString","resolvedServiceDbType","tenantBridgeUrl","ConfigMapping","getModel","schema","filter","configMapping","findOne","lean","exec","decryptedConnectionString","getConnection","clientDbUrl","disconnectByConnectionString","disconnect","delete","disconnectClient","getTenantModel","modelName","collectionName","model","models","Map","_applyDecoratedDescriptor","prototype","Object","getOwnPropertyDescriptor","TenantModelRepository","modelDef","dbModel"],"sources":["../../../src/repositories/multi-tenant.repository.ts"],"sourcesContent":["import mongoose, { Model, Schema, Types } from \"mongoose\";\nimport * as crypto from \"crypto\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { DefaultAzureCredential } from \"@azure/identity\";\nimport { SecretClient } from \"@azure/keyvault-secrets\";\nimport { AzureSecretKeysEnum } from \"../enums\";\nimport { Cacheable, createCache } from \"../utils/cache\";\nimport { getAzureVaultSecretByKey } from \"../utils/secrets\";\nimport {\n CONFIG_MAPPING_COLLECTION_NAME,\n CONFIG_MAPPING_DOCUMENT_NAME,\n ConfigMappingModel,\n IConfigMapping,\n} from \"../models/config-mapping.model\";\n\ntype ConnectionMap = Map<string, mongoose.Mongoose>;\n\ntype TenantBridgeConfig = {\n tenantBridgeEnvKey?: string;\n tenantBridgeSecretKey?: AzureSecretKeysEnum;\n};\n\nconst tenantDbCache = createCache(\"tenant-db\", 600);\nconst tenantBridgeCache = createCache(\"tenant-bridge-db-connection-string\", 1800);\nconst encryptionKeyCache = createCache(\"db-enc-key\", 1800);\n\n/**\n * Decorator that ensures tenant DB is connected before the method runs.\n */\nexport function WithTenantDb(\n _target: any,\n _propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<any>>,\n): void {\n if (!descriptor.value) return;\n const originalMethod = descriptor.value;\n descriptor.value = async function (\n this: MultiTenantRepository,\n ...args: any[]\n ) {\n await this.ensureClientConnection();\n return originalMethod.apply(this, args);\n };\n}\n\nexport class MultiTenantRepository {\n private static connections: ConnectionMap = new Map();\n private readonly context: InvocationContext;\n private readonly tenantBridgeConfig: TenantBridgeConfig;\n private readonly businessId: string;\n private readonly appId?: string;\n private readonly serviceDBType?: string;\n private dbConnectionEncryptionKey?: string;\n private clientConnectionString?: string;\n private connectionPromise?: Promise<mongoose.Mongoose>;\n\n constructor(\n context: InvocationContext,\n businessId: string,\n appId?: string,\n config?: TenantBridgeConfig,\n serviceDBType?: string,\n ) {\n this.context = context;\n this.businessId = businessId;\n this.appId = appId;\n this.serviceDBType = serviceDBType ?? \"main\";\n this.tenantBridgeConfig = {\n tenantBridgeEnvKey: \"TENANT_BRIDGE_DB_URI\",\n tenantBridgeSecretKey: AzureSecretKeysEnum.DB_CONNECTING_STRING_TENANT_BRIDGE,\n ...config,\n };\n\n this.connectionPromise = this.ensureClientConnection();\n }\n\n private getEncryptionIv(): Buffer {\n const iv = process.env.DB_CONNECTION_STRING_ENCRYPTION_IV;\n if (!iv) {\n return Buffer.alloc(16, 0);\n }\n return this.normalizeFixedSize(iv, \"IV\");\n }\n\n private normalizeFixedSize(value: string, label: string): Buffer {\n const utf8Value = Buffer.from(value, \"utf8\");\n if (utf8Value.length === 16) {\n return utf8Value;\n }\n\n const base64Value = Buffer.from(value, \"base64\");\n if (base64Value.length === 16) {\n return base64Value;\n }\n\n const hexValue = Buffer.from(value, \"hex\");\n if (hexValue.length === 16) {\n return hexValue;\n }\n\n throw new Error(\n `${label} must be 16 bytes for aes-128-cbc (got ${utf8Value.length})`,\n );\n }\n\n private async getOrCreateCachedConnection(\n connectionString: string,\n ): Promise<mongoose.Mongoose> {\n const existing = MultiTenantRepository.connections.get(connectionString);\n if (existing && existing.connection.readyState === 1) {\n return existing;\n }\n\n this.context.info(`Initializing database connection... ${connectionString}`);\n const instance = new mongoose.Mongoose();\n\n try {\n await instance.connect(connectionString, {\n serverSelectionTimeoutMS: 10000,\n connectTimeoutMS: 10000,\n socketTimeoutMS: 45000,\n });\n this.context.info(`✅ MongoDB connected successfully ${connectionString}`);\n MultiTenantRepository.connections.set(connectionString, instance);\n return instance;\n } catch (err: any) {\n this.context.error(\n `❌ MongoDB connection error for ${connectionString}`,\n {\n message: err.message,\n name: err.name,\n code: err.code,\n stack: err.stack,\n },\n );\n throw new Error(`Failed to connect to MongoDB: ${err.message}`);\n }\n }\n\n private toObjectId(id: string, fieldName: string): Types.ObjectId {\n if (!Types.ObjectId.isValid(id)) {\n throw new Error(`Invalid ${fieldName}`);\n }\n return new Types.ObjectId(id);\n }\n\n @Cacheable({\n cache: tenantBridgeCache,\n key: () => [\"tenant-bridge\"],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n async getTenantBridgeSrvDbConnectionString(): Promise<string> {\n const envKey = this.tenantBridgeConfig.tenantBridgeEnvKey;\n const localUri =\n (envKey ? process.env[envKey] : undefined);\n\n if (localUri) {\n return localUri;\n }\n\n const vault = process.env.AZURE_KEY_VAULT_NAME || \"\";\n const secretKey =\n this.tenantBridgeConfig.tenantBridgeSecretKey ||\n AzureSecretKeysEnum.DB_CONNECTING_STRING_TENANT_BRIDGE;\n\n const dbUrl = await getAzureVaultSecretByKey(\n this.context,\n vault,\n secretKey,\n );\n if (!dbUrl) {\n throw new Error(\"TenantBridge database connection string not found\");\n }\n return dbUrl;\n }\n\n @Cacheable({\n cache: encryptionKeyCache,\n key: () => [\"key\"],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n private async getDbConnectionEncryptionKey(): Promise<string> {\n if (this.dbConnectionEncryptionKey) {\n return this.dbConnectionEncryptionKey;\n }\n\n const envKey = process.env.DB_CONNECTION_STRING_ENCRYPTION_KEY;\n if (envKey) {\n this.dbConnectionEncryptionKey = envKey;\n return envKey;\n }\n\n const vault = process.env.AZURE_KEY_VAULT_NAME || \"\";\n if (!vault) {\n throw new Error(\"AZURE_KEY_VAULT_NAME is required to fetch encryption key\");\n }\n const vaultUrl = `https://${vault}.vault.azure.net`;\n const credential = new DefaultAzureCredential();\n const client = new SecretClient(vaultUrl, credential);\n const secret = await client.getSecret(\"DB-CONNECTION-STRING-ENCRYPTION-KEY\");\n const key = secret.value ?? \"\";\n if (!key) {\n throw new Error(\"DB connection string encryption key not found\");\n }\n this.dbConnectionEncryptionKey = key;\n return key;\n }\n\n private async decryptConnectionString(encryptedValue: string): Promise<string> {\n const key = await this.getDbConnectionEncryptionKey();\n const keyBuffer = this.normalizeEncryptionKey(key);\n\n const ivBuffer = this.getEncryptionIv();\n const decipher = crypto.createDecipheriv(\"aes-128-cbc\", keyBuffer, ivBuffer);\n let decrypted = decipher.update(encryptedValue, \"base64\", \"utf8\");\n decrypted += decipher.final(\"utf8\");\n return decrypted;\n }\n\n private normalizeEncryptionKey(key: string): Buffer {\n const utf8Key = Buffer.from(key, \"utf8\");\n if (utf8Key.length === 16) {\n return utf8Key;\n }\n\n const base64Key = Buffer.from(key, \"base64\");\n if (base64Key.length === 16) {\n return base64Key;\n }\n\n const hexKey = Buffer.from(key, \"hex\");\n if (hexKey.length === 16) {\n return hexKey;\n }\n\n throw new Error(\n `DB connection string encryption key must be 16 bytes for aes-128-cbc (got ${utf8Key.length})`,\n );\n }\n\n @Cacheable({\n cache: tenantDbCache,\n key: (businessId: string, appId?: string, serviceDbType?: string) => [\n businessId,\n appId,\n serviceDbType,\n ],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n async getClientDbConnectionString(\n businessId: string,\n appId?: string,\n serviceDBType?: string,\n ): Promise<string> {\n const resolvedServiceDbType = serviceDBType ?? \"main\";\n const tenantBridgeUrl = await this.getTenantBridgeSrvDbConnectionString();\n const connection = await this.getOrCreateCachedConnection(tenantBridgeUrl);\n\n const ConfigMapping = this.getModel(\n connection,\n CONFIG_MAPPING_DOCUMENT_NAME,\n ConfigMappingModel.schema,\n CONFIG_MAPPING_COLLECTION_NAME,\n ) as Model<IConfigMapping>;\n\n const filter: Record<string, unknown> = {\n businessId: this.toObjectId(businessId, \"businessId\"),\n };\n if (appId) {\n filter.appId = appId;\n }\n filter.serviceDBType = resolvedServiceDbType;\n\n const configMapping =\n (await ConfigMapping.findOne(filter).lean().exec()) as\n | IConfigMapping\n | null;\n if (!configMapping?.connectionString) {\n throw new Error(\"Config mapping not found for this business\");\n }\n const decryptedConnectionString = await this.decryptConnectionString(\n configMapping.connectionString,\n );\n this.context.info(\n `Resolved tenant DB connection string from bridge: ${decryptedConnectionString}`,\n );\n return decryptedConnectionString;\n }\n\n protected getConnection(): mongoose.Mongoose | undefined {\n if (!this.clientConnectionString) return undefined;\n return MultiTenantRepository.connections.get(this.clientConnectionString);\n }\n\n protected async ensureClientConnection(): Promise<mongoose.Mongoose> {\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n if (this.clientConnectionString) {\n const existing = this.getConnection();\n if (existing && existing.connection.readyState === 1) {\n return existing;\n }\n }\n\n const clientDbUrl = await this.getClientDbConnectionString(\n this.businessId,\n this.appId,\n this.serviceDBType,\n );\n this.clientConnectionString = clientDbUrl;\n this.connectionPromise = this.getOrCreateCachedConnection(clientDbUrl);\n return this.connectionPromise;\n }\n\n async disconnectByConnectionString(connectionString: string): Promise<void> {\n const existing = MultiTenantRepository.connections.get(connectionString);\n if (!existing) return;\n try {\n await existing.disconnect();\n this.context.info(`✅ Disconnected from database: ${connectionString}`);\n } catch (error) {\n this.context.error(`❌ Error disconnecting from database: ${connectionString}`, error);\n } finally {\n MultiTenantRepository.connections.delete(connectionString);\n }\n }\n\n async disconnectClient(): Promise<void> {\n const clientDbUrl = await this.getClientDbConnectionString(\n this.businessId,\n this.appId,\n );\n await this.disconnectByConnectionString(clientDbUrl);\n this.clientConnectionString = undefined;\n this.connectionPromise = undefined;\n }\n\n protected getTenantModel(\n modelName: string,\n schema: Schema<any>,\n collectionName?: string,\n ): Model<any> {\n const connection = this.getConnection();\n if (!connection) {\n throw new Error(\"database connection not established\");\n }\n return this.getModel(connection, modelName, schema, collectionName);\n }\n\n protected model<T>(model: Model<T>, collectionName?: string): Model<T> {\n return this.getTenantModel(\n model.modelName,\n model.schema,\n collectionName,\n ) as Model<T>;\n }\n\n protected getModel(\n connection: mongoose.Mongoose,\n modelName: string,\n schema: Schema<any>,\n collectionName?: string,\n ): Model<any> {\n if (connection.models[modelName]) {\n return connection.models[modelName] as Model<any>;\n }\n return connection.model(modelName, schema, collectionName);\n }\n}\n\nexport abstract class TenantModelRepository<T> extends MultiTenantRepository {\n protected abstract readonly modelDef: Model<T>;\n\n protected get dbModel(): Model<T> {\n return this.model(this.modelDef);\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"multi-tenant.repository.js","names":["mongoose","Types","crypto","DefaultAzureCredential","SecretClient","AzureSecretKeysEnum","Cacheable","createCache","getAzureVaultSecretByKey","CONFIG_MAPPING_COLLECTION_NAME","CONFIG_MAPPING_DOCUMENT_NAME","ConfigMappingModel","tenantDbCache","tenantBridgeCache","encryptionKeyCache","WithTenantDb","_target","_propertyKey","descriptor","value","originalMethod","args","ensureClientConnection","apply","MultiTenantRepository","_dec","cache","key","getContext","instance","context","_dec2","_dec3","businessId","appId","serviceDbType","_class","_MultiTenantRepository","constructor","config","serviceDBType","tenantBridgeConfig","dbConnectionEncryptionKey","clientConnectionString","connectionPromise","_extends","tenantBridgeEnvKey","tenantBridgeSecretKey","DB_CONNECTION_STRING_TENANT_BRIDGE","getConnectionLogLabel","connectionString","match","dbName","toLowerCase","includes","getEncryptionIv","iv","process","env","DB_CONNECTION_STRING_ENCRYPTION_IV","Buffer","alloc","normalizeFixedSize","label","utf8Value","from","length","base64Value","hexValue","Error","getOrCreateCachedConnection","existing","connections","get","connection","readyState","dbLabel","info","Mongoose","connect","serverSelectionTimeoutMS","connectTimeoutMS","socketTimeoutMS","set","err","error","message","name","code","stack","toObjectId","id","fieldName","ObjectId","isValid","getTenantBridgeSrvDbConnectionString","envKey","localUri","undefined","vault","AZURE_KEY_VAULT_NAME","secretKey","dbUrl","getDbConnectionEncryptionKey","_secret$value","DB_CONNECTION_STRING_ENCRYPTION_KEY","vaultUrl","credential","client","secret","getSecret","decryptConnectionString","encryptedValue","keyBuffer","normalizeEncryptionKey","ivBuffer","decipher","createDecipheriv","decrypted","update","final","utf8Key","base64Key","hexKey","getClientDbConnectionString","resolvedServiceDbType","tenantBridgeUrl","ConfigMapping","getModel","schema","filter","configMapping","findOne","lean","exec","decryptedConnectionString","getConnection","clientDbUrl","disconnectByConnectionString","disconnect","delete","disconnectClient","getTenantModel","modelName","collectionName","model","models","Map","_applyDecoratedDescriptor","prototype","Object","getOwnPropertyDescriptor","TenantModelRepository","modelDef","dbModel"],"sources":["../../../src/repositories/multi-tenant.repository.ts"],"sourcesContent":["import mongoose, { Model, Schema, Types } from \"mongoose\";\nimport * as crypto from \"crypto\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { DefaultAzureCredential } from \"@azure/identity\";\nimport { SecretClient } from \"@azure/keyvault-secrets\";\nimport { AzureSecretKeysEnum } from \"../enums\";\nimport { Cacheable, createCache } from \"../utils/cache\";\nimport { getAzureVaultSecretByKey } from \"../utils/secrets\";\nimport {\n CONFIG_MAPPING_COLLECTION_NAME,\n CONFIG_MAPPING_DOCUMENT_NAME,\n ConfigMappingModel,\n IConfigMapping,\n} from \"../models/config-mapping.model\";\n\ntype ConnectionMap = Map<string, mongoose.Mongoose>;\n\ntype TenantBridgeConfig = {\n tenantBridgeEnvKey?: string;\n tenantBridgeSecretKey?: AzureSecretKeysEnum;\n};\n\nconst tenantDbCache = createCache(\"tenant-db\", 600);\nconst tenantBridgeCache = createCache(\"tenant-bridge-db-connection-string\", 1800);\nconst encryptionKeyCache = createCache(\"db-enc-key\", 1800);\n\n/**\n * Decorator that ensures tenant DB is connected before the method runs.\n */\nexport function WithTenantDb(\n _target: any,\n _propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<any>>,\n): void {\n if (!descriptor.value) return;\n const originalMethod = descriptor.value;\n descriptor.value = async function (\n this: MultiTenantRepository,\n ...args: any[]\n ) {\n await this.ensureClientConnection();\n return originalMethod.apply(this, args);\n };\n}\n\nexport class MultiTenantRepository {\n private static connections: ConnectionMap = new Map();\n private readonly context: InvocationContext;\n private readonly tenantBridgeConfig: TenantBridgeConfig;\n private readonly businessId: string;\n private readonly appId?: string;\n private readonly serviceDBType?: string;\n private dbConnectionEncryptionKey?: string;\n private clientConnectionString?: string;\n private connectionPromise?: Promise<mongoose.Mongoose>;\n\n constructor(\n context: InvocationContext,\n businessId: string,\n appId?: string,\n config?: TenantBridgeConfig,\n serviceDBType?: string,\n ) {\n this.context = context;\n this.businessId = businessId;\n this.appId = appId;\n this.serviceDBType = serviceDBType ?? \"main\";\n this.tenantBridgeConfig = {\n tenantBridgeEnvKey: \"TENANT_BRIDGE_DB_URI\",\n tenantBridgeSecretKey: AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE,\n ...config,\n };\n\n this.connectionPromise = this.ensureClientConnection();\n }\n\n private getConnectionLogLabel(connectionString: string): string {\n const match = connectionString.match(/\\/([^/?]+)(\\?|$)/);\n const dbName = match?.[1] || \"unknown\";\n if (dbName.toLowerCase().includes(\"tenantbridge\")) {\n return \"TenantBridge-DB\";\n }\n if (dbName.toLowerCase().includes(\"user\")) {\n return \"Auth-DB\";\n }\n return `${dbName}-DB`;\n }\n\n private getEncryptionIv(): Buffer {\n const iv = process.env.DB_CONNECTION_STRING_ENCRYPTION_IV;\n if (!iv) {\n return Buffer.alloc(16, 0);\n }\n return this.normalizeFixedSize(iv, \"IV\");\n }\n\n private normalizeFixedSize(value: string, label: string): Buffer {\n const utf8Value = Buffer.from(value, \"utf8\");\n if (utf8Value.length === 16) {\n return utf8Value;\n }\n\n const base64Value = Buffer.from(value, \"base64\");\n if (base64Value.length === 16) {\n return base64Value;\n }\n\n const hexValue = Buffer.from(value, \"hex\");\n if (hexValue.length === 16) {\n return hexValue;\n }\n\n throw new Error(\n `${label} must be 16 bytes for aes-128-cbc (got ${utf8Value.length})`,\n );\n }\n\n private async getOrCreateCachedConnection(\n connectionString: string,\n ): Promise<mongoose.Mongoose> {\n const existing = MultiTenantRepository.connections.get(connectionString);\n if (existing && existing.connection.readyState === 1) {\n return existing;\n }\n\n const dbLabel = this.getConnectionLogLabel(connectionString);\n this.context.info(`Initializing database connection (${dbLabel})...`);\n const instance = new mongoose.Mongoose();\n\n try {\n await instance.connect(connectionString, {\n serverSelectionTimeoutMS: 10000,\n connectTimeoutMS: 10000,\n socketTimeoutMS: 45000,\n });\n this.context.info(`✅ MongoDB connected successfully (${dbLabel})`);\n MultiTenantRepository.connections.set(connectionString, instance);\n return instance;\n } catch (err: any) {\n this.context.error(\n `❌ MongoDB connection error for (${dbLabel})`,\n {\n message: err.message,\n name: err.name,\n code: err.code,\n stack: err.stack,\n },\n );\n throw new Error(`Failed to connect to MongoDB: ${err.message}`);\n }\n }\n\n private toObjectId(id: string, fieldName: string): Types.ObjectId {\n if (!Types.ObjectId.isValid(id)) {\n throw new Error(`Invalid ${fieldName}`);\n }\n return new Types.ObjectId(id);\n }\n\n @Cacheable({\n cache: tenantBridgeCache,\n key: () => [\"tenant-bridge\"],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n async getTenantBridgeSrvDbConnectionString(): Promise<string> {\n const envKey = this.tenantBridgeConfig.tenantBridgeEnvKey;\n const localUri =\n (envKey ? process.env[envKey] : undefined);\n\n if (localUri) {\n return localUri;\n }\n\n const vault = process.env.AZURE_KEY_VAULT_NAME || \"\";\n const secretKey =\n this.tenantBridgeConfig.tenantBridgeSecretKey ||\n AzureSecretKeysEnum.DB_CONNECTION_STRING_TENANT_BRIDGE;\n\n const dbUrl = await getAzureVaultSecretByKey(\n this.context,\n vault,\n secretKey,\n );\n if (!dbUrl) {\n throw new Error(\"TenantBridge database connection string not found\");\n }\n return dbUrl;\n }\n\n @Cacheable({\n cache: encryptionKeyCache,\n key: () => [\"key\"],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n private async getDbConnectionEncryptionKey(): Promise<string> {\n if (this.dbConnectionEncryptionKey) {\n return this.dbConnectionEncryptionKey;\n }\n\n const envKey = process.env.DB_CONNECTION_STRING_ENCRYPTION_KEY;\n if (envKey) {\n this.dbConnectionEncryptionKey = envKey;\n return envKey;\n }\n\n const vault = process.env.AZURE_KEY_VAULT_NAME || \"\";\n if (!vault) {\n throw new Error(\"AZURE_KEY_VAULT_NAME is required to fetch encryption key\");\n }\n const vaultUrl = `https://${vault}.vault.azure.net`;\n const credential = new DefaultAzureCredential();\n const client = new SecretClient(vaultUrl, credential);\n const secret = await client.getSecret(\"DB-CONNECTION-STRING-ENCRYPTION-KEY\");\n const key = secret.value ?? \"\";\n if (!key) {\n throw new Error(\"DB connection string encryption key not found\");\n }\n this.dbConnectionEncryptionKey = key;\n return key;\n }\n\n private async decryptConnectionString(encryptedValue: string): Promise<string> {\n const key = await this.getDbConnectionEncryptionKey();\n const keyBuffer = this.normalizeEncryptionKey(key);\n\n const ivBuffer = this.getEncryptionIv();\n const decipher = crypto.createDecipheriv(\"aes-128-cbc\", keyBuffer, ivBuffer);\n let decrypted = decipher.update(encryptedValue, \"base64\", \"utf8\");\n decrypted += decipher.final(\"utf8\");\n return decrypted;\n }\n\n private normalizeEncryptionKey(key: string): Buffer {\n const utf8Key = Buffer.from(key, \"utf8\");\n if (utf8Key.length === 16) {\n return utf8Key;\n }\n\n const base64Key = Buffer.from(key, \"base64\");\n if (base64Key.length === 16) {\n return base64Key;\n }\n\n const hexKey = Buffer.from(key, \"hex\");\n if (hexKey.length === 16) {\n return hexKey;\n }\n\n throw new Error(\n `DB connection string encryption key must be 16 bytes for aes-128-cbc (got ${utf8Key.length})`,\n );\n }\n\n @Cacheable({\n cache: tenantDbCache,\n key: (businessId: string, appId?: string, serviceDbType?: string) => [\n businessId,\n appId,\n serviceDbType,\n ],\n getContext: (instance: unknown) =>\n (instance as MultiTenantRepository).context,\n })\n async getClientDbConnectionString(\n businessId: string,\n appId?: string,\n serviceDBType?: string,\n ): Promise<string> {\n if (!appId) {\n throw new Error(\"appId is required to resolve tenant client database\");\n }\n const resolvedServiceDbType = serviceDBType ?? \"main\";\n const tenantBridgeUrl = await this.getTenantBridgeSrvDbConnectionString();\n const connection = await this.getOrCreateCachedConnection(tenantBridgeUrl);\n\n const ConfigMapping = this.getModel(\n connection,\n CONFIG_MAPPING_DOCUMENT_NAME,\n ConfigMappingModel.schema,\n CONFIG_MAPPING_COLLECTION_NAME,\n ) as Model<IConfigMapping>;\n\n const filter: Record<string, unknown> = {\n businessId: this.toObjectId(businessId, \"businessId\"),\n };\n filter.appId = appId;\n filter.serviceDBType = resolvedServiceDbType;\n\n const configMapping =\n (await ConfigMapping.findOne(filter).lean().exec()) as\n | IConfigMapping\n | null;\n if (!configMapping?.connectionString) {\n throw new Error(\"Config mapping not found for this business\");\n }\n const decryptedConnectionString = await this.decryptConnectionString(\n configMapping.connectionString,\n );\n this.context.info(\"Resolved tenant database mapping from TenantBridge\");\n return decryptedConnectionString;\n }\n\n protected getConnection(): mongoose.Mongoose | undefined {\n if (!this.clientConnectionString) return undefined;\n return MultiTenantRepository.connections.get(this.clientConnectionString);\n }\n\n protected async ensureClientConnection(): Promise<mongoose.Mongoose> {\n if (this.connectionPromise) {\n return this.connectionPromise;\n }\n\n if (this.clientConnectionString) {\n const existing = this.getConnection();\n if (existing && existing.connection.readyState === 1) {\n return existing;\n }\n }\n\n const clientDbUrl = await this.getClientDbConnectionString(\n this.businessId,\n this.appId,\n this.serviceDBType,\n );\n this.clientConnectionString = clientDbUrl;\n this.connectionPromise = this.getOrCreateCachedConnection(clientDbUrl);\n return this.connectionPromise;\n }\n\n async disconnectByConnectionString(connectionString: string): Promise<void> {\n const existing = MultiTenantRepository.connections.get(connectionString);\n if (!existing) return;\n try {\n await existing.disconnect();\n this.context.info(`✅ Disconnected from database (${this.getConnectionLogLabel(connectionString)})`);\n } catch (error) {\n this.context.error(`❌ Error disconnecting from database (${this.getConnectionLogLabel(connectionString)})`, error);\n } finally {\n MultiTenantRepository.connections.delete(connectionString);\n }\n }\n\n async disconnectClient(): Promise<void> {\n const clientDbUrl = await this.getClientDbConnectionString(\n this.businessId,\n this.appId,\n );\n await this.disconnectByConnectionString(clientDbUrl);\n this.clientConnectionString = undefined;\n this.connectionPromise = undefined;\n }\n\n protected getTenantModel(\n modelName: string,\n schema: Schema<any>,\n collectionName?: string,\n ): Model<any> {\n const connection = this.getConnection();\n if (!connection) {\n throw new Error(\"database connection not established\");\n }\n return this.getModel(connection, modelName, schema, collectionName);\n }\n\n protected model<T>(model: Model<T>, collectionName?: string): Model<T> {\n return this.getTenantModel(\n model.modelName,\n model.schema,\n collectionName,\n ) as Model<T>;\n }\n\n protected getModel(\n connection: mongoose.Mongoose,\n modelName: string,\n schema: Schema<any>,\n collectionName?: string,\n ): Model<any> {\n if (connection.models[modelName]) {\n return connection.models[modelName] as Model<any>;\n }\n return connection.model(modelName, schema, collectionName);\n }\n}\n\nexport abstract class TenantModelRepository<T> extends MultiTenantRepository {\n protected abstract readonly modelDef: Model<T>;\n\n protected get dbModel(): Model<T> {\n return this.model(this.modelDef);\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -15,6 +15,12 @@ export let TenantBaseRepository = (_class = class TenantBaseRepository extends T
|
|
|
15
15
|
async createMany(body) {
|
|
16
16
|
return this.dbModel.insertMany(body);
|
|
17
17
|
}
|
|
18
|
+
async findAllWithPagination(query, page, limit, sort = {
|
|
19
|
+
createdAt: -1
|
|
20
|
+
}, projection = {}) {
|
|
21
|
+
const list = await this.dbModel.find(query, projection).sort(sort).skip((page - 1) * limit).limit(limit).lean().exec();
|
|
22
|
+
return list;
|
|
23
|
+
}
|
|
18
24
|
async count(query = {}) {
|
|
19
25
|
return this.dbModel.countDocuments(query).exec();
|
|
20
26
|
}
|
|
@@ -44,5 +50,5 @@ export let TenantBaseRepository = (_class = class TenantBaseRepository extends T
|
|
|
44
50
|
async deleteMany(query = {}) {
|
|
45
51
|
return this.dbModel.deleteMany(query).exec();
|
|
46
52
|
}
|
|
47
|
-
}, _applyDecoratedDescriptor(_class.prototype, "aggregate", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "aggregate"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "create", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "create"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "createMany", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "createMany"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "count", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "count"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "findById", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "findById"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "findOne", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "findOne"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "find", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "find"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateById", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "updateById"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateOne", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "updateOne"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateMany", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "updateMany"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "deleteById", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "deleteById"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "deleteMany", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "deleteMany"), _class.prototype), _class);
|
|
53
|
+
}, _applyDecoratedDescriptor(_class.prototype, "aggregate", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "aggregate"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "create", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "create"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "createMany", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "createMany"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "findAllWithPagination", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "findAllWithPagination"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "count", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "count"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "findById", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "findById"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "findOne", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "findOne"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "find", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "find"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateById", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "updateById"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateOne", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "updateOne"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "updateMany", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "updateMany"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "deleteById", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "deleteById"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "deleteMany", [WithTenantDb], Object.getOwnPropertyDescriptor(_class.prototype, "deleteMany"), _class.prototype), _class);
|
|
48
54
|
//# sourceMappingURL=tenant-base.repository.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tenant-base.repository.js","names":["TenantModelRepository","WithTenantDb","TenantBaseRepository","_class","constructor","args","modelDef","aggregate","pipeline","dbModel","exec","create","body","createMany","insertMany","
|
|
1
|
+
{"version":3,"file":"tenant-base.repository.js","names":["TenantModelRepository","WithTenantDb","TenantBaseRepository","_class","constructor","args","modelDef","aggregate","pipeline","dbModel","exec","create","body","createMany","insertMany","findAllWithPagination","query","page","limit","sort","createdAt","projection","list","find","skip","lean","count","countDocuments","findById","id","options","findOne","updateById","new","findByIdAndUpdate","updateOne","updateMany","deleteById","findByIdAndDelete","deleteMany","_applyDecoratedDescriptor","prototype","Object","getOwnPropertyDescriptor"],"sources":["../../../src/repositories/tenant-base.repository.ts"],"sourcesContent":["import {\n FilterQuery,\n Model,\n PipelineStage,\n ProjectionType,\n QueryOptions,\n UpdateQuery,\n} from \"mongoose\";\nimport { TenantModelRepository, WithTenantDb } from \"./multi-tenant.repository\";\n\nexport abstract class TenantBaseRepository<T> extends TenantModelRepository<T> {\n protected abstract readonly modelDef: Model<T>;\n\n @WithTenantDb\n async aggregate(\n pipeline: PipelineStage[],\n ): Promise<any[]> {\n return this.dbModel.aggregate(pipeline).exec();\n }\n\n @WithTenantDb\n async create(body: T): Promise<T> {\n return this.dbModel.create(body);\n }\n\n @WithTenantDb\n async createMany(body: T[]): Promise<T[]> {\n return this.dbModel.insertMany(body);\n }\n\n @WithTenantDb\n async findAllWithPagination(\n query: FilterQuery<T>,\n page: number,\n limit: number,\n sort: Record<string, 1 | -1> = { createdAt: -1 },\n projection: ProjectionType<T> = {},\n ): Promise<T[]> {\n const list = await this.dbModel\n .find(query, projection)\n .sort(sort)\n .skip((page - 1) * limit)\n .limit(limit)\n .lean()\n .exec();\n return list as T[];\n }\n\n @WithTenantDb\n async count(query: FilterQuery<T> = {}): Promise<number> {\n return this.dbModel.countDocuments(query).exec();\n }\n\n @WithTenantDb\n async findById(\n id: string,\n projection: ProjectionType<T> = {},\n options: QueryOptions<T> = {},\n ): Promise<T | null> {\n return this.dbModel.findById(id, projection, options).exec();\n }\n\n @WithTenantDb\n async findOne(\n query: FilterQuery<T>,\n projection: ProjectionType<T> = {},\n options: QueryOptions<T> = {},\n ): Promise<T | null> {\n return this.dbModel.findOne(query, projection, options).exec();\n }\n\n @WithTenantDb\n async find(\n query: FilterQuery<T> = {},\n projection: ProjectionType<T> = {},\n options: QueryOptions<T> = {},\n ): Promise<T[]> {\n return this.dbModel.find(query, projection, options).exec();\n }\n\n @WithTenantDb\n async updateById(\n id: string,\n body: UpdateQuery<T>,\n options: any = { new: true },\n ): Promise<T | null> {\n return this.dbModel.findByIdAndUpdate(id, body, options).exec() as Promise<\n T | null\n >;\n }\n\n @WithTenantDb\n async updateOne(\n query: FilterQuery<T>,\n body: UpdateQuery<T>,\n options: any = {},\n ): Promise<any> {\n return this.dbModel.updateOne(query, body, options).exec();\n }\n\n @WithTenantDb\n async updateMany(\n query: FilterQuery<T>,\n body: UpdateQuery<T>,\n options: any = {},\n ): Promise<any> {\n return this.dbModel.updateMany(query, body, options).exec();\n }\n\n @WithTenantDb\n async deleteById(id: string): Promise<T | null> {\n return this.dbModel.findByIdAndDelete(id).exec();\n }\n\n @WithTenantDb\n async deleteMany(query: FilterQuery<T> = {}): Promise<any> {\n return this.dbModel.deleteMany(query).exec();\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -18,6 +18,11 @@ export class Initializers {
|
|
|
18
18
|
this.context = context;
|
|
19
19
|
this.dbConnectionString = dbConnectionString;
|
|
20
20
|
}
|
|
21
|
+
getDbLogLabel() {
|
|
22
|
+
const match = this.dbConnectionString.match(/\/([^/?]+)(\?|$)/);
|
|
23
|
+
const dbName = (match == null ? void 0 : match[1]) || "unknown";
|
|
24
|
+
return `${dbName}`;
|
|
25
|
+
}
|
|
21
26
|
async ensureConnection() {
|
|
22
27
|
// Check if we already have a connection for this specific connection string
|
|
23
28
|
const existingConnection = Initializers.connections.get(this.dbConnectionString);
|
|
@@ -26,7 +31,8 @@ export class Initializers {
|
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
// Create a new Mongoose instance for this connection string
|
|
29
|
-
|
|
34
|
+
const dbLabel = this.getDbLogLabel();
|
|
35
|
+
this.context.info(`Initializing database connection (${dbLabel})...`);
|
|
30
36
|
const newMongoose = new mongoose.Mongoose();
|
|
31
37
|
try {
|
|
32
38
|
await newMongoose.connect(this.dbConnectionString, {
|
|
@@ -34,14 +40,14 @@ export class Initializers {
|
|
|
34
40
|
connectTimeoutMS: 10000,
|
|
35
41
|
socketTimeoutMS: 45000
|
|
36
42
|
});
|
|
37
|
-
this.context.info(`✅ MongoDB connected successfully ${
|
|
43
|
+
this.context.info(`✅ MongoDB connected successfully (${dbLabel})`);
|
|
38
44
|
this.connectionInitialized = true;
|
|
39
45
|
|
|
40
46
|
// Store the connection for this connection string
|
|
41
47
|
Initializers.connections.set(this.dbConnectionString, newMongoose);
|
|
42
48
|
return newMongoose;
|
|
43
49
|
} catch (err) {
|
|
44
|
-
this.context.error(`❌ MongoDB connection error for ${
|
|
50
|
+
this.context.error(`❌ MongoDB connection error for (${dbLabel})`, {
|
|
45
51
|
message: err.message,
|
|
46
52
|
name: err.name,
|
|
47
53
|
code: err.code,
|
|
@@ -70,9 +76,9 @@ export class Initializers {
|
|
|
70
76
|
try {
|
|
71
77
|
// Properly close the connection
|
|
72
78
|
await connection.disconnect();
|
|
73
|
-
this.context.info(`✅ Disconnected from database
|
|
79
|
+
this.context.info(`✅ Disconnected from database (${this.getDbLogLabel()})`);
|
|
74
80
|
} catch (error) {
|
|
75
|
-
this.context.error(`❌ Error disconnecting from database
|
|
81
|
+
this.context.error(`❌ Error disconnecting from database (${this.getDbLogLabel()})`, error);
|
|
76
82
|
} finally {
|
|
77
83
|
// Always remove from the connections map
|
|
78
84
|
Initializers.connections.delete(this.dbConnectionString);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initializers.js","names":["mongoose","WithDb","_target","_propertyKey","descriptor","value","originalMethod","args","ensureConnection","apply","Initializers","constructor","context","dbConnectionString","connectionInitialized","existingConnection","connections","get","connection","readyState","info","newMongoose","Mongoose","connect","serverSelectionTimeoutMS","connectTimeoutMS","socketTimeoutMS","set","err","error","message","name","code","stack","Error","getConnection","forceNewConnection","disconnect","delete","Map"],"sources":["../../../src/utils/initializers.ts"],"sourcesContent":["import mongoose from \"mongoose\";\nimport { InvocationContext } from \"@azure/functions\";\n\n/**\n * Decorator that ensures MongoDB is connected before the method runs.\n */\nexport function WithDb(\n _target: any,\n _propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<any>>\n): void {\n if (!descriptor.value) return;\n const originalMethod = descriptor.value;\n descriptor.value = async function (this: Initializers, ...args: any[]) {\n await this.ensureConnection();\n return originalMethod.apply(this, args);\n };\n}\n\nexport abstract class Initializers {\n protected static connections: Map<string, mongoose.Mongoose> = new Map();\n protected context: InvocationContext;\n protected dbConnectionString: string;\n private connectionInitialized: boolean = false;\n\n constructor(context: InvocationContext, dbConnectionString: string) {\n this.context = context;\n this.dbConnectionString = dbConnectionString;\n }\n\n protected async ensureConnection(): Promise<mongoose.Mongoose> {\n // Check if we already have a connection for this specific connection string\n const existingConnection = Initializers.connections.get(this.dbConnectionString);\n if (existingConnection && existingConnection.connection.readyState === 1) {\n return existingConnection;\n }\n\n // Create a new Mongoose instance for this connection string\n this.context.info(`Initializing database connection
|
|
1
|
+
{"version":3,"file":"initializers.js","names":["mongoose","WithDb","_target","_propertyKey","descriptor","value","originalMethod","args","ensureConnection","apply","Initializers","constructor","context","dbConnectionString","connectionInitialized","getDbLogLabel","match","dbName","existingConnection","connections","get","connection","readyState","dbLabel","info","newMongoose","Mongoose","connect","serverSelectionTimeoutMS","connectTimeoutMS","socketTimeoutMS","set","err","error","message","name","code","stack","Error","getConnection","forceNewConnection","disconnect","delete","Map"],"sources":["../../../src/utils/initializers.ts"],"sourcesContent":["import mongoose from \"mongoose\";\nimport { InvocationContext } from \"@azure/functions\";\n\n/**\n * Decorator that ensures MongoDB is connected before the method runs.\n */\nexport function WithDb(\n _target: any,\n _propertyKey: string | symbol,\n descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<any>>\n): void {\n if (!descriptor.value) return;\n const originalMethod = descriptor.value;\n descriptor.value = async function (this: Initializers, ...args: any[]) {\n await this.ensureConnection();\n return originalMethod.apply(this, args);\n };\n}\n\nexport abstract class Initializers {\n protected static connections: Map<string, mongoose.Mongoose> = new Map();\n protected context: InvocationContext;\n protected dbConnectionString: string;\n private connectionInitialized: boolean = false;\n\n constructor(context: InvocationContext, dbConnectionString: string) {\n this.context = context;\n this.dbConnectionString = dbConnectionString;\n }\n\n private getDbLogLabel(): string {\n const match = this.dbConnectionString.match(/\\/([^/?]+)(\\?|$)/);\n const dbName = match?.[1] || \"unknown\";\n return `${dbName}`;\n }\n\n protected async ensureConnection(): Promise<mongoose.Mongoose> {\n // Check if we already have a connection for this specific connection string\n const existingConnection = Initializers.connections.get(this.dbConnectionString);\n if (existingConnection && existingConnection.connection.readyState === 1) {\n return existingConnection;\n }\n\n // Create a new Mongoose instance for this connection string\n const dbLabel = this.getDbLogLabel();\n this.context.info(`Initializing database connection (${dbLabel})...`);\n const newMongoose = new mongoose.Mongoose();\n \n try {\n await newMongoose.connect(this.dbConnectionString, {\n serverSelectionTimeoutMS: 10000,\n connectTimeoutMS: 10000,\n socketTimeoutMS: 45000,\n });\n \n this.context.info(`✅ MongoDB connected successfully (${dbLabel})`);\n this.connectionInitialized = true;\n \n // Store the connection for this connection string\n Initializers.connections.set(this.dbConnectionString, newMongoose);\n \n return newMongoose;\n } catch (err: any) {\n this.context.error(`❌ MongoDB connection error for (${dbLabel})`, {\n message: err.message,\n name: err.name,\n code: err.code,\n stack: err.stack\n });\n this.connectionInitialized = false;\n throw new Error(`Failed to connect to MongoDB: ${err.message}`);\n }\n }\n\n protected getConnection(): mongoose.Mongoose | undefined {\n return Initializers.connections.get(this.dbConnectionString);\n }\n\n async forceNewConnection(): Promise<mongoose.Mongoose> {\n // Disconnect existing connection if any\n await this.disconnect();\n \n // Reset connection state\n this.connectionInitialized = false;\n \n // Create a new connection\n return this.ensureConnection();\n }\n \n async disconnect(): Promise<void> {\n const connection = Initializers.connections.get(this.dbConnectionString);\n if (connection) {\n try {\n // Properly close the connection\n await connection.disconnect();\n this.context.info(`✅ Disconnected from database (${this.getDbLogLabel()})`);\n } catch (error) {\n this.context.error(`❌ Error disconnecting from database (${this.getDbLogLabel()})`, error);\n } finally {\n // Always remove from the connections map\n Initializers.connections.delete(this.dbConnectionString);\n }\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -8,7 +8,6 @@ export declare enum AzureSecretKeysEnum {
|
|
|
8
8
|
EMAIL_SERVICE_URL = "Email-Service-Url",// in-use,
|
|
9
9
|
DB_CONNECTING_STRING_AUTH = "DB-CONNECTION-STRING-AUTH",
|
|
10
10
|
DB_CONNECTING_STRING_USER = "DB-CONNECTION-STRING-USER",
|
|
11
|
-
DB_CONNECTING_STRING_TENANT_BRIDGE = "DB-Connecting-String-Tenant-Bridge",
|
|
12
11
|
DB_CONNECTING_STRING_PAYMENT = "DB-CONNECTION-STRING-PAYMENT",
|
|
13
12
|
DB_CONNECTING_STRING_CORE = "DB-CONNECTION-STRING-CORE",
|
|
14
13
|
DB_CONNECTING_STRING_BILLING = "DB-CONNECTION-STRING-BILLING",
|
|
@@ -13,7 +13,6 @@ var AzureSecretKeysEnum;
|
|
|
13
13
|
AzureSecretKeysEnum["EMAIL_SERVICE_URL"] = "Email-Service-Url";
|
|
14
14
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_AUTH"] = "DB-CONNECTION-STRING-AUTH";
|
|
15
15
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_USER"] = "DB-CONNECTION-STRING-USER";
|
|
16
|
-
AzureSecretKeysEnum["DB_CONNECTING_STRING_TENANT_BRIDGE"] = "DB-Connecting-String-Tenant-Bridge";
|
|
17
16
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_PAYMENT"] = "DB-CONNECTION-STRING-PAYMENT";
|
|
18
17
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_CORE"] = "DB-CONNECTION-STRING-CORE";
|
|
19
18
|
AzureSecretKeysEnum["DB_CONNECTING_STRING_BILLING"] = "DB-CONNECTION-STRING-BILLING";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secretKeys.enum.js","sourceRoot":"","sources":["../../../src/enums/secretKeys.enum.ts"],"names":[],"mappings":";;;AAAA,uBAAuB;AACvB,IAAY,
|
|
1
|
+
{"version":3,"file":"secretKeys.enum.js","sourceRoot":"","sources":["../../../src/enums/secretKeys.enum.ts"],"names":[],"mappings":";;;AAAA,uBAAuB;AACvB,IAAY,mBAmCX;AAnCD,WAAY,mBAAmB;IAC7B,oFAA6D,CAAA;IAC7D,4EAAqD,CAAA;IACrD,8DAAuC,CAAA;IACvC,8FAAuE,CAAA;IACvE,0FAAmE,CAAA;IACnE,sFAA+D,CAAA;IAC/D,8DAAuC,CAAA;IACvC,8EAAuD,CAAA;IACvD,8EAAuD,CAAA;IACvD,oFAA6D,CAAA;IAC7D,8EAAuD,CAAA;IACvD,oFAA6D,CAAA;IAC7D,oFAA8D,CAAA;IAC9D,oFAA6D,CAAA;IAC7D,gGAAyE,CAAA;IACzE,qFAA8D,CAAA;IAC9D,sGAA+E,CAAA;IAC/E,oGAA6E,CAAA;IAC7E,oGAA6E,CAAA;IAC7E,gGAAyE,CAAA;IACzE,8DAAuC,CAAA;IACvC,gHAAyF,CAAA;IACzF,8GAAuF,CAAA;IACvF,gGAAyE,CAAA;IACzE,2EAAkD,CAAA;IAClD,0EAAiD,CAAA;IACjD,wGAAiF,CAAA;IACjF,0FAAmE,CAAA;IACnE,wDAA+B,CAAA;IAC/B,kFAAyD,CAAA;IACzD,gDAAyB,CAAA;IACzB,oDAA6B,CAAA;IAC7B,kEAA2C,CAAA;IAC3C,kGAA2E,CAAA;AAC7E,CAAC,EAnCW,mBAAmB,mCAAnB,mBAAmB,QAmC9B;AAED,kCAAkC;AAClC,8DAA8D;AAE9D,sBAAsB"}
|