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.
- package/dist/db/mongo.d.ts +1 -2
- package/dist/db/mongo.js +1 -16
- package/dist/db/mongo2.d.ts +1 -2
- package/dist/db/mongo2.js +1 -15
- package/dist/db/mongo3.d.ts +3 -4
- package/dist/db/mongo3.js +6 -24
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/pub.d.ts +1 -0
- package/dist/pub.js +38 -0
- package/package.json +2 -1
- package/src/db/mongo.ts +1 -17
- package/src/db/mongo2.ts +1 -16
- package/src/db/mongo3.ts +6 -28
- package/src/index.ts +1 -0
- package/src/pub.ts +41 -0
- package/tests/db/mongo.test.ts +4 -35
- package/tests/db/mongo2.test.ts +4 -41
- package/tests/db/mongo3.test.ts +15 -81
- package/tests/pub.test.ts +85 -0
package/dist/db/mongo.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Db, Collection, Document } from 'mongodb';
|
|
2
|
-
export declare function connectToMongo(
|
|
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(
|
|
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) {
|
package/dist/db/mongo2.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Db, Collection, Document } from 'mongodb';
|
|
2
|
-
export declare function connectToMongo2(
|
|
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(
|
|
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) {
|
package/dist/db/mongo3.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { MongoClient, Db, Collection, Document } from 'mongodb';
|
|
2
|
-
export declare function connectToMongo3(
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
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(
|
|
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(
|
|
42
|
-
const client = clients.get(
|
|
23
|
+
function getDb3(uri, dbName) {
|
|
24
|
+
const client = clients.get(uri);
|
|
43
25
|
if (!client) {
|
|
44
|
-
throw new Error(`Mongo client
|
|
26
|
+
throw new Error(`Mongo client not initialized`);
|
|
45
27
|
}
|
|
46
28
|
return client.db(dbName);
|
|
47
29
|
}
|
|
48
|
-
function getCollection3(
|
|
49
|
-
return getDb3(
|
|
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
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.
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
46
|
-
const client = clients.get(
|
|
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
|
|
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
|
-
|
|
33
|
+
uri: string,
|
|
56
34
|
dbName: string,
|
|
57
35
|
collectionName: string
|
|
58
36
|
): Collection<T> {
|
|
59
|
-
return getDb3(
|
|
37
|
+
return getDb3(uri, dbName).collection<T>(collectionName)
|
|
60
38
|
}
|
|
61
39
|
|
|
62
40
|
export const __mongoClients = clients
|
package/src/index.ts
CHANGED
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
|
+
}
|
package/tests/db/mongo.test.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { connectToMongo,
|
|
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('
|
|
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('
|
|
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('
|
|
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
|
-
})
|
package/tests/db/mongo2.test.ts
CHANGED
|
@@ -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('
|
|
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('
|
|
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('
|
|
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
|
-
})
|
package/tests/db/mongo3.test.ts
CHANGED
|
@@ -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
|
|
35
|
-
const
|
|
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(
|
|
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(
|
|
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(
|
|
50
|
-
await connectToMongo3(
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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(
|
|
58
|
+
await connectToMongo3(clusterAUri)
|
|
75
59
|
|
|
76
|
-
getCollection3(
|
|
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
|
|
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
|
|
97
|
-
'Mongo client
|
|
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
|
+
})
|