opticedge-cloud-utils 1.1.16 → 1.1.18

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.
@@ -1,5 +1,4 @@
1
1
  import { Db, Collection, Document } from 'mongodb';
2
- export declare function connectToMongo(projectId: string, uriSecret: string, dbName: string): Promise<void>;
3
- export declare function connectToMongoWithUri(uri: string, dbName: string): Promise<void>;
2
+ export declare function connectToMongo(uri: string, dbName: string): Promise<void>;
4
3
  export declare function getDb(): Db;
5
4
  export declare function getCollection<T extends Document = Document>(name: string): Collection<T>;
package/dist/db/mongo.js CHANGED
@@ -1,28 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.connectToMongo = connectToMongo;
4
- exports.connectToMongoWithUri = connectToMongoWithUri;
5
4
  exports.getDb = getDb;
6
5
  exports.getCollection = getCollection;
7
6
  const mongodb_1 = require("mongodb");
8
- const secrets_1 = require("../secrets");
9
7
  let client;
10
8
  let db;
11
9
  let connectPromise;
12
- async function connectToMongo(projectId, uriSecret, dbName) {
13
- if (db)
14
- return; // already connected
15
- if (!connectPromise) {
16
- connectPromise = (async () => {
17
- const uri = await (0, secrets_1.getSecret)(projectId, uriSecret);
18
- client = new mongodb_1.MongoClient(uri);
19
- await client.connect();
20
- db = client.db(dbName);
21
- })();
22
- }
23
- await connectPromise;
24
- }
25
- async function connectToMongoWithUri(uri, dbName) {
10
+ async function connectToMongo(uri, dbName) {
26
11
  if (db)
27
12
  return; // already connected
28
13
  if (!connectPromise) {
@@ -1,5 +1,4 @@
1
1
  import { Db, Collection, Document } from 'mongodb';
2
- export declare function connectToMongo2(projectId: string, uriSecret: string): Promise<void>;
3
- export declare function connectToMongoWithUri2(uri: string): Promise<void>;
2
+ export declare function connectToMongo2(uri: string): Promise<void>;
4
3
  export declare function getDb2(dbName: string): Db;
5
4
  export declare function getCollection2<T extends Document = Document>(dbName: string, collectionName: string): Collection<T>;
package/dist/db/mongo2.js CHANGED
@@ -1,27 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.connectToMongo2 = connectToMongo2;
4
- exports.connectToMongoWithUri2 = connectToMongoWithUri2;
5
4
  exports.getDb2 = getDb2;
6
5
  exports.getCollection2 = getCollection2;
7
6
  // Multi DB safe util
8
7
  const mongodb_1 = require("mongodb");
9
- const secrets_1 = require("../secrets");
10
8
  let client;
11
9
  let connectPromise;
12
- async function connectToMongo2(projectId, uriSecret) {
13
- if (client)
14
- return; // already connected
15
- if (!connectPromise) {
16
- connectPromise = (async () => {
17
- const uri = await (0, secrets_1.getSecret)(projectId, uriSecret);
18
- client = new mongodb_1.MongoClient(uri);
19
- await client.connect();
20
- })();
21
- }
22
- await connectPromise;
23
- }
24
- async function connectToMongoWithUri2(uri) {
10
+ async function connectToMongo2(uri) {
25
11
  if (client)
26
12
  return; // already connected
27
13
  if (!connectPromise) {
@@ -1,7 +1,6 @@
1
1
  import { MongoClient, Db, Collection, Document } from 'mongodb';
2
- export declare function connectToMongo3(projectId: string, uriSecret: string): Promise<MongoClient>;
3
- export declare function connectToMongoWithUri3(uri: string): Promise<MongoClient>;
4
- export declare function getDb3(uriSecret: string, dbName: string): Db;
5
- export declare function getCollection3<T extends Document = Document>(uriSecret: string, dbName: string, collectionName: string): Collection<T>;
2
+ export declare function connectToMongo3(uri: string): Promise<MongoClient>;
3
+ export declare function getDb3(uri: string, dbName: string): Db;
4
+ export declare function getCollection3<T extends Document = Document>(uri: string, dbName: string, collectionName: string): Collection<T>;
6
5
  export declare const __mongoClients: Map<string, MongoClient>;
7
6
  export declare const __connectPromises: Map<string, Promise<void>>;
package/dist/db/mongo3.js CHANGED
@@ -2,31 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.__connectPromises = exports.__mongoClients = void 0;
4
4
  exports.connectToMongo3 = connectToMongo3;
5
- exports.connectToMongoWithUri3 = connectToMongoWithUri3;
6
5
  exports.getDb3 = getDb3;
7
6
  exports.getCollection3 = getCollection3;
8
7
  // Multi cluster safe util
9
8
  const mongodb_1 = require("mongodb");
10
- const secrets_1 = require("../secrets");
11
9
  const clients = new Map();
12
10
  const connectPromises = new Map();
13
- async function connectToMongo3(projectId, uriSecret) {
14
- if (clients.has(uriSecret)) {
15
- return clients.get(uriSecret);
16
- }
17
- if (!connectPromises.has(uriSecret)) {
18
- const promise = (async () => {
19
- const uri = await (0, secrets_1.getSecret)(projectId, uriSecret);
20
- const client = new mongodb_1.MongoClient(uri);
21
- await client.connect();
22
- clients.set(uriSecret, client);
23
- })();
24
- connectPromises.set(uriSecret, promise);
25
- }
26
- await connectPromises.get(uriSecret);
27
- return clients.get(uriSecret);
28
- }
29
- async function connectToMongoWithUri3(uri) {
11
+ async function connectToMongo3(uri) {
30
12
  if (!connectPromises.has(uri)) {
31
13
  const promise = (async () => {
32
14
  const client = new mongodb_1.MongoClient(uri);
@@ -38,15 +20,15 @@ async function connectToMongoWithUri3(uri) {
38
20
  await connectPromises.get(uri);
39
21
  return clients.get(uri);
40
22
  }
41
- function getDb3(uriSecret, dbName) {
42
- const client = clients.get(uriSecret);
23
+ function getDb3(uri, dbName) {
24
+ const client = clients.get(uri);
43
25
  if (!client) {
44
- throw new Error(`Mongo client for secret "${uriSecret}" not initialized`);
26
+ throw new Error(`Mongo client not initialized`);
45
27
  }
46
28
  return client.db(dbName);
47
29
  }
48
- function getCollection3(uriSecret, dbName, collectionName) {
49
- return getDb3(uriSecret, dbName).collection(collectionName);
30
+ function getCollection3(uri, dbName, collectionName) {
31
+ return getDb3(uri, dbName).collection(collectionName);
50
32
  }
51
33
  exports.__mongoClients = clients;
52
34
  exports.__connectPromises = connectPromises;
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from './auth';
7
7
  export * from './chunk';
8
8
  export * from './env';
9
9
  export * from './parser';
10
+ export * from './pub';
10
11
  export * from './regex';
11
12
  export * from './retry';
12
13
  export * from './secrets';
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ __exportStar(require("./auth"), exports);
23
23
  __exportStar(require("./chunk"), exports);
24
24
  __exportStar(require("./env"), exports);
25
25
  __exportStar(require("./parser"), exports);
26
+ __exportStar(require("./pub"), exports);
26
27
  __exportStar(require("./regex"), exports);
27
28
  __exportStar(require("./retry"), exports);
28
29
  __exportStar(require("./secrets"), exports);
package/dist/pub.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function publishMessage(projectId: string, topicName: string, envelope: Record<string, unknown>): Promise<string>;
package/dist/pub.js ADDED
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.publishMessage = publishMessage;
4
+ // src/pub.ts
5
+ const pubsub_1 = require("@google-cloud/pubsub");
6
+ const pubsubCache = new Map();
7
+ function getPubSub(projectId) {
8
+ if (!projectId)
9
+ throw new Error('projectId is required');
10
+ let ps = pubsubCache.get(projectId);
11
+ if (!ps) {
12
+ ps = new pubsub_1.PubSub({ projectId });
13
+ pubsubCache.set(projectId, ps);
14
+ }
15
+ return ps;
16
+ }
17
+ async function publishMessage(projectId, topicName, envelope) {
18
+ if (!projectId)
19
+ throw new Error('projectId is required');
20
+ if (!topicName)
21
+ throw new Error('topicName is required');
22
+ if (envelope === undefined)
23
+ throw new Error('envelope is required');
24
+ try {
25
+ const pubsub = getPubSub(projectId);
26
+ const topic = pubsub.topic(topicName);
27
+ const data = Buffer.from(JSON.stringify(envelope));
28
+ const messageId = await topic.publishMessage({
29
+ data
30
+ });
31
+ console.info(`INFO: Pub/Sub publish project=${projectId} topic=${topicName} msg_id=${messageId}`);
32
+ return messageId;
33
+ }
34
+ catch (err) {
35
+ console.error('ERROR: publish failed:', err);
36
+ throw err;
37
+ }
38
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opticedge-cloud-utils",
3
- "version": "1.1.16",
3
+ "version": "1.1.18",
4
4
  "description": "Common utilities for cloud functions",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -16,6 +16,7 @@
16
16
  "author": "Evans Musonda",
17
17
  "license": "MIT",
18
18
  "dependencies": {
19
+ "@google-cloud/pubsub": "^5.2.0",
19
20
  "@google-cloud/secret-manager": "^6.0.1",
20
21
  "@google-cloud/tasks": "^6.1.0",
21
22
  "axios": "^1.10.0",
package/src/db/mongo.ts CHANGED
@@ -1,26 +1,10 @@
1
1
  import { MongoClient, Db, Collection, Document } from 'mongodb'
2
- import { getSecret } from '../secrets'
3
2
 
4
3
  let client: MongoClient
5
4
  let db: Db
6
5
  let connectPromise: Promise<void> | undefined
7
6
 
8
- export async function connectToMongo(projectId: string, uriSecret: string, dbName: string) {
9
- if (db) return // already connected
10
-
11
- if (!connectPromise) {
12
- connectPromise = (async () => {
13
- const uri = await getSecret(projectId, uriSecret)
14
- client = new MongoClient(uri)
15
- await client.connect()
16
- db = client.db(dbName)
17
- })()
18
- }
19
-
20
- await connectPromise
21
- }
22
-
23
- export async function connectToMongoWithUri(uri: string, dbName: string) {
7
+ export async function connectToMongo(uri: string, dbName: string) {
24
8
  if (db) return // already connected
25
9
 
26
10
  if (!connectPromise) {
package/src/db/mongo2.ts CHANGED
@@ -1,25 +1,10 @@
1
1
  // Multi DB safe util
2
2
  import { MongoClient, Db, Collection, Document } from 'mongodb'
3
- import { getSecret } from '../secrets'
4
3
 
5
4
  let client: MongoClient
6
5
  let connectPromise: Promise<void> | undefined
7
6
 
8
- export async function connectToMongo2(projectId: string, uriSecret: string) {
9
- if (client) return // already connected
10
-
11
- if (!connectPromise) {
12
- connectPromise = (async () => {
13
- const uri = await getSecret(projectId, uriSecret)
14
- client = new MongoClient(uri)
15
- await client.connect()
16
- })()
17
- }
18
-
19
- await connectPromise
20
- }
21
-
22
- export async function connectToMongoWithUri2(uri: string) {
7
+ export async function connectToMongo2(uri: string) {
23
8
  if (client) return // already connected
24
9
 
25
10
  if (!connectPromise) {
package/src/db/mongo3.ts CHANGED
@@ -1,32 +1,10 @@
1
1
  // Multi cluster safe util
2
2
  import { MongoClient, Db, Collection, Document } from 'mongodb'
3
- import { getSecret } from '../secrets'
4
3
 
5
4
  const clients: Map<string, MongoClient> = new Map()
6
5
  const connectPromises: Map<string, Promise<void>> = new Map()
7
6
 
8
- export async function connectToMongo3(projectId: string, uriSecret: string): Promise<MongoClient> {
9
- if (clients.has(uriSecret)) {
10
- return clients.get(uriSecret)!
11
- }
12
-
13
- if (!connectPromises.has(uriSecret)) {
14
- const promise = (async () => {
15
- const uri = await getSecret(projectId, uriSecret)
16
- const client = new MongoClient(uri)
17
- await client.connect()
18
- clients.set(uriSecret, client)
19
- })()
20
-
21
- connectPromises.set(uriSecret, promise)
22
- }
23
-
24
- await connectPromises.get(uriSecret)!
25
-
26
- return clients.get(uriSecret)!
27
- }
28
-
29
- export async function connectToMongoWithUri3(uri: string): Promise<MongoClient> {
7
+ export async function connectToMongo3(uri: string): Promise<MongoClient> {
30
8
  if (!connectPromises.has(uri)) {
31
9
  const promise = (async () => {
32
10
  const client = new MongoClient(uri)
@@ -42,21 +20,21 @@ export async function connectToMongoWithUri3(uri: string): Promise<MongoClient>
42
20
  return clients.get(uri)!
43
21
  }
44
22
 
45
- export function getDb3(uriSecret: string, dbName: string): Db {
46
- const client = clients.get(uriSecret)
23
+ export function getDb3(uri: string, dbName: string): Db {
24
+ const client = clients.get(uri)
47
25
  if (!client) {
48
- throw new Error(`Mongo client for secret "${uriSecret}" not initialized`)
26
+ throw new Error(`Mongo client not initialized`)
49
27
  }
50
28
 
51
29
  return client.db(dbName)
52
30
  }
53
31
 
54
32
  export function getCollection3<T extends Document = Document>(
55
- uriSecret: string,
33
+ uri: string,
56
34
  dbName: string,
57
35
  collectionName: string
58
36
  ): Collection<T> {
59
- return getDb3(uriSecret, dbName).collection<T>(collectionName)
37
+ return getDb3(uri, dbName).collection<T>(collectionName)
60
38
  }
61
39
 
62
40
  export const __mongoClients = clients
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ export * from './auth'
7
7
  export * from './chunk'
8
8
  export * from './env'
9
9
  export * from './parser'
10
+ export * from './pub'
10
11
  export * from './regex'
11
12
  export * from './retry'
12
13
  export * from './secrets'
package/src/pub.ts ADDED
@@ -0,0 +1,41 @@
1
+ // src/pub.ts
2
+ import { PubSub } from '@google-cloud/pubsub'
3
+
4
+ const pubsubCache = new Map<string, PubSub>()
5
+
6
+ function getPubSub(projectId: string): PubSub {
7
+ if (!projectId) throw new Error('projectId is required')
8
+ let ps = pubsubCache.get(projectId)
9
+ if (!ps) {
10
+ ps = new PubSub({ projectId })
11
+ pubsubCache.set(projectId, ps)
12
+ }
13
+ return ps
14
+ }
15
+
16
+ export async function publishMessage(
17
+ projectId: string,
18
+ topicName: string,
19
+ envelope: Record<string, unknown>
20
+ ): Promise<string> {
21
+ if (!projectId) throw new Error('projectId is required')
22
+ if (!topicName) throw new Error('topicName is required')
23
+ if (envelope === undefined) throw new Error('envelope is required')
24
+
25
+ try {
26
+ const pubsub = getPubSub(projectId)
27
+ const topic = pubsub.topic(topicName)
28
+ const data = Buffer.from(JSON.stringify(envelope))
29
+ const messageId = await topic.publishMessage({
30
+ data
31
+ })
32
+
33
+ console.info(
34
+ `INFO: Pub/Sub publish project=${projectId} topic=${topicName} msg_id=${messageId}`
35
+ )
36
+ return messageId
37
+ } catch (err) {
38
+ console.error('ERROR: publish failed:', err)
39
+ throw err
40
+ }
41
+ }
@@ -1,9 +1,7 @@
1
- import { connectToMongo, connectToMongoWithUri, getCollection, getDb } from '../../src/db/mongo'
1
+ import { connectToMongo, getCollection, getDb } from '../../src/db/mongo'
2
2
  import { MongoClient, Db } from 'mongodb'
3
- import * as secretsModule from '../../src/secrets'
4
3
 
5
4
  jest.mock('mongodb')
6
- jest.mock('../../src/secrets')
7
5
 
8
6
  const mockDb = {
9
7
  collection: jest.fn()
@@ -17,28 +15,26 @@ const mockClient = {
17
15
 
18
16
  beforeEach(() => {
19
17
  jest.clearAllMocks()
20
- ;(secretsModule.getSecret as jest.Mock).mockResolvedValue('mongodb://mock-uri')
21
18
  ;(MongoClient as unknown as jest.Mock).mockImplementation(() => mockClient)
22
19
  })
23
20
 
24
21
  describe('Mongo Utils', () => {
25
22
  it('should connect to MongoDB and store client/db', async () => {
26
- await connectToMongo('test-project', 'mongo-uri-secret', 'test-db')
23
+ await connectToMongo('mongo-uri', 'test-db')
27
24
 
28
- expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', 'mongo-uri-secret')
29
25
  expect(mockConnect).toHaveBeenCalled()
30
26
  expect(mockClient.db).toHaveBeenCalledWith('test-db')
31
27
  })
32
28
 
33
29
  it('should return a collection when db is initialized', async () => {
34
- await connectToMongo('test-project', 'mongo-uri-secret', 'test-db')
30
+ await connectToMongo('mongo-uri', 'test-db')
35
31
  getCollection('users')
36
32
 
37
33
  expect(mockDb.collection).toHaveBeenCalledWith('users')
38
34
  })
39
35
 
40
36
  it('getDb should return the initialized Db instance', async () => {
41
- await connectToMongo('test-project', 'mongo-uri-secret', 'test-db')
37
+ await connectToMongo('mongo-uri', 'test-db')
42
38
  const got = getDb()
43
39
  expect(got).toBe(mockDb)
44
40
  })
@@ -53,30 +49,3 @@ describe('Mongo Utils', () => {
53
49
  })
54
50
  })
55
51
  })
56
-
57
- describe('Mongo Utils 2', () => {
58
- it('should connect to MongoDB and store client/db with URI helper', async () => {
59
- // isolate modules so connect state is fresh for this test
60
- await jest.isolateModulesAsync(async () => {
61
- // eslint-disable-next-line @typescript-eslint/no-require-imports
62
- const { connectToMongoWithUri } = require('../../src/db/mongo')
63
- await connectToMongoWithUri('mongo-uri', 'test-db')
64
-
65
- expect(mockConnect).toHaveBeenCalled()
66
- expect(mockClient.db).toHaveBeenCalledWith('test-db')
67
- })
68
- })
69
-
70
- it('should return a collection when db is initialized (connectToMongoWithUri)', async () => {
71
- await connectToMongoWithUri('mongo-uri', 'test-db')
72
- getCollection('users')
73
-
74
- expect(mockDb.collection).toHaveBeenCalledWith('users')
75
- })
76
-
77
- it('getDb should return the initialized Db instance after connectToMongoWithUri', async () => {
78
- await connectToMongoWithUri('mongo-uri', 'test-db')
79
- const got = getDb()
80
- expect(got).toBe(mockDb)
81
- })
82
- })
@@ -1,14 +1,7 @@
1
- import {
2
- connectToMongo2,
3
- getDb2,
4
- getCollection2,
5
- connectToMongoWithUri2
6
- } from '../../src/db/mongo2'
1
+ import { connectToMongo2, getDb2, getCollection2 } from '../../src/db/mongo2'
7
2
  import { MongoClient, Db } from 'mongodb'
8
- import * as secretsModule from '../../src/secrets'
9
3
 
10
4
  jest.mock('mongodb')
11
- jest.mock('../../src/secrets')
12
5
 
13
6
  const mockDb = {
14
7
  collection: jest.fn()
@@ -22,20 +15,18 @@ const mockClient = {
22
15
 
23
16
  beforeEach(() => {
24
17
  jest.clearAllMocks()
25
- ;(secretsModule.getSecret as jest.Mock).mockResolvedValue('mongodb://mock-uri')
26
18
  ;(MongoClient as unknown as jest.Mock).mockImplementation(() => mockClient)
27
19
  })
28
20
 
29
21
  describe('Mongo Utils', () => {
30
22
  it('should connect to MongoDB and store client', async () => {
31
- await connectToMongo2('test-project', 'mongo-uri-secret')
23
+ await connectToMongo2('mongo-uri')
32
24
 
33
- expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', 'mongo-uri-secret')
34
25
  expect(mockConnect).toHaveBeenCalled()
35
26
  })
36
27
 
37
28
  it('should return a Db instance when client is initialized', async () => {
38
- await connectToMongo2('test-project', 'mongo-uri-secret')
29
+ await connectToMongo2('mongo-uri')
39
30
 
40
31
  const db = getDb2('test-db')
41
32
  expect(mockClient.db).toHaveBeenCalledWith('test-db')
@@ -43,7 +34,7 @@ describe('Mongo Utils', () => {
43
34
  })
44
35
 
45
36
  it('should return a collection when client is initialized', async () => {
46
- await connectToMongo2('test-project', 'mongo-uri-secret')
37
+ await connectToMongo2('mongo-uri')
47
38
 
48
39
  getCollection2('test-db', 'users')
49
40
  expect(mockClient.db).toHaveBeenCalledWith('test-db')
@@ -66,31 +57,3 @@ describe('Mongo Utils', () => {
66
57
  })
67
58
  })
68
59
  })
69
-
70
- describe('Mongo Utils 2', () => {
71
- it('should connect to MongoDB and store client', async () => {
72
- jest.isolateModules(async () => {
73
- // eslint-disable-next-line @typescript-eslint/no-require-imports
74
- const { connectToMongoWithUri2 } = require('../../src/db/mongo2')
75
- await connectToMongoWithUri2('mongo-uri')
76
-
77
- expect(mockConnect).toHaveBeenCalled()
78
- })
79
- })
80
-
81
- it('should return a Db instance when client is initialized', async () => {
82
- await connectToMongoWithUri2('mongo-uri')
83
-
84
- const db = getDb2('test-db')
85
- expect(mockClient.db).toHaveBeenCalledWith('test-db')
86
- expect(db).toBe(mockDb)
87
- })
88
-
89
- it('should return a collection when client is initialized', async () => {
90
- await connectToMongoWithUri2('mongo-uri')
91
-
92
- getCollection2('test-db', 'users')
93
- expect(mockClient.db).toHaveBeenCalledWith('test-db')
94
- expect(mockDb.collection).toHaveBeenCalledWith('users')
95
- })
96
- })
@@ -3,14 +3,11 @@ import {
3
3
  getDb3,
4
4
  getCollection3,
5
5
  __mongoClients,
6
- __connectPromises,
7
- connectToMongoWithUri3
6
+ __connectPromises
8
7
  } from '../../src/db/mongo3'
9
8
  import { MongoClient, Db } from 'mongodb'
10
- import * as secretsModule from '../../src/secrets'
11
9
 
12
10
  jest.mock('mongodb')
13
- jest.mock('../../src/secrets')
14
11
 
15
12
  const mockDb = {
16
13
  collection: jest.fn()
@@ -26,54 +23,41 @@ beforeEach(() => {
26
23
  jest.clearAllMocks()
27
24
  __mongoClients.clear()
28
25
  __connectPromises.clear()
29
- ;(secretsModule.getSecret as jest.Mock).mockResolvedValue('mongodb://mock-uri')
30
26
  ;(MongoClient as unknown as jest.Mock).mockImplementation(() => mockClient)
31
27
  })
32
28
 
33
29
  describe('MongoClientManager (multi-cluster)', () => {
34
- const clusterASecret = 'clusterA-uri-secret'
35
- const clusterBSecret = 'clusterB-uri-secret'
30
+ const clusterAUri = 'clusterA-uri'
31
+ const clusterBUri = 'clusterB-uri'
36
32
 
37
33
  it('should connect and cache client for a single cluster', async () => {
38
- await connectToMongo3('test-project', clusterASecret)
34
+ await connectToMongo3(clusterAUri)
39
35
 
40
- expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', clusterASecret)
41
36
  expect(mockConnect).toHaveBeenCalled()
42
37
 
43
- const db = getDb3(clusterASecret, 'test-db')
38
+ const db = getDb3(clusterAUri, 'test-db')
44
39
  expect(mockClient.db).toHaveBeenCalledWith('test-db')
45
40
  expect(db).toBe(mockDb)
46
41
  })
47
42
 
48
43
  it('should reuse client if already connected', async () => {
49
- await connectToMongo3('test-project', clusterASecret)
50
- await connectToMongo3('test-project', clusterASecret)
44
+ await connectToMongo3(clusterAUri)
45
+ await connectToMongo3(clusterAUri)
51
46
 
52
- // getSecret and connect should only happen once
53
- expect(secretsModule.getSecret).toHaveBeenCalledTimes(1)
54
47
  expect(mockConnect).toHaveBeenCalledTimes(1)
55
48
  })
56
49
 
57
50
  it('should connect and cache separate clients for multiple clusters', async () => {
58
- // Mock different URIs for 2 clusters
59
- ;(secretsModule.getSecret as jest.Mock)
60
- .mockResolvedValueOnce('mongodb://mock-uri-A')
61
- .mockResolvedValueOnce('mongodb://mock-uri-B')
62
-
63
- await connectToMongo3('test-project', clusterASecret)
64
- await connectToMongo3('test-project', clusterBSecret)
65
-
66
- // Should call getSecret + connect twice (for 2 clusters)
67
- expect(secretsModule.getSecret).toHaveBeenCalledTimes(2)
68
- expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', clusterASecret)
69
- expect(secretsModule.getSecret).toHaveBeenCalledWith('test-project', clusterBSecret)
51
+ await connectToMongo3(clusterAUri)
52
+ await connectToMongo3(clusterBUri)
53
+
70
54
  expect(mockConnect).toHaveBeenCalledTimes(2)
71
55
  })
72
56
 
73
57
  it('should return a collection when client is initialized', async () => {
74
- await connectToMongo3('test-project', clusterASecret)
58
+ await connectToMongo3(clusterAUri)
75
59
 
76
- getCollection3(clusterASecret, 'test-db', 'users')
60
+ getCollection3(clusterAUri, 'test-db', 'users')
77
61
 
78
62
  expect(mockClient.db).toHaveBeenCalledWith('test-db')
79
63
  expect(mockDb.collection).toHaveBeenCalledWith('users')
@@ -83,9 +67,7 @@ describe('MongoClientManager (multi-cluster)', () => {
83
67
  jest.isolateModules(() => {
84
68
  // eslint-disable-next-line @typescript-eslint/no-require-imports
85
69
  const { getDb3 } = require('../../src/db/mongo3')
86
- expect(() => getDb3('unknown-uri-secret', 'some-db')).toThrow(
87
- 'Mongo client for secret "unknown-uri-secret" not initialized'
88
- )
70
+ expect(() => getDb3('unknown-uri', 'some-db')).toThrow('Mongo client not initialized')
89
71
  })
90
72
  })
91
73
 
@@ -93,57 +75,9 @@ describe('MongoClientManager (multi-cluster)', () => {
93
75
  jest.isolateModules(() => {
94
76
  // eslint-disable-next-line @typescript-eslint/no-require-imports
95
77
  const { getCollection3 } = require('../../src/db/mongo3')
96
- expect(() => getCollection3('unknown-uri-secret', 'some-db', 'users')).toThrow(
97
- 'Mongo client for secret "unknown-uri-secret" not initialized'
78
+ expect(() => getCollection3('unknown-uri', 'some-db', 'users')).toThrow(
79
+ 'Mongo client not initialized'
98
80
  )
99
81
  })
100
82
  })
101
83
  })
102
-
103
- describe('MongoClientManager (multi-cluster) 2', () => {
104
- const clusterAUri = 'clusterA-uri'
105
- const clusterBUri = 'clusterB-uri'
106
-
107
- it('should connect and cache client for a single cluster', async () => {
108
- jest.isolateModules(async () => {
109
- // eslint-disable-next-line @typescript-eslint/no-require-imports
110
- const { connectToMongoWithUri3, getDb3 } = require('../../src/db/mongo3')
111
- await connectToMongoWithUri3(clusterAUri)
112
-
113
- expect(mockConnect).toHaveBeenCalled()
114
-
115
- const db = getDb3(clusterAUri, 'test-db')
116
- expect(mockClient.db).toHaveBeenCalledWith('test-db')
117
- expect(db).toBe(mockDb)
118
- })
119
- })
120
-
121
- it('should reuse client if already connected', async () => {
122
- jest.isolateModules(async () => {
123
- // eslint-disable-next-line @typescript-eslint/no-require-imports
124
- const { connectToMongoWithUri3 } = require('../../src/db/mongo3')
125
- await connectToMongoWithUri3(clusterAUri)
126
- await connectToMongoWithUri3(clusterAUri)
127
- expect(mockConnect).toHaveBeenCalledTimes(1)
128
- })
129
- })
130
-
131
- it('should connect and cache separate clients for multiple clusters', async () => {
132
- jest.isolateModules(async () => {
133
- // eslint-disable-next-line @typescript-eslint/no-require-imports
134
- const { connectToMongoWithUri3 } = require('../../src/db/mongo3')
135
- await connectToMongoWithUri3(clusterAUri)
136
- await connectToMongoWithUri3(clusterBUri)
137
- expect(mockConnect).toHaveBeenCalledTimes(2)
138
- })
139
- })
140
-
141
- it('should return a collection when client is initialized', async () => {
142
- await connectToMongoWithUri3(clusterAUri)
143
-
144
- getCollection3(clusterAUri, 'test-db', 'users')
145
-
146
- expect(mockClient.db).toHaveBeenCalledWith('test-db')
147
- expect(mockDb.collection).toHaveBeenCalledWith('users')
148
- })
149
- })
@@ -0,0 +1,85 @@
1
+ // tests/pub.test.ts
2
+ jest.mock('@google-cloud/pubsub', () => {
3
+ const instances: any[] = []
4
+
5
+ class PubSub {
6
+ opts: any
7
+ topics = new Map<string, any>()
8
+ constructor(opts?: any) {
9
+ this.opts = opts
10
+ instances.push(this)
11
+ }
12
+ topic(name: string) {
13
+ if (!this.topics.has(name)) {
14
+ const publishMessage = jest.fn(({ data }: { data: Buffer }) =>
15
+ Promise.resolve(`${this.opts?.projectId}-${name}`)
16
+ )
17
+ this.topics.set(name, { publishMessage })
18
+ }
19
+ return this.topics.get(name)
20
+ }
21
+ }
22
+
23
+ return { PubSub, __instances: instances }
24
+ })
25
+
26
+ const path = '../src/pub'
27
+
28
+ describe('publishMessage', () => {
29
+ beforeEach(() => {
30
+ // Ensure a fresh module load so the mocked PubSub and src/pub share the same mock instance
31
+ jest.resetModules()
32
+ })
33
+
34
+ test('publishes and returns messageId, sends JSON buffer', async () => {
35
+ const mockPubsub = require('@google-cloud/pubsub')
36
+ const { publishMessage } = require(path)
37
+ const envelope = { hello: 'world' }
38
+
39
+ const msgId = await publishMessage('project-1', 'topic-a', envelope)
40
+ expect(msgId).toBe('project-1-topic-a')
41
+
42
+ const instance = mockPubsub.__instances[0]
43
+ expect(instance).toBeDefined()
44
+
45
+ const publishMock = instance.topics.get('topic-a').publishMessage
46
+ expect(publishMock).toHaveBeenCalledTimes(1)
47
+
48
+ const callArg = publishMock.mock.calls[0][0]
49
+ expect(callArg).toHaveProperty('data')
50
+ expect(callArg.data.toString()).toBe(JSON.stringify(envelope))
51
+ })
52
+
53
+ test('throws on missing arguments', async () => {
54
+ const { publishMessage } = require(path)
55
+ await expect(publishMessage('', 't', {})).rejects.toThrow('projectId is required')
56
+ await expect(publishMessage('p', '', {})).rejects.toThrow('topicName is required')
57
+ await expect(publishMessage('p', 't', undefined as any)).rejects.toThrow('envelope is required')
58
+ })
59
+
60
+ test('caches one PubSub instance per project', async () => {
61
+ const mockPubsub = require('@google-cloud/pubsub')
62
+ const { publishMessage } = require(path)
63
+
64
+ await publishMessage('project-1', 'topic-x', { a: 1 })
65
+ await publishMessage('project-1', 'topic-x', { b: 2 })
66
+
67
+ const instances = mockPubsub.__instances
68
+ expect(instances.length).toBe(1)
69
+ const publishMock = instances[0].topics.get('topic-x').publishMessage
70
+ expect(publishMock).toHaveBeenCalledTimes(2)
71
+ })
72
+
73
+ test('creates separate PubSub instances for different projects', async () => {
74
+ const mockPubsub = require('@google-cloud/pubsub')
75
+ const { publishMessage } = require(path)
76
+
77
+ await publishMessage('project-A', 't1', { x: 1 })
78
+ await publishMessage('project-B', 't2', { y: 2 })
79
+
80
+ const instances = mockPubsub.__instances
81
+ expect(instances.length).toBe(2)
82
+ expect(instances[0].opts).toEqual({ projectId: 'project-A' })
83
+ expect(instances[1].opts).toEqual({ projectId: 'project-B' })
84
+ })
85
+ })