Created
January 15, 2025 08:23
-
-
Save antimatter15/ff88089a39c329624d4eb1ae7f358735 to your computer and use it in GitHub Desktop.
Minimal NodeJS/Typescript Implementation of Azure CosmosDB REST API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const COSMOS_ENDPOINT = 'https://cosmos-demo.documents.azure.com' | |
async function cosmosFetch( | |
method: 'GET' | 'POST' | 'PUT' | 'PATCH', | |
path: string, | |
headers?: any, | |
body?: any | |
) { | |
const dateUtc = new Date().toUTCString() | |
const parts = path.match( | |
/(.*\/)?(dbs|colls|sprocs|udfs|triggers|users|permissions|docs)(\/.*)?$/ | |
) | |
const resourceType = parts[2] | |
const resourceId = parts[3] | |
? (parts[1] || '') + parts[2] + (parts[3] || '') | |
: (parts[1] || '').slice(0, -1) | |
const stringToSign = `${method.toLowerCase()}\n${resourceType.toLowerCase()}\n${resourceId}\n${dateUtc.toLowerCase()}\n\n` | |
const hmac = await crypto.subtle.importKey( | |
'raw', | |
Buffer.from(process.env.AZURE_COSMOS_KEY, 'base64'), | |
{ name: 'HMAC', hash: 'SHA-256' }, | |
false, | |
['sign'] | |
) | |
const signature = await crypto.subtle.sign('HMAC', hmac, new TextEncoder().encode(stringToSign)) | |
const response = await fetch(`${COSMOS_ENDPOINT}/${path}`, { | |
method, | |
headers: { | |
Authorization: encodeURIComponent( | |
`type=master&ver=1.0&sig=${Buffer.from(signature).toString('base64')}` | |
), | |
'x-ms-version': '2020-07-15', | |
'x-ms-date': dateUtc, | |
Accept: 'application/json', | |
...(headers || {}), | |
}, | |
body: JSON.stringify(body), | |
}) | |
let data | |
try { | |
data = await response.json() | |
} catch (err) {} | |
if (!response.ok) | |
throw new Error(`CosmosDB Error ${response.status}: ${data?.message?.split('\n')[0]}`) | |
return data | |
} | |
async function main() { | |
console.log(await cosmosFetch('GET', 'dbs')) | |
console.log(await cosmosFetch('GET', 'dbs/Test')) | |
console.log(await cosmosFetch('GET', 'dbs/Test/colls')) | |
console.log(await cosmosFetch('GET', 'dbs/Test/colls/test')) | |
console.log(await cosmosFetch('GET', 'dbs/Test/colls/test/docs')) | |
console.log( | |
await cosmosFetch( | |
'POST', | |
'dbs/Test/colls/test/docs', | |
{ | |
'x-ms-documentdb-isquery': 'True', | |
'x-ms-documentdb-query-enablecrosspartition': 'True', | |
'Content-Type': 'application/query+json', | |
}, | |
{ | |
query: 'SELECT c.id FROM c', | |
} | |
) | |
) | |
console.log( | |
await cosmosFetch('GET', 'dbs/Test/colls/test/docs/wumbology3', { | |
'x-ms-documentdb-partitionkey': '["wumbology3"]', | |
}) | |
) | |
console.log( | |
await cosmosFetch( | |
'PATCH', | |
'dbs/Test/colls/test/docs/wumbology3', | |
{ | |
'Content-Type': 'application/json', | |
'x-ms-documentdb-partitionkey': '["wumbology3"]', | |
}, | |
{ | |
operations: [ | |
{ | |
op: 'set', | |
path: '/FamilyName', | |
value: 'Bob', | |
}, | |
], | |
} | |
) | |
) | |
console.log(await cosmosFetch('GET', 'dbs/Test/colls/test/sprocs')) | |
console.log(await cosmosFetch('GET', 'dbs/Test/colls/test/triggers')) | |
console.log( | |
await cosmosFetch( | |
'POST', | |
'dbs/Test/colls/test/docs', | |
{ | |
'x-ms-documentdb-isquery': 'True', | |
'x-ms-documentdb-query-enablecrosspartition': 'True', | |
// 'x-ms-documentdb-populatequerymetrics': 'True', | |
'Content-Type': 'application/query+json', | |
}, | |
{ | |
query: 'SELECT c.id FROM c', | |
} | |
) | |
) | |
console.log(await cosmosFetch('GET', 'dbs/Test/users')) | |
} | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment