diff --git a/app/v4/host.json b/app/v4/host.json index 4b1999c..7ce80aa 100644 --- a/app/v4/host.json +++ b/app/v4/host.json @@ -1,6 +1,9 @@ { "version": "2.0", "logging": { + "logLevel": { + "Microsoft.Azure.Functions.Extensions.Connector": "Information" + }, "applicationInsights": { "samplingSettings": { "isEnabled": true, @@ -9,10 +12,7 @@ } }, "extensionBundle": { - "id": "Microsoft.Azure.Functions.ExtensionBundle", - "version": "[4.*, 5.0.0)" - }, - "mcp": { - "enabled": true + "id": "Microsoft.Azure.Functions.ExtensionBundle.Preview", + "version": "[4.43.*, 5.0.0)" } -} +} \ No newline at end of file diff --git a/app/v4/package-lock.json b/app/v4/package-lock.json index 78f3df2..82f03a9 100644 --- a/app/v4/package-lock.json +++ b/app/v4/package-lock.json @@ -8,7 +8,7 @@ "name": "v4", "version": "1.0.0", "dependencies": { - "@azure/functions": "^4.12.0" + "@azure/functions": "4.16.0-preview" }, "devDependencies": { "@types/long": "^4.0.0", @@ -17,27 +17,62 @@ "typescript": "^4.0.0" } }, - "node_modules/@azure/functions": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@azure/functions/-/functions-4.12.0.tgz", - "integrity": "sha512-aHBSvEDHOUhLhkivPiotoYfE6WPZdutv9OnXEkSqYtyWjbf1k/DoQ/Z9swqIbyaBSvh2xOR8ARKj5CR/2jqEOw==", + "../../../azure-functions-nodejs-library": { + "name": "@azure/functions", + "version": "4.16.0-preview", "license": "MIT", "dependencies": { "@azure/functions-extensions-base": "0.2.0", "cookie": "^0.7.0" }, + "devDependencies": { + "@types/chai": "^4.2.22", + "@types/chai-as-promised": "^7.1.5", + "@types/cookie": "^0.6.0", + "@types/fs-extra": "^9.0.13", + "@types/long": "^4.0.2", + "@types/minimist": "^1.2.2", + "@types/mocha": "^9.1.1", + "@types/node": "^20.0.0", + "@types/semver": "^7.3.9", + "@types/sinon": "^17.0.4", + "@typescript-eslint/eslint-plugin": "^5.12.1", + "@typescript-eslint/parser": "^5.12.1", + "chai": "^4.2.0", + "chai-as-promised": "^7.1.1", + "eslint": "^7.32.0", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-deprecation": "^1.3.2", + "eslint-plugin-header": "^3.1.1", + "eslint-plugin-import": "^2.29.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "eslint-webpack-plugin": "^3.2.0", + "fork-ts-checker-webpack-plugin": "^7.2.13", + "fs-extra": "^10.0.1", + "globby": "^11.0.0", + "long": "^4.0.0", + "minimist": "^1.2.6", + "mocha": "^11.1.0", + "mocha-junit-reporter": "^2.0.2", + "mocha-multi-reporters": "^1.5.1", + "prettier": "^2.4.1", + "semver": "^7.3.5", + "sinon": "^20.0.0", + "ts-loader": "^9.5.1", + "ts-node": "^10.9.2", + "typescript": "~5.0.0", + "typescript4": "npm:typescript@~4.0.0", + "webpack": "^5.74.0", + "webpack-cli": "^4.10.0" + }, "engines": { "node": ">=20.0" } }, - "node_modules/@azure/functions-extensions-base": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@azure/functions-extensions-base/-/functions-extensions-base-0.2.0.tgz", - "integrity": "sha512-ncCkHBNQYJa93dBIh+toH0v1iSgCzSo9tr94s6SMBe7DPWREkaWh8cq33A5P4rPSFX1g5W+3SPvIzDr/6/VOWQ==", - "license": "MIT", - "engines": { - "node": ">=18.0" - } + "node_modules/@azure/functions": { + "resolved": "../../../azure-functions-nodejs-library", + "link": true }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -143,15 +178,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", diff --git a/app/v4/package.json b/app/v4/package.json index 68646d5..08cf0f6 100644 --- a/app/v4/package.json +++ b/app/v4/package.json @@ -12,7 +12,7 @@ "test": "echo \"No tests yet...\"" }, "dependencies": { - "@azure/functions": "^4.12.0" + "@azure/functions": "4.16.0-preview" }, "devDependencies": { "@types/long": "^4.0.0", diff --git a/app/v4/src/functions/cosmosDBMongoTrigger.ts b/app/v4/src/functions/cosmosDBMongoTrigger.ts new file mode 100644 index 0000000..86c40ef --- /dev/null +++ b/app/v4/src/functions/cosmosDBMongoTrigger.ts @@ -0,0 +1,22 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +import { app, InvocationContext } from '@azure/functions'; + +export async function cosmosDBMongoTrigger(change: any, context: InvocationContext): Promise { + const document = change && change.fullDocument; + const documentId = (document && document._id) || (change && change.documentKey && change.documentKey._id); + + context.log(`cosmosDBMongoTrigger operation "${change && change.operationType}" for "${documentId}"`); + context.log(`cosmosDBMongoTrigger saw "${document && document.testData}"`); +} + +app.cosmosDBMongo('cosmosDBMongoTrigger', { + connectionStringSetting: 'CosmosDBMongoConnection', + databaseName: 'e2eTestCosmosDBMongo', + collectionName: 'e2eTestCollectionTrigger', + createIfNotExists: true, + leaseDatabaseName: 'e2eTestCosmosDBMongo', + leaseCollectionName: 'e2eLeasesTrigger', + handler: cosmosDBMongoTrigger, +}); diff --git a/app/v4/src/functions/cosmosDBMongoTriggerAndOutput.ts b/app/v4/src/functions/cosmosDBMongoTriggerAndOutput.ts new file mode 100644 index 0000000..8aa0d04 --- /dev/null +++ b/app/v4/src/functions/cosmosDBMongoTriggerAndOutput.ts @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +import { app, InvocationContext, output } from '@azure/functions'; + +const cosmosDBMongoOutput = output.cosmosDBMongo({ + connectionStringSetting: 'CosmosDBMongoConnection', + databaseName: 'e2eTestCosmosDBMongo', + collectionName: 'e2eTestCollectionTrigger', + createIfNotExists: true, +}); + +export async function cosmosDBMongoTriggerAndOutput(change: any, context: InvocationContext): Promise { + const document = change && change.fullDocument; + const documentId = (document && document._id) || (change && change.documentKey && change.documentKey._id); + + context.log(`cosmosDBMongoTriggerAndOutput operation "${change && change.operationType}" for "${documentId}"`); + context.log(`cosmosDBMongoTriggerAndOutput saw "${document && document.testData}"`); + + if (document) { + context.extraOutputs.set(cosmosDBMongoOutput, document); + } +} + +app.cosmosDBMongo('cosmosDBMongoTriggerAndOutput', { + connectionStringSetting: 'CosmosDBMongoConnection', + databaseName: 'e2eTestCosmosDBMongo', + collectionName: 'e2eTestCollectionTriggerAndOutput', + createIfNotExists: true, + leaseDatabaseName: 'e2eTestCosmosDBMongo', + leaseCollectionName: 'e2eLeasesTriggerAndOutput', + extraOutputs: [cosmosDBMongoOutput], + handler: cosmosDBMongoTriggerAndOutput, +}); diff --git a/app/v4/src/functions/httpTriggerCosmosDBMongoInput.ts b/app/v4/src/functions/httpTriggerCosmosDBMongoInput.ts new file mode 100644 index 0000000..17b7f22 --- /dev/null +++ b/app/v4/src/functions/httpTriggerCosmosDBMongoInput.ts @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +import { app, HttpRequest, HttpResponseInit, input, InvocationContext } from '@azure/functions'; + +const cosmosDBMongoInput = input.cosmosDBMongo({ + connectionStringSetting: 'CosmosDBMongoConnection', + databaseName: 'e2eTestCosmosDBMongo', + collectionName: 'e2eTestCollectionTriggerAndOutput', + queryString: '{{"_id":"{Query.id}"}}', + createIfNotExists: true, +}); + +export async function httpTriggerCosmosDBMongoInput( + _request: HttpRequest, + context: InvocationContext +): Promise { + const result = context.extraInputs.get(cosmosDBMongoInput); + const documents = typeof result === 'string' ? JSON.parse(result) : result; + const document = Array.isArray(documents) ? documents[0] : documents; + return { body: document ? (document).testData : '' }; +} + +app.http('httpTriggerCosmosDBMongoInput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraInputs: [cosmosDBMongoInput], + handler: httpTriggerCosmosDBMongoInput, +}); diff --git a/app/v4/src/functions/httpTriggerCosmosDBMongoOutput.ts b/app/v4/src/functions/httpTriggerCosmosDBMongoOutput.ts new file mode 100644 index 0000000..1b91bd4 --- /dev/null +++ b/app/v4/src/functions/httpTriggerCosmosDBMongoOutput.ts @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +import { app, HttpRequest, HttpResponseInit, InvocationContext, output } from '@azure/functions'; + +const cosmosDBMongoOutput = output.cosmosDBMongo({ + connectionStringSetting: 'CosmosDBMongoConnection', + databaseName: 'e2eTestCosmosDBMongo', + collectionName: 'e2eTestCollectionTrigger', + createIfNotExists: true, +}); + +export async function httpTriggerCosmosDBMongoOutput( + request: HttpRequest, + context: InvocationContext +): Promise { + const body = await request.json(); + context.extraOutputs.set(cosmosDBMongoOutput, body); + return { body: 'done' }; +} + +app.http('httpTriggerCosmosDBMongoOutput', { + methods: ['GET', 'POST'], + authLevel: 'anonymous', + extraOutputs: [cosmosDBMongoOutput], + handler: httpTriggerCosmosDBMongoOutput, +}); diff --git a/package-lock.json b/package-lock.json index 94f02ef..a7fc196 100644 --- a/package-lock.json +++ b/package-lock.json @@ -50,6 +50,7 @@ "mocha": "^10.8.2", "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", + "mongodb": "^6.0.0", "mssql": "^10.0.2", "node-fetch": "2.6.7", "p-retry": "^4.0.0", @@ -1213,6 +1214,14 @@ "dev": true, "license": "MIT" }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.4.11.tgz", + "integrity": "sha512-o9rAHc0IpIjuPSxRutWpE1F62x7n+4mVS4rCNHkzhIUMQcc18bb6xEq5wd2NdN0WjepIyXIppRshYI2kQDOZVA==", + "dependencies": { + "sparse-bitfield": "^3.0.3" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1387,6 +1396,19 @@ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.5.tgz", "integrity": "sha512-xfHdwa1FMJ082prjSJpoEI57GZITiQz10r3vEJCHa2khEFQjKy91aWKz6+zybzssCvXUwE1LQWgWVwZ4nYUvHQ==" }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==" + }, + "node_modules/@types/whatwg-url": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz", + "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", @@ -2243,6 +2265,14 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bson": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", + "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", + "engines": { + "node": ">=16.20.1" + } + }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -4973,6 +5003,11 @@ "node": ">= 0.8" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==" + }, "node_modules/merge-descriptors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", @@ -5209,6 +5244,91 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/mongodb": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.21.0.tgz", + "integrity": "sha512-URyb/VXMjJ4da46OeSXg+puO39XH9DeQpWCslifrRn9JWugy0D+DvvBvkm2WxmHe61O/H19JM66p1z7RHVkZ6A==", + "dependencies": { + "@mongodb-js/saslprep": "^1.3.0", + "bson": "^6.10.4", + "mongodb-connection-string-url": "^3.0.2" + }, + "engines": { + "node": ">=16.20.1" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.188.0", + "@mongodb-js/zstd": "^1.1.0 || ^2.0.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.3.2", + "socks": "^2.7.1" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "gcp-metadata": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + }, + "socks": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^14.1.0 || ^13.0.0" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5706,9 +5826,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } @@ -6412,6 +6532,14 @@ "node": ">=0.10.0" } }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", diff --git a/package.json b/package.json index 0c905d0..89f7df1 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "mocha": "^10.8.2", "mocha-junit-reporter": "^2.0.2", "mocha-multi-reporters": "^1.5.1", + "mongodb": "^6.0.0", "mssql": "^10.0.2", "node-fetch": "2.6.7", "p-retry": "^4.0.0", diff --git a/src/constants.ts b/src/constants.ts index ff651c7..2dfdfef 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,6 +4,7 @@ export namespace EnvVarNames { export const storage = 'AzureWebJobsStorage'; export const cosmosDB = 'CosmosDBConnection'; + export const cosmosDBMongo = 'CosmosDBMongoConnection'; export const eventHub = 'EventHubConnection'; export const serviceBus = 'ServiceBusConnection'; export const sql = 'SqlConnection'; @@ -17,6 +18,15 @@ export namespace CosmosDB { export const partitionKey = 'testPartKey'; } +export namespace CosmosDBMongo { + export const dbName = 'e2eTestCosmosDBMongo'; + export const triggerCollectionName = 'e2eTestCollectionTrigger'; + export const triggerAndOutputCollectionName = 'e2eTestCollectionTriggerAndOutput'; + export const leaseDbName = 'e2eTestCosmosDBMongo'; + export const leaseCollectionTrigger = 'e2eLeasesTrigger'; + export const leaseCollectionTriggerAndOutput = 'e2eLeasesTriggerAndOutput'; +} + export namespace EventHub { export const eventHubOneTriggerAndOutput = 'e2e-test-hub-one-trigger-and-output'; export const eventHubManyTriggerAndOutput = 'e2e-test-hub-many-trigger-and-output'; diff --git a/src/cosmosDBMongo.test.ts b/src/cosmosDBMongo.test.ts new file mode 100644 index 0000000..2149a81 --- /dev/null +++ b/src/cosmosDBMongo.test.ts @@ -0,0 +1,58 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +import { expect } from 'chai'; +import { default as fetch } from 'node-fetch'; +import { MongoClient } from 'mongodb'; +import { getFuncUrl, CosmosDBMongo } from './constants'; +import { waitForOutput } from './global.test'; +import { cosmosDBMongoConnectionString } from './utils/connectionStrings'; +import { getRandomTestData } from './utils/getRandomTestData'; + +describe('cosmosDBMongo', () => { + let client: MongoClient; + + before(async () => { + client = new MongoClient(cosmosDBMongoConnectionString); + await client.connect(); + }); + + after(async () => { + await client.close(); + }); + + it('trigger and output via change stream', async () => { + const collection = client + .db(CosmosDBMongo.dbName) + .collection(CosmosDBMongo.triggerAndOutputCollectionName); + + const testData = getRandomTestData(); + const result = await collection.insertOne({ testData }); + + await waitForOutput(`cosmosDBMongoTriggerAndOutput saw "${testData}"`); + await waitForOutput(`cosmosDBMongoTrigger saw "${testData}"`); + + const url = `${getFuncUrl('httpTriggerCosmosDBMongoInput')}?id=${result.insertedId}`; + const response = await fetch(url); + const body = await response.text(); + expect(body).to.equal(testData); + }); + + it('extra output via http', async () => { + const url = getFuncUrl('httpTriggerCosmosDBMongoOutput'); + + const singleData = getRandomTestData(); + const singleDoc = { testData: singleData }; + await fetch(url, { method: 'POST', body: JSON.stringify(singleDoc) }); + await waitForOutput(`cosmosDBMongoTrigger saw "${singleData}"`); + + const bulkDocs = Array.from({ length: 3 }, () => { + const data = getRandomTestData(); + return { testData: data }; + }); + await fetch(url, { method: 'POST', body: JSON.stringify(bulkDocs) }); + for (const doc of bulkDocs) { + await waitForOutput(`cosmosDBMongoTrigger saw "${doc.testData}"`); + } + }); +}); diff --git a/src/global.test.ts b/src/global.test.ts index eb2e4e2..3a1aaed 100644 --- a/src/global.test.ts +++ b/src/global.test.ts @@ -9,6 +9,7 @@ import { combinedFolder, defaultTimeout, EnvVarNames, oldConfigSuffix, ServiceBu import { getModelArg, getOldConfigArg, getTestFileFilter, Model } from './getModelArg'; import { cosmosDBConnectionString, + cosmosDBMongoConnectionString, eventHubConnectionString, initializeConnectionStrings, serviceBusConnectionString, @@ -18,6 +19,7 @@ import { import { delay } from './utils/delay'; import findProcess = require('find-process'); import { setupCosmosDB } from './utils/cosmosdb/setupCosmosDB'; +import { setupCosmosDBMongo } from './utils/cosmosdbmongo/setupCosmosDBMongo'; import { setupServiceBus } from './utils/servicebus/setupServiceBus'; import { runSqlSetupQueries } from './utils/sql/setupSql'; @@ -49,6 +51,7 @@ before(async function (this: Mocha.Context): Promise { if (only?.startsWith(ServiceBus.serviceBusTestFileName)) { await runSqlSetupQueries(); await setupCosmosDB(); + await setupCosmosDBMongo(); } // Setup ServiceBus entities for v4 model (includes both MCP and ServiceBus functions) @@ -157,6 +160,7 @@ async function startFuncProcess(appPath: string, disableServiceBusFunctions: boo logging__logLevel__Worker: 'debug', [EnvVarNames.storage]: storageConnectionString, [EnvVarNames.cosmosDB]: cosmosDBConnectionString, + [EnvVarNames.cosmosDBMongo]: cosmosDBMongoConnectionString, [EnvVarNames.eventHub]: eventHubConnectionString, [EnvVarNames.serviceBus]: serviceBusConnectionString, [EnvVarNames.sql]: sqlTestConnectionString, diff --git a/src/utils/connectionStrings.ts b/src/utils/connectionStrings.ts index 31b6501..a34d5e0 100644 --- a/src/utils/connectionStrings.ts +++ b/src/utils/connectionStrings.ts @@ -3,6 +3,7 @@ export let storageConnectionString: string; export let cosmosDBConnectionString: string; +export let cosmosDBMongoConnectionString: string; export let eventHubConnectionString: string; export let serviceBusConnectionString: string; export let sqlConnectionString: string; @@ -11,6 +12,7 @@ export let sqlTestConnectionString: string; export async function initializeConnectionStrings(): Promise { storageConnectionString = "UseDevelopmentStorage=true"; cosmosDBConnectionString = "AccountEndpoint=http://localhost:8081/;AccountKey=C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="; + cosmosDBMongoConnectionString = "mongodb://localhost:10255/?ssl=true&replicaSet=globaldb&retrywrites=false&maxIdleTimeMS=120000&appName=@localhost@"; serviceBusConnectionString = eventHubConnectionString = "Endpoint=sb://localhost;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"; sqlConnectionString = `Server=localhost,15433;Database=master;User Id=sa;Password=${process.env.SA_PASSWORD};Encrypt=false;TrustServerCertificate=true;`; sqlTestConnectionString = `Server=localhost,15433;Database=e2eTestDB;User Id=sa;Password=${process.env.SA_PASSWORD};Encrypt=false;TrustServerCertificate=true;`; diff --git a/src/utils/cosmosdbmongo/setupCosmosDBMongo.ts b/src/utils/cosmosdbmongo/setupCosmosDBMongo.ts new file mode 100644 index 0000000..f8c53d5 --- /dev/null +++ b/src/utils/cosmosdbmongo/setupCosmosDBMongo.ts @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. + +import { MongoClient } from 'mongodb'; +import { cosmosDBMongoConnectionString } from '../connectionStrings'; +import { CosmosDBMongo } from '../../constants'; + +export async function setupCosmosDBMongo() { + if (!cosmosDBMongoConnectionString) { + throw new Error('CosmosDB Mongo connection string is not set'); + } + const client = new MongoClient(cosmosDBMongoConnectionString); + await client.connect(); + const db = client.db(CosmosDBMongo.dbName); + const collections = await db.listCollections().toArray(); + const names = collections.map((c) => c.name); + if (!names.includes(CosmosDBMongo.triggerCollectionName)) { + await db.createCollection(CosmosDBMongo.triggerCollectionName); + } + if (!names.includes(CosmosDBMongo.triggerAndOutputCollectionName)) { + await db.createCollection(CosmosDBMongo.triggerAndOutputCollectionName); + } + await client.close(); +}