@culturefy/shared 1.0.12 → 1.0.13

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.
@@ -2,113 +2,68 @@
2
2
 
3
3
  exports.__esModule = true;
4
4
  exports.Initializers = void 0;
5
+ exports.WithDb = WithDb;
5
6
  var _mongoose = _interopRequireDefault(require("mongoose"));
6
- var _secrets = require("./secrets");
7
7
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
8
  // packages/libs/src/db-initializers.ts
9
9
 
10
+ /**
11
+ * Decorator that ensures the MongoDB connection is initialized and
12
+ * sets `this.db` before the method runs.
13
+ *
14
+ * Uses a TypedPropertyDescriptor so TypeScript understands the `this` context.
15
+ */
16
+ function WithDb(_target, _propertyKey, descriptor) {
17
+ if (!descriptor.value) return;
18
+ const originalMethod = descriptor.value;
19
+ descriptor.value = async function (...args) {
20
+ // Ensure DB is connected and `this.db` is set
21
+ this.db = await this.getDb();
22
+ // Execute the original method with correct `this`
23
+ return originalMethod.apply(this, args);
24
+ };
25
+ }
10
26
  class Initializers {
11
- constructor(context, dbSecret) {
27
+ // will be set by @WithDb
28
+
29
+ constructor(context, dbConnectionString) {
30
+ this.context = context;
31
+ this.dbConnectionString = dbConnectionString;
32
+ this.dbPromise = void 0;
12
33
  this.db = void 0;
13
- MongoConnectionSingleton.getInstance(context, dbSecret).then(conn => {
14
- this.db = conn;
34
+ // Initialize the DB promise only once per connection string
35
+ this.dbPromise = MongoConnectionSingleton.getInstance(context, dbConnectionString).then(conn => {
15
36
  context.info("✅ MongoDB initialized");
37
+ return conn;
16
38
  }).catch(err => {
17
39
  context.error("❌ Failed to initialize MongoDB:", err);
18
40
  throw err;
19
41
  });
20
42
  }
43
+
44
+ /**
45
+ * Returns a promise that resolves to the MongoDB connection.
46
+ */
47
+ getDb() {
48
+ return this.dbPromise;
49
+ }
21
50
  }
22
51
  exports.Initializers = Initializers;
23
52
  class MongoConnectionSingleton {
24
- static async getInstance(context, secretKey) {
25
- if (!this.instances.has(secretKey)) {
26
- const vaultName = process.env.AZURE_KEY_VAULT_NAME;
27
- if (!vaultName) throw new Error("Missing AZURE_KEY_VAULT_NAME env var");
28
- context.info(`[Mongo] fetching secret "${secretKey}" from vault "${vaultName}"`);
29
- const uri = await (0, _secrets.getAzureVaultSecretByKey)(context, vaultName, secretKey);
30
- if (!uri) throw new Error(`No value for secret "${secretKey}"`);
53
+ static async getInstance(context, dbConnectionString) {
54
+ if (!this.instances.has(dbConnectionString)) {
31
55
  context.info("[Mongo] connecting to MongoDB…");
32
- const conn = await _mongoose.default.createConnection(uri, {}).asPromise();
33
- context.info("[Mongo] connected to MongoDB");
34
- this.instances.set(secretKey, conn);
56
+ const connPromise = _mongoose.default.createConnection(dbConnectionString).asPromise().then(conn => {
57
+ context.info("[Mongo] connected to MongoDB");
58
+ return conn;
59
+ }).catch(err => {
60
+ context.error("[Mongo] connection failed", err);
61
+ throw err;
62
+ });
63
+ this.instances.set(dbConnectionString, connPromise);
35
64
  }
36
- return this.instances.get(secretKey);
65
+ return this.instances.get(dbConnectionString);
37
66
  }
38
67
  }
39
-
40
- // import mongoose, { Mongoose } from "mongoose";
41
- // import { InvocationContext } from "@azure/functions";
42
- // import { getAzureVaultSecretByKey } from "./secrets";
43
- // import { AzureSecretKeysEnum } from "../enums";
44
-
45
- // /**
46
- // * Base class for any service that needs a MongoDB connection.
47
- // * Pass in the name of the Key Vault secret that holds your MongoDB URI.
48
- // */
49
- // export abstract class Initializers {
50
- // mongoose!: Mongoose;
51
-
52
- // constructor(
53
- // context: InvocationContext,
54
- // dbConnectionSecretKey: AzureSecretKeysEnum
55
- // ) {
56
- // MongoConnectionSingleton
57
- // .getInstance(context, dbConnectionSecretKey)
58
- // .then(singleton => {
59
- // this.mongoose = singleton.mongoose;
60
- // })
61
- // .catch(err => {
62
- // context.error("Failed to initialize MongoDB:", err);
63
- // throw err;
64
- // });
65
- // }
66
- // }
67
-
68
- // /**
69
- // * A singleton manager that caches one mongoose connection per secret key.
70
- // */
71
- // class MongoConnectionSingleton {
72
- // private static instances: Map<AzureSecretKeysEnum, MongoConnectionSingleton> = new Map();
73
- // public mongoose!: Mongoose;
74
-
75
- // private constructor() { }
76
-
77
- // public static async getInstance(
78
- // context: InvocationContext,
79
- // secretKey: AzureSecretKeysEnum
80
- // ): Promise<MongoConnectionSingleton> {
81
- // if (!this.instances.has(secretKey)) {
82
- // const inst = new MongoConnectionSingleton();
83
- // await inst.connect(context, secretKey);
84
- // this.instances.set(secretKey, inst);
85
- // }
86
- // return this.instances.get(secretKey)!;
87
- // }
88
-
89
- // private async connect(
90
- // context: InvocationContext,
91
- // secretKey: AzureSecretKeysEnum
92
- // ): Promise<void> {
93
- // // 1) Fetch vault name and secret
94
- // const vaultName = process.env.AZURE_KEY_VAULT_NAME!;
95
- // if (!vaultName) throw new Error("Missing KEY_VAULT_NAME env var");
96
-
97
- // context.info(`[Mongo] Fetching connection string from vault "${vaultName}", secret "${secretKey}"`);
98
- // const connString = await getAzureVaultSecretByKey(
99
- // context,
100
- // vaultName,
101
- // secretKey
102
- // );
103
- // if (!connString) {
104
- // throw new Error(`No value found for secret "${secretKey}"`);
105
- // }
106
-
107
- // // 2) Connect via mongoose
108
- // context.info(`[Mongo] Connecting to MongoDB…`);
109
- // this.mongoose = await mongoose.connect(connString);
110
- // context.info(`[Mongo] Connected using secret "${secretKey}"`);
111
- // }
112
- // }
113
68
  MongoConnectionSingleton.instances = new Map();
114
69
  //# sourceMappingURL=initializers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"initializers.js","names":["_mongoose","_interopRequireDefault","require","_secrets","e","__esModule","default","Initializers","constructor","context","dbSecret","db","MongoConnectionSingleton","getInstance","then","conn","info","catch","err","error","exports","secretKey","instances","has","vaultName","process","env","AZURE_KEY_VAULT_NAME","Error","uri","getAzureVaultSecretByKey","mongoose","createConnection","asPromise","set","get","Map"],"sources":["../../../src/utils/initializers.ts"],"sourcesContent":["// packages/libs/src/db-initializers.ts\n\nimport mongoose, { Connection } from \"mongoose\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { getAzureVaultSecretByKey } from \"./secrets\";\nimport { AzureSecretKeysEnum } from \"../enums\";\n\nexport abstract class Initializers {\n protected db!: Connection;\n\n constructor(\n context: InvocationContext,\n dbSecret: AzureSecretKeysEnum\n ) {\n MongoConnectionSingleton\n .getInstance(context, dbSecret)\n .then(conn => {\n this.db = conn;\n context.info(\"✅ MongoDB initialized\");\n })\n .catch(err => {\n context.error(\"❌ Failed to initialize MongoDB:\", err);\n throw err;\n });\n }\n}\n\nclass MongoConnectionSingleton {\n private static instances = new Map<AzureSecretKeysEnum, Connection>();\n\n static async getInstance(\n context: InvocationContext,\n secretKey: AzureSecretKeysEnum\n ): Promise<Connection> {\n if (!this.instances.has(secretKey)) {\n const vaultName = process.env.AZURE_KEY_VAULT_NAME!;\n if (!vaultName) throw new Error(\"Missing AZURE_KEY_VAULT_NAME env var\");\n\n context.info(`[Mongo] fetching secret \"${secretKey}\" from vault \"${vaultName}\"`);\n const uri = await getAzureVaultSecretByKey(context, vaultName, secretKey);\n if (!uri) throw new Error(`No value for secret \"${secretKey}\"`);\n\n context.info(\"[Mongo] connecting to MongoDB…\");\n const conn = await mongoose\n .createConnection(uri, {})\n .asPromise();\n context.info(\"[Mongo] connected to MongoDB\");\n\n this.instances.set(secretKey, conn);\n }\n return this.instances.get(secretKey)!;\n }\n}\n\n\n\n\n\n// import mongoose, { Mongoose } from \"mongoose\";\n// import { InvocationContext } from \"@azure/functions\";\n// import { getAzureVaultSecretByKey } from \"./secrets\";\n// import { AzureSecretKeysEnum } from \"../enums\";\n\n// /**\n// * Base class for any service that needs a MongoDB connection.\n// * Pass in the name of the Key Vault secret that holds your MongoDB URI.\n// */\n// export abstract class Initializers {\n// mongoose!: Mongoose;\n\n// constructor(\n// context: InvocationContext,\n// dbConnectionSecretKey: AzureSecretKeysEnum\n// ) {\n// MongoConnectionSingleton\n// .getInstance(context, dbConnectionSecretKey)\n// .then(singleton => {\n// this.mongoose = singleton.mongoose;\n// })\n// .catch(err => {\n// context.error(\"Failed to initialize MongoDB:\", err);\n// throw err;\n// });\n// }\n// }\n\n// /**\n// * A singleton manager that caches one mongoose connection per secret key.\n// */\n// class MongoConnectionSingleton {\n// private static instances: Map<AzureSecretKeysEnum, MongoConnectionSingleton> = new Map();\n// public mongoose!: Mongoose;\n\n// private constructor() { }\n\n// public static async getInstance(\n// context: InvocationContext,\n// secretKey: AzureSecretKeysEnum\n// ): Promise<MongoConnectionSingleton> {\n// if (!this.instances.has(secretKey)) {\n// const inst = new MongoConnectionSingleton();\n// await inst.connect(context, secretKey);\n// this.instances.set(secretKey, inst);\n// }\n// return this.instances.get(secretKey)!;\n// }\n\n// private async connect(\n// context: InvocationContext,\n// secretKey: AzureSecretKeysEnum\n// ): Promise<void> {\n// // 1) Fetch vault name and secret\n// const vaultName = process.env.AZURE_KEY_VAULT_NAME!;\n// if (!vaultName) throw new Error(\"Missing KEY_VAULT_NAME env var\");\n\n// context.info(`[Mongo] Fetching connection string from vault \"${vaultName}\", secret \"${secretKey}\"`);\n// const connString = await getAzureVaultSecretByKey(\n// context,\n// vaultName,\n// secretKey\n// );\n// if (!connString) {\n// throw new Error(`No value found for secret \"${secretKey}\"`);\n// }\n\n// // 2) Connect via mongoose\n// context.info(`[Mongo] Connecting to MongoDB…`);\n// this.mongoose = await mongoose.connect(connString);\n// context.info(`[Mongo] Connected using secret \"${secretKey}\"`);\n// }\n// }\n"],"mappings":";;;;AAEA,IAAAA,SAAA,GAAAC,sBAAA,CAAAC,OAAA;AAEA,IAAAC,QAAA,GAAAD,OAAA;AAAqD,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAJrD;;AAOO,MAAeG,YAAY,CAAC;EAGjCC,WAAWA,CACTC,OAA0B,EAC1BC,QAA6B,EAC7B;IAAA,KALQC,EAAE;IAMVC,wBAAwB,CACrBC,WAAW,CAACJ,OAAO,EAAEC,QAAQ,CAAC,CAC9BI,IAAI,CAACC,IAAI,IAAI;MACZ,IAAI,CAACJ,EAAE,GAAGI,IAAI;MACdN,OAAO,CAACO,IAAI,CAAC,uBAAuB,CAAC;IACvC,CAAC,CAAC,CACDC,KAAK,CAACC,GAAG,IAAI;MACZT,OAAO,CAACU,KAAK,CAAC,iCAAiC,EAAED,GAAG,CAAC;MACrD,MAAMA,GAAG;IACX,CAAC,CAAC;EACN;AACF;AAACE,OAAA,CAAAb,YAAA,GAAAA,YAAA;AAED,MAAMK,wBAAwB,CAAC;EAG7B,aAAaC,WAAWA,CACtBJ,OAA0B,EAC1BY,SAA8B,EACT;IACrB,IAAI,CAAC,IAAI,CAACC,SAAS,CAACC,GAAG,CAACF,SAAS,CAAC,EAAE;MAClC,MAAMG,SAAS,GAAGC,OAAO,CAACC,GAAG,CAACC,oBAAqB;MACnD,IAAI,CAACH,SAAS,EAAE,MAAM,IAAII,KAAK,CAAC,sCAAsC,CAAC;MAEvEnB,OAAO,CAACO,IAAI,CAAC,4BAA4BK,SAAS,iBAAiBG,SAAS,GAAG,CAAC;MAChF,MAAMK,GAAG,GAAG,MAAM,IAAAC,iCAAwB,EAACrB,OAAO,EAAEe,SAAS,EAAEH,SAAS,CAAC;MACzE,IAAI,CAACQ,GAAG,EAAE,MAAM,IAAID,KAAK,CAAC,wBAAwBP,SAAS,GAAG,CAAC;MAE/DZ,OAAO,CAACO,IAAI,CAAC,gCAAgC,CAAC;MAC9C,MAAMD,IAAI,GAAG,MAAMgB,iBAAQ,CACxBC,gBAAgB,CAACH,GAAG,EAAE,CAAC,CAAC,CAAC,CACzBI,SAAS,CAAC,CAAC;MACdxB,OAAO,CAACO,IAAI,CAAC,8BAA8B,CAAC;MAE5C,IAAI,CAACM,SAAS,CAACY,GAAG,CAACb,SAAS,EAAEN,IAAI,CAAC;IACrC;IACA,OAAO,IAAI,CAACO,SAAS,CAACa,GAAG,CAACd,SAAS,CAAC;EACtC;AACF;;AAMA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AAvGMT,wBAAwB,CACbU,SAAS,GAAG,IAAIc,GAAG,CAAkC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"initializers.js","names":["_mongoose","_interopRequireDefault","require","e","__esModule","default","WithDb","_target","_propertyKey","descriptor","value","originalMethod","args","db","getDb","apply","Initializers","constructor","context","dbConnectionString","dbPromise","MongoConnectionSingleton","getInstance","then","conn","info","catch","err","error","exports","instances","has","connPromise","mongoose","createConnection","asPromise","set","get","Map"],"sources":["../../../src/utils/initializers.ts"],"sourcesContent":["// packages/libs/src/db-initializers.ts\n\nimport mongoose, { Connection } from \"mongoose\";\nimport { InvocationContext } from \"@azure/functions\";\n\n/**\n * Decorator that ensures the MongoDB connection is initialized and\n * sets `this.db` before the method runs.\n *\n * Uses a TypedPropertyDescriptor so TypeScript understands the `this` context.\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 // Ensure DB is connected and `this.db` is set\n this.db = await this.getDb();\n // Execute the original method with correct `this`\n return originalMethod.apply(this, args);\n };\n}\n\nexport abstract class Initializers {\n protected dbPromise: Promise<Connection>;\n protected db!: Connection; // will be set by @WithDb\n\n constructor(\n protected context: InvocationContext,\n protected dbConnectionString: string\n ) {\n // Initialize the DB promise only once per connection string\n this.dbPromise = MongoConnectionSingleton.getInstance(\n context,\n dbConnectionString\n )\n .then(conn => {\n context.info(\"✅ MongoDB initialized\");\n return conn;\n })\n .catch(err => {\n context.error(\"Failed to initialize MongoDB:\", err);\n throw err;\n });\n }\n\n /**\n * Returns a promise that resolves to the MongoDB connection.\n */\n protected getDb(): Promise<Connection> {\n return this.dbPromise;\n }\n}\n\nclass MongoConnectionSingleton {\n private static instances: Map<string, Promise<Connection>> = new Map();\n\n static async getInstance(\n context: InvocationContext,\n dbConnectionString: string\n ): Promise<Connection> {\n if (!this.instances.has(dbConnectionString)) {\n context.info(\"[Mongo] connecting to MongoDB…\");\n const connPromise = mongoose\n .createConnection(dbConnectionString)\n .asPromise()\n .then(conn => {\n context.info(\"[Mongo] connected to MongoDB\");\n return conn;\n })\n .catch(err => {\n context.error(\"[Mongo] connection failed\", err);\n throw err;\n });\n this.instances.set(dbConnectionString, connPromise);\n }\n return this.instances.get(dbConnectionString)!;\n }\n}\n"],"mappings":";;;;;AAEA,IAAAA,SAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAgD,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAFhD;;AAKA;AACA;AACA;AACA;AACA;AACA;AACO,SAASG,MAAMA,CACpBC,OAAY,EACZC,YAA6B,EAC7BC,UAAqE,EAC/D;EACN,IAAI,CAACA,UAAU,CAACC,KAAK,EAAE;EACvB,MAAMC,cAAc,GAAGF,UAAU,CAACC,KAAK;EACvCD,UAAU,CAACC,KAAK,GAAG,gBAAoC,GAAGE,IAAW,EAAE;IACrE;IACA,IAAI,CAACC,EAAE,GAAG,MAAM,IAAI,CAACC,KAAK,CAAC,CAAC;IAC5B;IACA,OAAOH,cAAc,CAACI,KAAK,CAAC,IAAI,EAAEH,IAAI,CAAC;EACzC,CAAC;AACH;AAEO,MAAeI,YAAY,CAAC;EAEN;;EAE3BC,WAAWA,CACCC,OAA0B,EAC1BC,kBAA0B,EACpC;IAAA,KAFUD,OAA0B,GAA1BA,OAA0B;IAAA,KAC1BC,kBAA0B,GAA1BA,kBAA0B;IAAA,KAL5BC,SAAS;IAAA,KACTP,EAAE;IAMV;IACA,IAAI,CAACO,SAAS,GAAGC,wBAAwB,CAACC,WAAW,CACnDJ,OAAO,EACPC,kBACF,CAAC,CACEI,IAAI,CAACC,IAAI,IAAI;MACZN,OAAO,CAACO,IAAI,CAAC,uBAAuB,CAAC;MACrC,OAAOD,IAAI;IACb,CAAC,CAAC,CACDE,KAAK,CAACC,GAAG,IAAI;MACZT,OAAO,CAACU,KAAK,CAAC,iCAAiC,EAAED,GAAG,CAAC;MACrD,MAAMA,GAAG;IACX,CAAC,CAAC;EACN;;EAEA;AACF;AACA;EACYb,KAAKA,CAAA,EAAwB;IACrC,OAAO,IAAI,CAACM,SAAS;EACvB;AACF;AAACS,OAAA,CAAAb,YAAA,GAAAA,YAAA;AAED,MAAMK,wBAAwB,CAAC;EAG7B,aAAaC,WAAWA,CACtBJ,OAA0B,EAC1BC,kBAA0B,EACL;IACrB,IAAI,CAAC,IAAI,CAACW,SAAS,CAACC,GAAG,CAACZ,kBAAkB,CAAC,EAAE;MAC3CD,OAAO,CAACO,IAAI,CAAC,gCAAgC,CAAC;MAC9C,MAAMO,WAAW,GAAGC,iBAAQ,CACzBC,gBAAgB,CAACf,kBAAkB,CAAC,CACpCgB,SAAS,CAAC,CAAC,CACXZ,IAAI,CAACC,IAAI,IAAI;QACZN,OAAO,CAACO,IAAI,CAAC,8BAA8B,CAAC;QAC5C,OAAOD,IAAI;MACb,CAAC,CAAC,CACDE,KAAK,CAACC,GAAG,IAAI;QACZT,OAAO,CAACU,KAAK,CAAC,2BAA2B,EAAED,GAAG,CAAC;QAC/C,MAAMA,GAAG;MACX,CAAC,CAAC;MACJ,IAAI,CAACG,SAAS,CAACM,GAAG,CAACjB,kBAAkB,EAAEa,WAAW,CAAC;IACrD;IACA,OAAO,IAAI,CAACF,SAAS,CAACO,GAAG,CAAClB,kBAAkB,CAAC;EAC/C;AACF;AAxBME,wBAAwB,CACbS,SAAS,GAAqC,IAAIQ,GAAG,CAAC,CAAC","ignoreList":[]}
@@ -1,108 +1,62 @@
1
1
  // packages/libs/src/db-initializers.ts
2
2
 
3
3
  import mongoose from "mongoose";
4
- import { getAzureVaultSecretByKey } from "./secrets";
4
+ /**
5
+ * Decorator that ensures the MongoDB connection is initialized and
6
+ * sets `this.db` before the method runs.
7
+ *
8
+ * Uses a TypedPropertyDescriptor so TypeScript understands the `this` context.
9
+ */
10
+ export function WithDb(_target, _propertyKey, descriptor) {
11
+ if (!descriptor.value) return;
12
+ const originalMethod = descriptor.value;
13
+ descriptor.value = async function (...args) {
14
+ // Ensure DB is connected and `this.db` is set
15
+ this.db = await this.getDb();
16
+ // Execute the original method with correct `this`
17
+ return originalMethod.apply(this, args);
18
+ };
19
+ }
5
20
  export class Initializers {
6
- constructor(context, dbSecret) {
21
+ // will be set by @WithDb
22
+
23
+ constructor(context, dbConnectionString) {
24
+ this.context = context;
25
+ this.dbConnectionString = dbConnectionString;
26
+ this.dbPromise = void 0;
7
27
  this.db = void 0;
8
- MongoConnectionSingleton.getInstance(context, dbSecret).then(conn => {
9
- this.db = conn;
28
+ // Initialize the DB promise only once per connection string
29
+ this.dbPromise = MongoConnectionSingleton.getInstance(context, dbConnectionString).then(conn => {
10
30
  context.info("✅ MongoDB initialized");
31
+ return conn;
11
32
  }).catch(err => {
12
33
  context.error("❌ Failed to initialize MongoDB:", err);
13
34
  throw err;
14
35
  });
15
36
  }
37
+
38
+ /**
39
+ * Returns a promise that resolves to the MongoDB connection.
40
+ */
41
+ getDb() {
42
+ return this.dbPromise;
43
+ }
16
44
  }
17
45
  class MongoConnectionSingleton {
18
- static async getInstance(context, secretKey) {
19
- if (!this.instances.has(secretKey)) {
20
- const vaultName = process.env.AZURE_KEY_VAULT_NAME;
21
- if (!vaultName) throw new Error("Missing AZURE_KEY_VAULT_NAME env var");
22
- context.info(`[Mongo] fetching secret "${secretKey}" from vault "${vaultName}"`);
23
- const uri = await getAzureVaultSecretByKey(context, vaultName, secretKey);
24
- if (!uri) throw new Error(`No value for secret "${secretKey}"`);
46
+ static async getInstance(context, dbConnectionString) {
47
+ if (!this.instances.has(dbConnectionString)) {
25
48
  context.info("[Mongo] connecting to MongoDB…");
26
- const conn = await mongoose.createConnection(uri, {}).asPromise();
27
- context.info("[Mongo] connected to MongoDB");
28
- this.instances.set(secretKey, conn);
49
+ const connPromise = mongoose.createConnection(dbConnectionString).asPromise().then(conn => {
50
+ context.info("[Mongo] connected to MongoDB");
51
+ return conn;
52
+ }).catch(err => {
53
+ context.error("[Mongo] connection failed", err);
54
+ throw err;
55
+ });
56
+ this.instances.set(dbConnectionString, connPromise);
29
57
  }
30
- return this.instances.get(secretKey);
58
+ return this.instances.get(dbConnectionString);
31
59
  }
32
60
  }
33
-
34
- // import mongoose, { Mongoose } from "mongoose";
35
- // import { InvocationContext } from "@azure/functions";
36
- // import { getAzureVaultSecretByKey } from "./secrets";
37
- // import { AzureSecretKeysEnum } from "../enums";
38
-
39
- // /**
40
- // * Base class for any service that needs a MongoDB connection.
41
- // * Pass in the name of the Key Vault secret that holds your MongoDB URI.
42
- // */
43
- // export abstract class Initializers {
44
- // mongoose!: Mongoose;
45
-
46
- // constructor(
47
- // context: InvocationContext,
48
- // dbConnectionSecretKey: AzureSecretKeysEnum
49
- // ) {
50
- // MongoConnectionSingleton
51
- // .getInstance(context, dbConnectionSecretKey)
52
- // .then(singleton => {
53
- // this.mongoose = singleton.mongoose;
54
- // })
55
- // .catch(err => {
56
- // context.error("Failed to initialize MongoDB:", err);
57
- // throw err;
58
- // });
59
- // }
60
- // }
61
-
62
- // /**
63
- // * A singleton manager that caches one mongoose connection per secret key.
64
- // */
65
- // class MongoConnectionSingleton {
66
- // private static instances: Map<AzureSecretKeysEnum, MongoConnectionSingleton> = new Map();
67
- // public mongoose!: Mongoose;
68
-
69
- // private constructor() { }
70
-
71
- // public static async getInstance(
72
- // context: InvocationContext,
73
- // secretKey: AzureSecretKeysEnum
74
- // ): Promise<MongoConnectionSingleton> {
75
- // if (!this.instances.has(secretKey)) {
76
- // const inst = new MongoConnectionSingleton();
77
- // await inst.connect(context, secretKey);
78
- // this.instances.set(secretKey, inst);
79
- // }
80
- // return this.instances.get(secretKey)!;
81
- // }
82
-
83
- // private async connect(
84
- // context: InvocationContext,
85
- // secretKey: AzureSecretKeysEnum
86
- // ): Promise<void> {
87
- // // 1) Fetch vault name and secret
88
- // const vaultName = process.env.AZURE_KEY_VAULT_NAME!;
89
- // if (!vaultName) throw new Error("Missing KEY_VAULT_NAME env var");
90
-
91
- // context.info(`[Mongo] Fetching connection string from vault "${vaultName}", secret "${secretKey}"`);
92
- // const connString = await getAzureVaultSecretByKey(
93
- // context,
94
- // vaultName,
95
- // secretKey
96
- // );
97
- // if (!connString) {
98
- // throw new Error(`No value found for secret "${secretKey}"`);
99
- // }
100
-
101
- // // 2) Connect via mongoose
102
- // context.info(`[Mongo] Connecting to MongoDB…`);
103
- // this.mongoose = await mongoose.connect(connString);
104
- // context.info(`[Mongo] Connected using secret "${secretKey}"`);
105
- // }
106
- // }
107
61
  MongoConnectionSingleton.instances = new Map();
108
62
  //# sourceMappingURL=initializers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"initializers.js","names":["mongoose","getAzureVaultSecretByKey","Initializers","constructor","context","dbSecret","db","MongoConnectionSingleton","getInstance","then","conn","info","catch","err","error","secretKey","instances","has","vaultName","process","env","AZURE_KEY_VAULT_NAME","Error","uri","createConnection","asPromise","set","get","Map"],"sources":["../../../src/utils/initializers.ts"],"sourcesContent":["// packages/libs/src/db-initializers.ts\n\nimport mongoose, { Connection } from \"mongoose\";\nimport { InvocationContext } from \"@azure/functions\";\nimport { getAzureVaultSecretByKey } from \"./secrets\";\nimport { AzureSecretKeysEnum } from \"../enums\";\n\nexport abstract class Initializers {\n protected db!: Connection;\n\n constructor(\n context: InvocationContext,\n dbSecret: AzureSecretKeysEnum\n ) {\n MongoConnectionSingleton\n .getInstance(context, dbSecret)\n .then(conn => {\n this.db = conn;\n context.info(\"✅ MongoDB initialized\");\n })\n .catch(err => {\n context.error(\"❌ Failed to initialize MongoDB:\", err);\n throw err;\n });\n }\n}\n\nclass MongoConnectionSingleton {\n private static instances = new Map<AzureSecretKeysEnum, Connection>();\n\n static async getInstance(\n context: InvocationContext,\n secretKey: AzureSecretKeysEnum\n ): Promise<Connection> {\n if (!this.instances.has(secretKey)) {\n const vaultName = process.env.AZURE_KEY_VAULT_NAME!;\n if (!vaultName) throw new Error(\"Missing AZURE_KEY_VAULT_NAME env var\");\n\n context.info(`[Mongo] fetching secret \"${secretKey}\" from vault \"${vaultName}\"`);\n const uri = await getAzureVaultSecretByKey(context, vaultName, secretKey);\n if (!uri) throw new Error(`No value for secret \"${secretKey}\"`);\n\n context.info(\"[Mongo] connecting to MongoDB…\");\n const conn = await mongoose\n .createConnection(uri, {})\n .asPromise();\n context.info(\"[Mongo] connected to MongoDB\");\n\n this.instances.set(secretKey, conn);\n }\n return this.instances.get(secretKey)!;\n }\n}\n\n\n\n\n\n// import mongoose, { Mongoose } from \"mongoose\";\n// import { InvocationContext } from \"@azure/functions\";\n// import { getAzureVaultSecretByKey } from \"./secrets\";\n// import { AzureSecretKeysEnum } from \"../enums\";\n\n// /**\n// * Base class for any service that needs a MongoDB connection.\n// * Pass in the name of the Key Vault secret that holds your MongoDB URI.\n// */\n// export abstract class Initializers {\n// mongoose!: Mongoose;\n\n// constructor(\n// context: InvocationContext,\n// dbConnectionSecretKey: AzureSecretKeysEnum\n// ) {\n// MongoConnectionSingleton\n// .getInstance(context, dbConnectionSecretKey)\n// .then(singleton => {\n// this.mongoose = singleton.mongoose;\n// })\n// .catch(err => {\n// context.error(\"Failed to initialize MongoDB:\", err);\n// throw err;\n// });\n// }\n// }\n\n// /**\n// * A singleton manager that caches one mongoose connection per secret key.\n// */\n// class MongoConnectionSingleton {\n// private static instances: Map<AzureSecretKeysEnum, MongoConnectionSingleton> = new Map();\n// public mongoose!: Mongoose;\n\n// private constructor() { }\n\n// public static async getInstance(\n// context: InvocationContext,\n// secretKey: AzureSecretKeysEnum\n// ): Promise<MongoConnectionSingleton> {\n// if (!this.instances.has(secretKey)) {\n// const inst = new MongoConnectionSingleton();\n// await inst.connect(context, secretKey);\n// this.instances.set(secretKey, inst);\n// }\n// return this.instances.get(secretKey)!;\n// }\n\n// private async connect(\n// context: InvocationContext,\n// secretKey: AzureSecretKeysEnum\n// ): Promise<void> {\n// // 1) Fetch vault name and secret\n// const vaultName = process.env.AZURE_KEY_VAULT_NAME!;\n// if (!vaultName) throw new Error(\"Missing KEY_VAULT_NAME env var\");\n\n// context.info(`[Mongo] Fetching connection string from vault \"${vaultName}\", secret \"${secretKey}\"`);\n// const connString = await getAzureVaultSecretByKey(\n// context,\n// vaultName,\n// secretKey\n// );\n// if (!connString) {\n// throw new Error(`No value found for secret \"${secretKey}\"`);\n// }\n\n// // 2) Connect via mongoose\n// context.info(`[Mongo] Connecting to MongoDB…`);\n// this.mongoose = await mongoose.connect(connString);\n// context.info(`[Mongo] Connected using secret \"${secretKey}\"`);\n// }\n// }\n"],"mappings":"AAAA;;AAEA,OAAOA,QAAQ,MAAsB,UAAU;AAE/C,SAASC,wBAAwB,QAAQ,WAAW;AAGpD,OAAO,MAAeC,YAAY,CAAC;EAGjCC,WAAWA,CACTC,OAA0B,EAC1BC,QAA6B,EAC7B;IAAA,KALQC,EAAE;IAMVC,wBAAwB,CACrBC,WAAW,CAACJ,OAAO,EAAEC,QAAQ,CAAC,CAC9BI,IAAI,CAACC,IAAI,IAAI;MACZ,IAAI,CAACJ,EAAE,GAAGI,IAAI;MACdN,OAAO,CAACO,IAAI,CAAC,uBAAuB,CAAC;IACvC,CAAC,CAAC,CACDC,KAAK,CAACC,GAAG,IAAI;MACZT,OAAO,CAACU,KAAK,CAAC,iCAAiC,EAAED,GAAG,CAAC;MACrD,MAAMA,GAAG;IACX,CAAC,CAAC;EACN;AACF;AAEA,MAAMN,wBAAwB,CAAC;EAG7B,aAAaC,WAAWA,CACtBJ,OAA0B,EAC1BW,SAA8B,EACT;IACrB,IAAI,CAAC,IAAI,CAACC,SAAS,CAACC,GAAG,CAACF,SAAS,CAAC,EAAE;MAClC,MAAMG,SAAS,GAAGC,OAAO,CAACC,GAAG,CAACC,oBAAqB;MACnD,IAAI,CAACH,SAAS,EAAE,MAAM,IAAII,KAAK,CAAC,sCAAsC,CAAC;MAEvElB,OAAO,CAACO,IAAI,CAAC,4BAA4BI,SAAS,iBAAiBG,SAAS,GAAG,CAAC;MAChF,MAAMK,GAAG,GAAG,MAAMtB,wBAAwB,CAACG,OAAO,EAAEc,SAAS,EAAEH,SAAS,CAAC;MACzE,IAAI,CAACQ,GAAG,EAAE,MAAM,IAAID,KAAK,CAAC,wBAAwBP,SAAS,GAAG,CAAC;MAE/DX,OAAO,CAACO,IAAI,CAAC,gCAAgC,CAAC;MAC9C,MAAMD,IAAI,GAAG,MAAMV,QAAQ,CACxBwB,gBAAgB,CAACD,GAAG,EAAE,CAAC,CAAC,CAAC,CACzBE,SAAS,CAAC,CAAC;MACdrB,OAAO,CAACO,IAAI,CAAC,8BAA8B,CAAC;MAE5C,IAAI,CAACK,SAAS,CAACU,GAAG,CAACX,SAAS,EAAEL,IAAI,CAAC;IACrC;IACA,OAAO,IAAI,CAACM,SAAS,CAACW,GAAG,CAACZ,SAAS,CAAC;EACtC;AACF;;AAMA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AAvGMR,wBAAwB,CACbS,SAAS,GAAG,IAAIY,GAAG,CAAkC,CAAC","ignoreList":[]}
1
+ {"version":3,"file":"initializers.js","names":["mongoose","WithDb","_target","_propertyKey","descriptor","value","originalMethod","args","db","getDb","apply","Initializers","constructor","context","dbConnectionString","dbPromise","MongoConnectionSingleton","getInstance","then","conn","info","catch","err","error","instances","has","connPromise","createConnection","asPromise","set","get","Map"],"sources":["../../../src/utils/initializers.ts"],"sourcesContent":["// packages/libs/src/db-initializers.ts\n\nimport mongoose, { Connection } from \"mongoose\";\nimport { InvocationContext } from \"@azure/functions\";\n\n/**\n * Decorator that ensures the MongoDB connection is initialized and\n * sets `this.db` before the method runs.\n *\n * Uses a TypedPropertyDescriptor so TypeScript understands the `this` context.\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 // Ensure DB is connected and `this.db` is set\n this.db = await this.getDb();\n // Execute the original method with correct `this`\n return originalMethod.apply(this, args);\n };\n}\n\nexport abstract class Initializers {\n protected dbPromise: Promise<Connection>;\n protected db!: Connection; // will be set by @WithDb\n\n constructor(\n protected context: InvocationContext,\n protected dbConnectionString: string\n ) {\n // Initialize the DB promise only once per connection string\n this.dbPromise = MongoConnectionSingleton.getInstance(\n context,\n dbConnectionString\n )\n .then(conn => {\n context.info(\"✅ MongoDB initialized\");\n return conn;\n })\n .catch(err => {\n context.error(\"Failed to initialize MongoDB:\", err);\n throw err;\n });\n }\n\n /**\n * Returns a promise that resolves to the MongoDB connection.\n */\n protected getDb(): Promise<Connection> {\n return this.dbPromise;\n }\n}\n\nclass MongoConnectionSingleton {\n private static instances: Map<string, Promise<Connection>> = new Map();\n\n static async getInstance(\n context: InvocationContext,\n dbConnectionString: string\n ): Promise<Connection> {\n if (!this.instances.has(dbConnectionString)) {\n context.info(\"[Mongo] connecting to MongoDB…\");\n const connPromise = mongoose\n .createConnection(dbConnectionString)\n .asPromise()\n .then(conn => {\n context.info(\"[Mongo] connected to MongoDB\");\n return conn;\n })\n .catch(err => {\n context.error(\"[Mongo] connection failed\", err);\n throw err;\n });\n this.instances.set(dbConnectionString, connPromise);\n }\n return this.instances.get(dbConnectionString)!;\n }\n}\n"],"mappings":"AAAA;;AAEA,OAAOA,QAAQ,MAAsB,UAAU;AAG/C;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,MAAMA,CACpBC,OAAY,EACZC,YAA6B,EAC7BC,UAAqE,EAC/D;EACN,IAAI,CAACA,UAAU,CAACC,KAAK,EAAE;EACvB,MAAMC,cAAc,GAAGF,UAAU,CAACC,KAAK;EACvCD,UAAU,CAACC,KAAK,GAAG,gBAAoC,GAAGE,IAAW,EAAE;IACrE;IACA,IAAI,CAACC,EAAE,GAAG,MAAM,IAAI,CAACC,KAAK,CAAC,CAAC;IAC5B;IACA,OAAOH,cAAc,CAACI,KAAK,CAAC,IAAI,EAAEH,IAAI,CAAC;EACzC,CAAC;AACH;AAEA,OAAO,MAAeI,YAAY,CAAC;EAEN;;EAE3BC,WAAWA,CACCC,OAA0B,EAC1BC,kBAA0B,EACpC;IAAA,KAFUD,OAA0B,GAA1BA,OAA0B;IAAA,KAC1BC,kBAA0B,GAA1BA,kBAA0B;IAAA,KAL5BC,SAAS;IAAA,KACTP,EAAE;IAMV;IACA,IAAI,CAACO,SAAS,GAAGC,wBAAwB,CAACC,WAAW,CACnDJ,OAAO,EACPC,kBACF,CAAC,CACEI,IAAI,CAACC,IAAI,IAAI;MACZN,OAAO,CAACO,IAAI,CAAC,uBAAuB,CAAC;MACrC,OAAOD,IAAI;IACb,CAAC,CAAC,CACDE,KAAK,CAACC,GAAG,IAAI;MACZT,OAAO,CAACU,KAAK,CAAC,iCAAiC,EAAED,GAAG,CAAC;MACrD,MAAMA,GAAG;IACX,CAAC,CAAC;EACN;;EAEA;AACF;AACA;EACYb,KAAKA,CAAA,EAAwB;IACrC,OAAO,IAAI,CAACM,SAAS;EACvB;AACF;AAEA,MAAMC,wBAAwB,CAAC;EAG7B,aAAaC,WAAWA,CACtBJ,OAA0B,EAC1BC,kBAA0B,EACL;IACrB,IAAI,CAAC,IAAI,CAACU,SAAS,CAACC,GAAG,CAACX,kBAAkB,CAAC,EAAE;MAC3CD,OAAO,CAACO,IAAI,CAAC,gCAAgC,CAAC;MAC9C,MAAMM,WAAW,GAAG1B,QAAQ,CACzB2B,gBAAgB,CAACb,kBAAkB,CAAC,CACpCc,SAAS,CAAC,CAAC,CACXV,IAAI,CAACC,IAAI,IAAI;QACZN,OAAO,CAACO,IAAI,CAAC,8BAA8B,CAAC;QAC5C,OAAOD,IAAI;MACb,CAAC,CAAC,CACDE,KAAK,CAACC,GAAG,IAAI;QACZT,OAAO,CAACU,KAAK,CAAC,2BAA2B,EAAED,GAAG,CAAC;QAC/C,MAAMA,GAAG;MACX,CAAC,CAAC;MACJ,IAAI,CAACE,SAAS,CAACK,GAAG,CAACf,kBAAkB,EAAEY,WAAW,CAAC;IACrD;IACA,OAAO,IAAI,CAACF,SAAS,CAACM,GAAG,CAAChB,kBAAkB,CAAC;EAC/C;AACF;AAxBME,wBAAwB,CACbQ,SAAS,GAAqC,IAAIO,GAAG,CAAC,CAAC","ignoreList":[]}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@culturefy/shared",
3
3
  "description": "Shared utilities for culturefy serverless services",
4
- "version": "1.0.12",
4
+ "version": "1.0.13",
5
5
  "main": "build/cjs/index.js",
6
6
  "module": "build/esm/index.js",
7
7
  "types": "build/src/index.d.ts",
@@ -1,7 +1,20 @@
1
1
  import { Connection } from "mongoose";
2
2
  import { InvocationContext } from "@azure/functions";
3
- import { AzureSecretKeysEnum } from "../enums";
3
+ /**
4
+ * Decorator that ensures the MongoDB connection is initialized and
5
+ * sets `this.db` before the method runs.
6
+ *
7
+ * Uses a TypedPropertyDescriptor so TypeScript understands the `this` context.
8
+ */
9
+ export declare function WithDb(_target: any, _propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<any>>): void;
4
10
  export declare abstract class Initializers {
11
+ protected context: InvocationContext;
12
+ protected dbConnectionString: string;
13
+ protected dbPromise: Promise<Connection>;
5
14
  protected db: Connection;
6
- constructor(context: InvocationContext, dbSecret: AzureSecretKeysEnum);
15
+ constructor(context: InvocationContext, dbConnectionString: string);
16
+ /**
17
+ * Returns a promise that resolves to the MongoDB connection.
18
+ */
19
+ protected getDb(): Promise<Connection>;
7
20
  }
@@ -2,110 +2,72 @@
2
2
  // packages/libs/src/db-initializers.ts
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.Initializers = void 0;
5
+ exports.WithDb = WithDb;
5
6
  const tslib_1 = require("tslib");
6
7
  const mongoose_1 = tslib_1.__importDefault(require("mongoose"));
7
- const secrets_1 = require("./secrets");
8
+ /**
9
+ * Decorator that ensures the MongoDB connection is initialized and
10
+ * sets `this.db` before the method runs.
11
+ *
12
+ * Uses a TypedPropertyDescriptor so TypeScript understands the `this` context.
13
+ */
14
+ function WithDb(_target, _propertyKey, descriptor) {
15
+ if (!descriptor.value)
16
+ return;
17
+ const originalMethod = descriptor.value;
18
+ descriptor.value = function (...args) {
19
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
20
+ // Ensure DB is connected and `this.db` is set
21
+ this.db = yield this.getDb();
22
+ // Execute the original method with correct `this`
23
+ return originalMethod.apply(this, args);
24
+ });
25
+ };
26
+ }
8
27
  class Initializers {
9
- constructor(context, dbSecret) {
10
- MongoConnectionSingleton
11
- .getInstance(context, dbSecret)
28
+ constructor(context, dbConnectionString) {
29
+ this.context = context;
30
+ this.dbConnectionString = dbConnectionString;
31
+ // Initialize the DB promise only once per connection string
32
+ this.dbPromise = MongoConnectionSingleton.getInstance(context, dbConnectionString)
12
33
  .then(conn => {
13
- this.db = conn;
14
34
  context.info("✅ MongoDB initialized");
35
+ return conn;
15
36
  })
16
37
  .catch(err => {
17
38
  context.error("❌ Failed to initialize MongoDB:", err);
18
39
  throw err;
19
40
  });
20
41
  }
42
+ /**
43
+ * Returns a promise that resolves to the MongoDB connection.
44
+ */
45
+ getDb() {
46
+ return this.dbPromise;
47
+ }
21
48
  }
22
49
  exports.Initializers = Initializers;
23
50
  class MongoConnectionSingleton {
24
- static getInstance(context, secretKey) {
51
+ static getInstance(context, dbConnectionString) {
25
52
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
26
- if (!this.instances.has(secretKey)) {
27
- const vaultName = process.env.AZURE_KEY_VAULT_NAME;
28
- if (!vaultName)
29
- throw new Error("Missing AZURE_KEY_VAULT_NAME env var");
30
- context.info(`[Mongo] fetching secret "${secretKey}" from vault "${vaultName}"`);
31
- const uri = yield (0, secrets_1.getAzureVaultSecretByKey)(context, vaultName, secretKey);
32
- if (!uri)
33
- throw new Error(`No value for secret "${secretKey}"`);
53
+ if (!this.instances.has(dbConnectionString)) {
34
54
  context.info("[Mongo] connecting to MongoDB…");
35
- const conn = yield mongoose_1.default
36
- .createConnection(uri, {})
37
- .asPromise();
38
- context.info("[Mongo] connected to MongoDB");
39
- this.instances.set(secretKey, conn);
55
+ const connPromise = mongoose_1.default
56
+ .createConnection(dbConnectionString)
57
+ .asPromise()
58
+ .then(conn => {
59
+ context.info("[Mongo] connected to MongoDB");
60
+ return conn;
61
+ })
62
+ .catch(err => {
63
+ context.error("[Mongo] connection failed", err);
64
+ throw err;
65
+ });
66
+ this.instances.set(dbConnectionString, connPromise);
40
67
  }
41
- return this.instances.get(secretKey);
68
+ return this.instances.get(dbConnectionString);
42
69
  });
43
70
  }
44
71
  }
45
72
  MongoConnectionSingleton.instances = new Map();
46
- // import mongoose, { Mongoose } from "mongoose";
47
- // import { InvocationContext } from "@azure/functions";
48
- // import { getAzureVaultSecretByKey } from "./secrets";
49
- // import { AzureSecretKeysEnum } from "../enums";
50
- // /**
51
- // * Base class for any service that needs a MongoDB connection.
52
- // * Pass in the name of the Key Vault secret that holds your MongoDB URI.
53
- // */
54
- // export abstract class Initializers {
55
- // mongoose!: Mongoose;
56
- // constructor(
57
- // context: InvocationContext,
58
- // dbConnectionSecretKey: AzureSecretKeysEnum
59
- // ) {
60
- // MongoConnectionSingleton
61
- // .getInstance(context, dbConnectionSecretKey)
62
- // .then(singleton => {
63
- // this.mongoose = singleton.mongoose;
64
- // })
65
- // .catch(err => {
66
- // context.error("Failed to initialize MongoDB:", err);
67
- // throw err;
68
- // });
69
- // }
70
- // }
71
- // /**
72
- // * A singleton manager that caches one mongoose connection per secret key.
73
- // */
74
- // class MongoConnectionSingleton {
75
- // private static instances: Map<AzureSecretKeysEnum, MongoConnectionSingleton> = new Map();
76
- // public mongoose!: Mongoose;
77
- // private constructor() { }
78
- // public static async getInstance(
79
- // context: InvocationContext,
80
- // secretKey: AzureSecretKeysEnum
81
- // ): Promise<MongoConnectionSingleton> {
82
- // if (!this.instances.has(secretKey)) {
83
- // const inst = new MongoConnectionSingleton();
84
- // await inst.connect(context, secretKey);
85
- // this.instances.set(secretKey, inst);
86
- // }
87
- // return this.instances.get(secretKey)!;
88
- // }
89
- // private async connect(
90
- // context: InvocationContext,
91
- // secretKey: AzureSecretKeysEnum
92
- // ): Promise<void> {
93
- // // 1) Fetch vault name and secret
94
- // const vaultName = process.env.AZURE_KEY_VAULT_NAME!;
95
- // if (!vaultName) throw new Error("Missing KEY_VAULT_NAME env var");
96
- // context.info(`[Mongo] Fetching connection string from vault "${vaultName}", secret "${secretKey}"`);
97
- // const connString = await getAzureVaultSecretByKey(
98
- // context,
99
- // vaultName,
100
- // secretKey
101
- // );
102
- // if (!connString) {
103
- // throw new Error(`No value found for secret "${secretKey}"`);
104
- // }
105
- // // 2) Connect via mongoose
106
- // context.info(`[Mongo] Connecting to MongoDB…`);
107
- // this.mongoose = await mongoose.connect(connString);
108
- // context.info(`[Mongo] Connected using secret "${secretKey}"`);
109
- // }
110
- // }
111
73
  //# sourceMappingURL=initializers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"initializers.js","sourceRoot":"","sources":["../../../src/utils/initializers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"initializers.js","sourceRoot":"","sources":["../../../src/utils/initializers.ts"],"names":[],"mappings":";AAAA,uCAAuC;;;AAWvC,wBAaC;;AAtBD,gEAAgD;AAGhD;;;;;GAKG;AACH,SAAgB,MAAM,CACpB,OAAY,EACZ,YAA6B,EAC7B,UAAqE;IAErE,IAAI,CAAC,UAAU,CAAC,KAAK;QAAE,OAAO;IAC9B,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC;IACxC,UAAU,CAAC,KAAK,GAAG,UAAoC,GAAG,IAAW;;YACnE,8CAA8C;YAC9C,IAAI,CAAC,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YAC7B,kDAAkD;YAClD,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1C,CAAC;KAAA,CAAC;AACJ,CAAC;AAED,MAAsB,YAAY;IAIhC,YACY,OAA0B,EAC1B,kBAA0B;QAD1B,YAAO,GAAP,OAAO,CAAmB;QAC1B,uBAAkB,GAAlB,kBAAkB,CAAQ;QAEpC,4DAA4D;QAC5D,IAAI,CAAC,SAAS,GAAG,wBAAwB,CAAC,WAAW,CACnD,OAAO,EACP,kBAAkB,CACnB;aACE,IAAI,CAAC,IAAI,CAAC,EAAE;YACX,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,CAAC,EAAE;YACX,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,GAAG,CAAC,CAAC;YACtD,MAAM,GAAG,CAAC;QACZ,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACO,KAAK;QACb,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF;AA7BD,oCA6BC;AAED,MAAM,wBAAwB;IAG5B,MAAM,CAAO,WAAW,CACtB,OAA0B,EAC1B,kBAA0B;;YAE1B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC5C,OAAO,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;gBAC/C,MAAM,WAAW,GAAG,kBAAQ;qBACzB,gBAAgB,CAAC,kBAAkB,CAAC;qBACpC,SAAS,EAAE;qBACX,IAAI,CAAC,IAAI,CAAC,EAAE;oBACX,OAAO,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;oBAC7C,OAAO,IAAI,CAAC;gBACd,CAAC,CAAC;qBACD,KAAK,CAAC,GAAG,CAAC,EAAE;oBACX,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,GAAG,CAAC,CAAC;oBAChD,MAAM,GAAG,CAAC;gBACZ,CAAC,CAAC,CAAC;gBACL,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAC;YACtD,CAAC;YACD,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,CAAE,CAAC;QACjD,CAAC;KAAA;;AAtBc,kCAAS,GAAqC,IAAI,GAAG,EAAE,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@culturefy/shared",
3
3
  "description": "Shared utilities for culturefy serverless services",
4
- "version": "1.0.12",
4
+ "version": "1.0.13",
5
5
  "main": "build/cjs/index.js",
6
6
  "module": "build/esm/index.js",
7
7
  "types": "build/src/index.d.ts",
@@ -2,130 +2,81 @@
2
2
 
3
3
  import mongoose, { Connection } from "mongoose";
4
4
  import { InvocationContext } from "@azure/functions";
5
- import { getAzureVaultSecretByKey } from "./secrets";
6
- import { AzureSecretKeysEnum } from "../enums";
5
+
6
+ /**
7
+ * Decorator that ensures the MongoDB connection is initialized and
8
+ * sets `this.db` before the method runs.
9
+ *
10
+ * Uses a TypedPropertyDescriptor so TypeScript understands the `this` context.
11
+ */
12
+ export function WithDb(
13
+ _target: any,
14
+ _propertyKey: string | symbol,
15
+ descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<any>>
16
+ ): void {
17
+ if (!descriptor.value) return;
18
+ const originalMethod = descriptor.value;
19
+ descriptor.value = async function (this: Initializers, ...args: any[]) {
20
+ // Ensure DB is connected and `this.db` is set
21
+ this.db = await this.getDb();
22
+ // Execute the original method with correct `this`
23
+ return originalMethod.apply(this, args);
24
+ };
25
+ }
7
26
 
8
27
  export abstract class Initializers {
9
- protected db!: Connection;
28
+ protected dbPromise: Promise<Connection>;
29
+ protected db!: Connection; // will be set by @WithDb
10
30
 
11
31
  constructor(
12
- context: InvocationContext,
13
- dbSecret: AzureSecretKeysEnum
32
+ protected context: InvocationContext,
33
+ protected dbConnectionString: string
14
34
  ) {
15
- MongoConnectionSingleton
16
- .getInstance(context, dbSecret)
35
+ // Initialize the DB promise only once per connection string
36
+ this.dbPromise = MongoConnectionSingleton.getInstance(
37
+ context,
38
+ dbConnectionString
39
+ )
17
40
  .then(conn => {
18
- this.db = conn;
19
41
  context.info("✅ MongoDB initialized");
42
+ return conn;
20
43
  })
21
44
  .catch(err => {
22
45
  context.error("❌ Failed to initialize MongoDB:", err);
23
46
  throw err;
24
47
  });
25
48
  }
49
+
50
+ /**
51
+ * Returns a promise that resolves to the MongoDB connection.
52
+ */
53
+ protected getDb(): Promise<Connection> {
54
+ return this.dbPromise;
55
+ }
26
56
  }
27
57
 
28
58
  class MongoConnectionSingleton {
29
- private static instances = new Map<AzureSecretKeysEnum, Connection>();
59
+ private static instances: Map<string, Promise<Connection>> = new Map();
30
60
 
31
61
  static async getInstance(
32
62
  context: InvocationContext,
33
- secretKey: AzureSecretKeysEnum
63
+ dbConnectionString: string
34
64
  ): Promise<Connection> {
35
- if (!this.instances.has(secretKey)) {
36
- const vaultName = process.env.AZURE_KEY_VAULT_NAME!;
37
- if (!vaultName) throw new Error("Missing AZURE_KEY_VAULT_NAME env var");
38
-
39
- context.info(`[Mongo] fetching secret "${secretKey}" from vault "${vaultName}"`);
40
- const uri = await getAzureVaultSecretByKey(context, vaultName, secretKey);
41
- if (!uri) throw new Error(`No value for secret "${secretKey}"`);
42
-
65
+ if (!this.instances.has(dbConnectionString)) {
43
66
  context.info("[Mongo] connecting to MongoDB…");
44
- const conn = await mongoose
45
- .createConnection(uri, {})
46
- .asPromise();
47
- context.info("[Mongo] connected to MongoDB");
48
-
49
- this.instances.set(secretKey, conn);
67
+ const connPromise = mongoose
68
+ .createConnection(dbConnectionString)
69
+ .asPromise()
70
+ .then(conn => {
71
+ context.info("[Mongo] connected to MongoDB");
72
+ return conn;
73
+ })
74
+ .catch(err => {
75
+ context.error("[Mongo] connection failed", err);
76
+ throw err;
77
+ });
78
+ this.instances.set(dbConnectionString, connPromise);
50
79
  }
51
- return this.instances.get(secretKey)!;
80
+ return this.instances.get(dbConnectionString)!;
52
81
  }
53
82
  }
54
-
55
-
56
-
57
-
58
-
59
- // import mongoose, { Mongoose } from "mongoose";
60
- // import { InvocationContext } from "@azure/functions";
61
- // import { getAzureVaultSecretByKey } from "./secrets";
62
- // import { AzureSecretKeysEnum } from "../enums";
63
-
64
- // /**
65
- // * Base class for any service that needs a MongoDB connection.
66
- // * Pass in the name of the Key Vault secret that holds your MongoDB URI.
67
- // */
68
- // export abstract class Initializers {
69
- // mongoose!: Mongoose;
70
-
71
- // constructor(
72
- // context: InvocationContext,
73
- // dbConnectionSecretKey: AzureSecretKeysEnum
74
- // ) {
75
- // MongoConnectionSingleton
76
- // .getInstance(context, dbConnectionSecretKey)
77
- // .then(singleton => {
78
- // this.mongoose = singleton.mongoose;
79
- // })
80
- // .catch(err => {
81
- // context.error("Failed to initialize MongoDB:", err);
82
- // throw err;
83
- // });
84
- // }
85
- // }
86
-
87
- // /**
88
- // * A singleton manager that caches one mongoose connection per secret key.
89
- // */
90
- // class MongoConnectionSingleton {
91
- // private static instances: Map<AzureSecretKeysEnum, MongoConnectionSingleton> = new Map();
92
- // public mongoose!: Mongoose;
93
-
94
- // private constructor() { }
95
-
96
- // public static async getInstance(
97
- // context: InvocationContext,
98
- // secretKey: AzureSecretKeysEnum
99
- // ): Promise<MongoConnectionSingleton> {
100
- // if (!this.instances.has(secretKey)) {
101
- // const inst = new MongoConnectionSingleton();
102
- // await inst.connect(context, secretKey);
103
- // this.instances.set(secretKey, inst);
104
- // }
105
- // return this.instances.get(secretKey)!;
106
- // }
107
-
108
- // private async connect(
109
- // context: InvocationContext,
110
- // secretKey: AzureSecretKeysEnum
111
- // ): Promise<void> {
112
- // // 1) Fetch vault name and secret
113
- // const vaultName = process.env.AZURE_KEY_VAULT_NAME!;
114
- // if (!vaultName) throw new Error("Missing KEY_VAULT_NAME env var");
115
-
116
- // context.info(`[Mongo] Fetching connection string from vault "${vaultName}", secret "${secretKey}"`);
117
- // const connString = await getAzureVaultSecretByKey(
118
- // context,
119
- // vaultName,
120
- // secretKey
121
- // );
122
- // if (!connString) {
123
- // throw new Error(`No value found for secret "${secretKey}"`);
124
- // }
125
-
126
- // // 2) Connect via mongoose
127
- // context.info(`[Mongo] Connecting to MongoDB…`);
128
- // this.mongoose = await mongoose.connect(connString);
129
- // context.info(`[Mongo] Connected using secret "${secretKey}"`);
130
- // }
131
- // }