Azure Cosmos DB (DocumentDB SQL API) TypeScript interface
This Node.js module provides a TypeScript-based wrapper around the Node.js APIs for Microsoft's awesome SQL-queried schema-free NoSQL database in the Azure cloud, DocumentDB Cosmos DB.
Refer to the DocumentDB API documentation here: https://docs.microsoft.com/en-us/azure/documentdb/documentdb-sdk-node
No TypeScript required — you can use this module with plain JavaScript too (ES3, ES5, or ES6 aka ES2015, ES7 and whatever comes after), and enjoy enhanced Intellisense in an editor that supports TypeScript 2 definition files, such as VS Code.
NOTE: The author of this module is not affiliated with Microsoft, Azure, or Cosmos DB / Document DB.
Goals
This module was written with the following goals in mind:
- Streamline common DocumentDB use cases;
- Enable a better developer experience with accurate Intellisense;
- Reduce clutter by grouping methods into classes and combining some of their functionality;
- Use idiomatic TypeScript 2 (es6 for Node JS) internally and externally;
- Enable asynchronous programming with
async/await
and/or Promises (native Node JS).
Change Log
v1.0.7
- Update: CosmosDB Node.js API v1.14, with Session consistency, DisableSSLVerification and ProxyURL options.
- Fixed several typing issues that occur with newer TypeScript compilers.
v1.0.6:
- Fixed an issue with the asyncIterator polyfill
v1.0.5:
- Update: DocumentDB Node.js API v1.12.0 for Cosmos DB, with support for RU/min billing and ConsistentPrefix consistency level.
v1.0.4:
- Minor bug fix
v1.0.3:
- New: Added support for Typescript 2.3's
for await (... of ...)
syntax (without breaking support for ES < 6 and TS < 2.3). See example below.
v1.0.0:
- Important: This version now requires TypeScript 2.1+.
- New: Added an
existsAsync
method toCollection
that uses aselect count(1) from c where...
query to determine more efficiently if any documents exist that match given ID or properties. - New: Added
path
properties toDatabase
andCollection
, which can be used with the underlying Node.js API (throughClient.documentClient
) if needed. - New: Most methods now accept an
options
parameter to forward feed and/or request options to the underlying Node.js API (e.g. forenableCrossPartitionQuery
). - Improved: Where possible, document IDs are now used to locate document resources instead of mandatory
_self
links. This allows for a new overload of thedeleteDocumentAsync
method that just takes an ID, and removes the need for a query infindDocumentAsync
if an ID is passed in (either as a property or as a single parameter). Also,storeDocumentAsync
withStoreMode.UpdateOnly
no longer requires a_self
property, anid
property will do. - Improved: More accurate types for objects passed to and/or returned from
Collection
methods. E.g. query results generated byqueryDocuments
no longer automatically include document properties such asid
and_self
, because queries may not actually return full documents anyway (or a document at all, e.g. forselect value...
queries). This is a breaking change since the TypeScript compiler may no longer find these properties on result objects, even forselect *
queries. ThefindDocumentAsync
andqueryDocuments
methods now accept a type parameter to specify a result type explicitly. - Changed: Getting
Client.documentClient
now throws an exception if the client connection has not been opened yet, or has been closed. UseisOpen()
to check if the connection is currently open. - Fixed: Operations are now queued properly in
DocumentStream
, e.g. calling.read()
twice in succession (synchronously) actually returns promises for two different results. - Fixed: Added
strictNullChecks
andnoImplicitAny
to the TypeScript configuration for compatibility with projects that have these options enabled. - Fixed: Added TypeScript as a development dependency to
package.json
.
Note:
At this point parts of the DocumentDB API feature set are still missing. If your app needs stored procedures, or users and permissions, for example, then please add to this code (preferably as new classes). Pull requests are greatly appreciated!
Tests are sorely needed as well. Perhaps some of the tests can be ported over from DocumentDB itself.
Installation
Use npm
to install this module:
npm install documentdb-typescript
Then import this module into your JavaScript or TypeScript code:
const DB = ;const client = /*...*/; // OR: ...;const client = /*...*/; // OR: ...;const client = /*...*/;
Usage
This module exports only the following symbols:
Client
class: contains methods for dealing with the connection toDocumentDBCosmos DB account.Database
class: represents a database.Collection
class: represents a collection, and contains methods for dealing with documents.DocumentStream
class: contains methods for reading query results (used as a return type only).StoreMode
enum: lists different modes of storing documents in a collection.
Where is Document? —
There is no 'Document' class because documents are really just plain JavaScript objects (of type any
), which may or may not have some extra properties (such as _self
) depending on where they come from, and are very hard to pin down as such. Also, the results of a query may or may not be full documents, which makes it impossible to predict exact return types. Adding another abstraction layer (à la the .NET API with its set- / getPropertyValue methods) doesn't seem like the right thing to do in JavaScript code.
Client
Start here if you need to work with multiple databases, or set advanced connection options.
// Example: open a connection and find all databases
The original DocumentClient from the documentdb
module is kept in the documentClient
property, after the openAsync
method is called:
A static property Client.concurrencyLimit
(number) controls how many requests may be outstanding globally at any time; this defaults to 25. Further requests are held internally (without timing out) until a pending request completes. You may want to increase this number if you are performing a high volume of low-cost operations such as deletions.
Database
Start here if you need to list all collections in a database, or delete it from the account. Nothing else here.
// Example: get a list of collections
Collection
This is where most of the functionality lives. Finding and/or creating a collection, optionally along with the database is easy:
// Example: create and delete a collection
The Collection
instance has methods for setting and getting provisioned throughput levels:
// Example: set and get throughput information
Storing documents
This module abstracts away most of the work involved in creating, updating, and upserting documents in a collection.
// Example: store and delete a document
Finding documents
There are a number of ways to find a document or a set of documents in a collection.
// Example: find document(s)
Iterating over query results
The queryDocuments
method on the Collection
class is one of the few methods that does not return a Promise. Instead, it returns a DocumentStream
instance which can be used to iterate over the results or load them all in one go.
The DocumentStream
class exposes a number of methods (e.g. forEach
and mapAsync
)
If you do not wish to use the Typescript/ES6 await
keyword, you can use the Promise
object returned by next
, read
, forEach
, or mapAsync
instead.
// Example: iterate over query results