I am working with Node 18 TypeScript azure functions and developing with VSCode. I am using the @azure/cosmos
SDK to intreract with CosmosDB. I create an instance inside the functions by first creating this module:
collection.ts
import { Container, CosmosClient } from "@azure/cosmos";
const endpoint = process.env.COSMOS_DB_ENDPOINT;
const key = process.env.COSMOS_DB_KEY;
const database = process.env.COSMOS_DB_DATABASE;
const container = process.env.COSMOS_DB_COLLECTION;
export default () => {
const client = new CosmosClient({ endpoint, key });
return client.database(database).container(container);
};
Importing/Instantiating like so:
index.ts
(some function)
import client from "collection.ts";
const collection = client();
export default async (context, req) => {...}
After some testing, I found that it fails on collection.ts:10
where I actually create the client instance (const client = new CosmosClient({ endpoint, key });
). The problem is this all works in development before I deploy. I'm calling this is an internal error because I catch exceptions in the function and return an error object, but when I call a function that uses this SDK, it's not present.
I figured there was some kind of disconnect in the environments, so I added the endpoint/key/database/container env vars in the portal, and locally "Download Remote Settings..." with the vscode extention (env vars are in the Application Settings under Configuration in the portal). I have even tried hard coding strings with the correct endpoint/key instead of using process.env
.
I have also tried looking at the log stream and it isn't much help:
2023-09-06T08:57:57Z [Error] Executed 'Functions.LoginUser' (Failed, Id=6c7dc7c5-a942-4b93-89d8-a354e1d6a868, Duration=2ms)
I'm not sure what else to try. I can provide more info if requested. Any ideas would be appreciated!
I have got the expected result in the following way both in local and in portal
Created a HTTP Trigger function and then trying to invoke collection.ts
file inside it. You can use Timer trigger function as well.
collection.ts
import { Container, CosmosClient } from "@azure/cosmos";
const endpoint = process.env.COSMOS_DB_ENDPOINT;
const key = process.env.COSMOS_DB_KEY;
const database = process.env.COSMOS_DB_DATABASE;
const container = process.env.COSMOS_DB_COLLECTION;
export default () => {
const client = new CosmosClient({ endpoint, key });
return client.database(database).container(container);
};
httpTrigger.ts
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
import client from "./collection";
const collection = client();
export default async function httpTrigger1(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
context.log(`Cosmos DB data:`,collection);
context.log(`Http function processed request for url "${request.url}"`);
const name = request.query.get('name') || await request.text() || 'world';
return { body: `Hello, ${name}!` };
};
app.http('httpTrigger1', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: httpTrigger1
});
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
"COSMOS_DB_ENDPOINT": "<Enter Cosmos DB endpoint here>",
"COSMOS_DB_KEY": "<Enter Cosmos DB Key here>",
"COSMOS_DB_DATABASE": "<Cosmos DB Database Name>",
"COSMOS_DB_COLLECTION": "<Cosmos DB Container Name>"
}
}
Local Output:
After deployment, I have added the credentials in Function App's App Settings.
I triggered the function and got the expected Output.