Skip to content

Instantly share code, notes, and snippets.

@jdhenckel
Created August 29, 2022 18:45
Show Gist options
  • Save jdhenckel/b415cdfa226bf710338d3744f14a0458 to your computer and use it in GitHub Desktop.
Save jdhenckel/b415cdfa226bf710338d3744f14a0458 to your computer and use it in GitHub Desktop.
A convenience class for Javascript to read documents from CosmosDB
//=====================
// Service functions for accessing the CosmosDB from the Madras-WDC
//==================
"use strict";
import { CosmosClient } from "@azure/cosmos";
function parseConnectionString(connection_string) {
let result = {};
for (let m of connection_string.matchAll(/(\w+)=(.*?);/g))
result[m[1]] = m[2];
return result;
}
function getReasonFromException(ex) {
// Returns the Cosmos exception as a concise string
let reason = '';
if (!ex) return ', null';
if ('body' in ex && 'code' in ex.body) reason += ', ' + ex.body.code;
if ('code' in ex) reason += ', ' + ex.code;
if ('message' in ex) reason += ', ' + ex.message.substr(0,60);
if (!reason) reason = ex.constructor.name;
return reason;
}
class MadrasClient {
//-----------------------------------------------------------------------
// This is a convenience wrapper for the CosmosClient. Sample code:
//
// myclient = new MadrasClient(connection_string);
// for async (let doc of myclient.query(dbname, container_name, sql_string)) {
// console.log(doc)
// }
constructor(connection_string) {
let cs = parseConnectionString(connection_string);
this.client = new CosmosClient({ endpoint: cs.AccountEndpoint, key: cs.AccountKey });
}
async getDatabase(dbname) {
try {
let res = await this.client.database(dbname).read();
return res.database;
} catch (ex) {
throw new Error('Failed to open ' + dbname + getReasonFromException(ex));
}
}
async getContainer(dbname, container_name) {
let database = await this.getDatabase(dbname);
try {
let res = await database.container(container_name).read();
return res.container;
} catch (ex) {
throw new Error('Failed to open ' + container_name + getReasonFromException(ex));
}
}
async getItems(dbname, container_name) {
let container = await this.getContainer(dbname, container_name);
return container.items;
}
async* query(dbname, container_name, sql_query) {
// Returns a generator to fetch one document at a time asynchronousely,
// see sample code above. sql_query is optional, default returns ALL
let items = await this.getItems(dbname, container_name);
let queryIterator = sql_query ? items.query(sql_query) : items.readAll();
for (;;) {
let feedResponse = await queryIterator.fetchNext();
for (let doc of feedResponse.resources)
yield doc;
if (!feedResponse.hasMoreResults)
break;
}
}
}
//-----------------------------------------------------------------
// Expose public stuff in the global namespace
global.MadrasClient = MadrasClient;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment