Blog Post

Educator Developer Blog
16 MIN READ

Getting Started with Azure Cosmos DB SDK for TypeScript/JavaScript (4.2.0)

kevin_comba's avatar
kevin_comba
Iron Contributor
Dec 03, 2024

In this blog, we will walk through how to get started with Azure Cosmos DB SDK for TypeScript. Using the SDK, we'll cover how to set up a Cosmos DB client, interact with containers and items, and perform basic CRUD operations such as creating, updating, querying, and deleting items. By the end of this tutorial, you'll have a solid understanding of how to integrate Azure Cosmos DB into your TypeScript applications.

What is an SDK?

An SDK (Software Development Kit) is a collection of software development tools, libraries, and documentation that helps developers integrate and interact with a service or platform. In this case, the Azure Cosmos DB SDK for JavaScript/TypeScript provides a set of tools to interact with the Cosmos DB service, making it easier to perform operations like database and container management, data insertion, querying, and more.

What is the Azure Cosmos DB Client Library for JavaScript/TypeScript?

The Azure Cosmos DB Client Library for JavaScript/TypeScript is a package that allows developers to interact with Azure Cosmos DB through an easy-to-use API. It supports operations for creating databases, containers, and documents, as well as querying and updating documents.

For our example, we will be using the SQL API, which is the most widely used API in Cosmos DB, and will show how to use the SDK for basic CRUD operations.

To get started, make sure to install the SDK by running:

npm i @azure/cosmos

Prerequisites

Before we can start interacting with Cosmos DB, we need to make sure we have the following prerequisites in place:

1. Azure Subscription

You need an active Azure subscription. If you don’t have one, you can Sign up for a free Azure account, or Azure for students to get $100 azure credit.

2. Azure Cosmos DB Account

To interact with Cosmos DB, you need to have a Azure Cosmos DB API account. Create one from the Azure Portal and keep the Endpoint URL and Primary Key handy. If you dont know how to do so check out this blog Getting started with Azure Cosmos Database (A Deep Dive)

Overview of Cosmos Client Concepts

Before diving into code, let's briefly go over the essential concepts you will interact with in Azure Cosmos DB.

1. Database

A Database is a container for data in Cosmos DB. You can think of it as a high-level entity under which collections (containers) are stored.

client.databases("<db id>") for creating new databases, and reading/querying all databases

2. Container

A Container (formerly known as a collection) is a logical unit for storing items (documents). In Cosmos DB, each container is independent, and the items within a container are stored as JSON-like documents.

Operations for reading, replacing, or deleting a specific, existing container by id. For creating new containers and reading/querying all containers; use .containers() ie .container(id).read()

3. Partition Key

A Partition Key is used to distribute data across multiple physical partitions. When you insert data into a container, you must define a partition key. This helps Cosmos DB scale and optimize read and write operations.

4. Item

An Item in Cosmos DB is a single piece of data that resides in a container. It is typically stored as a JSON document, and each item must have a unique ID and be associated with a partition key.

Used to perform operations on a specific item. 

  • read method
const { resource,statusCode } = await usersContainer.item(id, id).read<TUser>();
  • delete method
const { statusCode } = await usersContainer.item(id, id).delete()

5. Items

Items in Cosmos DB is used for Operations for creating new items and reading/querying all items.

Used to perform operations on a many items. 

  • query method
const { resources } = await usersContainer.items.query(querySpec).fetchAll();

 

  • read all items method
const { resources} = await usersContainer.items.readAll<TUser[]>().fetchAll();

 

  • upsert (update or insert if item doesn't exist)
const { resource } = await usersContainer.items.upsert<Partial<TUser>>(user);

Environment Variables Setup

  • Create a .env file in the root directory of your project with the following contents:
NODE_ENV=DEVELOPMENT AZURE_COSMOS_DB_ENDPOINT=https://<your-cosmos-db-account>.documents.azure.com:443 AZURE_COSMOS_DB_KEY=<your-primary-key> AZURE_COSMOS_DB_DATABASE_NAME=<your-database-name>

Let's set up a simple node app

  • Initialize the Project

Create a new directory for your project and navigate into it:

mkdir simple-node-app cd simple-node-app

Initialize a new Node.js project with default settings:

npm init -y

 

  • Install Dependencies

Install the necessary dependencies for Express, TypeScript, and other tools:

npm install @azure/cosmos zod uuid dotenv 
npm install --save-dev typescript rimraf tsx @types/node
  • Configure TypeScript

Create a tsconfig.json file in the root of your project with the following content:

{
  "compilerOptions": {
    /* Base Options: */
    "target": "es2022",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "moduleResolution": "nodenext",
    "resolveJsonModule": true,
    /* Strictness */
    "strict": true,
    "allowUnreachableCode": false,
    "noUnusedLocals": true,
    // "noUnusedParameters": true,
    "strictBindCallApply": true,
    /* If transpiling with TypeScript: */
    "module": "NodeNext",
    "outDir": "dist",
    "rootDir": "./",
    "lib": [
      "ES2022"
    ],
  },
  "include": [
    "./*.ts"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

Loading Environment Variables

Create env.ts to securely and type safe load our env variables using zod add below code

//./env.ts
import dotenv from 'dotenv';
import { z } from 'zod';

// Load environment variables from .env file
dotenv.config();

// Define the environment schema
const EnvSchema = z.object({
    // Node Server Configuration
    NODE_ENV: z.enum(['PRODUCTION', 'DEVELOPMENT']).default('DEVELOPMENT'),

    // CosmosDB Configuration
    AZURE_COSMOS_DB_ENDPOINT: z.string({
        required_error: "AZURE_COSMOS_DB_ENDPOINT is required",
        invalid_type_error: "AZURE_COSMOS_DB_ENDPOINT must be a string",
    }),
    AZURE_COSMOS_DB_KEY: z.string({
        required_error: "AZURE_COSMOS_DB_KEY is required",
        invalid_type_error: "AZURE_COSMOS_DB_KEY must be a string",
    }),
    AZURE_COSMOS_DB_DATABASE_NAME: z.string({
        required_error: "AZURE_COSMOS_DB DB Name is required",
        invalid_type_error: "AZURE_COSMOS_DB must be a string",
    }),    
});

// Parse and validate the environment variables
export const env = EnvSchema.parse(process.env);

// Configuration object consolidating all settings
const config = {
    nodeEnv: env.NODE_ENV,
    cosmos: {
        endpoint: env.AZURE_COSMOS_DB_ENDPOINT,
        key: env.AZURE_COSMOS_DB_KEY,
        database: env.AZURE_COSMOS_DB_DATABASE_NAME,
        containers: {
            users: 'usersContainer',
        },
    },
    
};

export default config;

Securely Setting Up Cosmos Client Instance

To interact with Cosmos DB, we need to securely set up a CosmosClient instance. Here's how to initialize the client using environment variables for security.

Create cosmosClient.ts and add below code 

 

// ./cosmosdb.config.ts
import { PartitionKeyDefinitionVersion, PartitionKeyKind, Database, CosmosClient, Container, CosmosDbDiagnosticLevel, ErrorResponse, RestError, AbortError, TimeoutError } from '@azure/cosmos';

import config from './env';

let client: CosmosClient;
let database: Database;
let usersContainer: Container;

async function initializeCosmosDB(): Promise<void> {
  try {

    // Create a new CosmosClient instance
    client = new CosmosClient({
      endpoint: config.cosmos.endpoint,
      key: config.cosmos.key,
      diagnosticLevel: config.nodeEnv === 'PRODUCTION' ? CosmosDbDiagnosticLevel.info : CosmosDbDiagnosticLevel.debug
    });

    // Create or get the database
    const { database: db } = await client.databases.createIfNotExists({ id: config.cosmos.database });
    database = db;

    console.log(`Database '${config.cosmos.database}' initialized.`);

    // Initialize containers
    usersContainer = await createUsersContainer();

    console.log('Cosmos DB initialized successfully.');
  } catch (error: any) {
    return handleCosmosError(error);
  }
}
// Create the users container
async function createUsersContainer(): Promise<Container> {
  const containerDefinition = {
    id: config.cosmos.containers.users,
    partitionKey: {
      paths: ['/id'],
      version: PartitionKeyDefinitionVersion.V2,
      kind: PartitionKeyKind.Hash,
    },
  };

  try {
    const { container } = await database.containers.createIfNotExists(containerDefinition);
    console.log(`'${container.id}' is ready.`);
    // const { container, diagnostics } = await database.containers.createIfNotExists(containerDefinition);
    // console.log(diagnostics.clientConfig) Contains aggregates diagnostic details for the client configuration
    // console.log(diagnostics.diagnosticNode)  is intended for debugging non-production environments only
    return container;
  } catch (error: any) {
    return handleCosmosError(error);
  }
}

// Getter functions for containers
function getUsersContainer(): Container {
  if (!usersContainer) {
    throw new Error('user container is not initialized.');
  }
  return usersContainer;
}

const handleCosmosError = (error: any) => {
  if (error instanceof RestError) {
    throw new Error(`error: ${error.name},  message: ${error.message}`);
  } else if (error instanceof ErrorResponse) {
    throw new Error(`Error: ${error.message}, message: ${error.message}`);
  } else if (error instanceof AbortError) {
    throw new Error(error.message);
  } else if (error instanceof TimeoutError) {
    throw new Error(`TimeoutError code: ${error.code}, message: ${error.message}`);
  } else if (error.code === 409) {
    //if you try to create an item using an id that's already in use in your Cosmos DB database, a 409 error is returned
    throw new Error('Conflict occurred while creating an item using an existing ID.');
  } else {
    console.log(JSON.stringify(error));
    throw new Error('An error occurred while processing your request.');
  }
};

export { initializeCosmosDB, getUsersContainer, handleCosmosError };

 

This code is for initializing and interacting with Azure Cosmos DB using the Azure Cosmos SDK in a Node.js environment. Here's a brief and straightforward explanation of what each part does:

Imports:

  • The code imports several classes and enums from azure/cosmos that are needed to interact with Cosmos DB, like CosmosClient, Database, Container, and various error types.

Variables:

  • client, database, and usersContainer are declared to hold references to the Cosmos DB client, database, and a specific container for user data.

initializeCosmosDB() function:

  • Purpose: Initializes the Cosmos DB client, database, and container.
  • Steps:
    1. Creates a new CosmosClient with credentials from the config (like endpoint, key, and diagnosticLevel).
    2. Attempts to create or retrieve a database (using createIfNotExists).
    3. Logs success and proceeds to initialize the usersContainer by calling createUsersContainer().

createUsersContainer() function:

  • Purpose: Creates a container for storing user data in Cosmos DB with a partition key.
  • Steps:
    1. Defines a partition key for the container (using /id as the partition key path).
    2. Attempts to create the container (or retrieves it if it already exists) with the given definition.
    3. Returns the container instance.

getUsersContainer() function:

  • Purpose: Returns the usersContainer object if it exists.
  • Throws an error if the container is not initialized.

handleCosmosError() function:

  • Purpose: Handles errors thrown by Cosmos DB operations.
  • Error Handling:
    • It checks the type of error (e.g., RestError, ErrorResponse, AbortError, TimeoutError) and throws a formatted error message.
    • Specifically handles conflict errors (HTTP 409) when attempting to create an item with an existing ID.

Key Exported Functions:

  • initializeCosmosDB: Initializes the Cosmos DB client and container.
  • getUsersContainer: Returns the initialized users container.
  • handleCosmosError: Custom error handler for Cosmos DB operations.

Create User Schema

This code defines data validation schemas using Zod, a TypeScript-first schema declaration and validation library. Create user.schema.ts and add below code

// ./user.schema.ts
import { z } from 'zod';

const coerceDate = z.preprocess((arg) => {
    if (typeof arg === 'string' || arg instanceof Date) {
        return new Date(arg);
    } else {
        return arg;
    }
}, z.date());

export const userSchema = z.object({
    id: z.string().uuid(),
    fullname: z.string(),
    email: z.string().email(),
    address: z.string(),
    createdAt: coerceDate.default(() => new Date()),
})

const responseSchema = z.object({
    statusCode: z.number(),
    message: z.string(),
})

export type TResponse = z.infer<typeof responseSchema>;
export type TUser = z.infer<typeof userSchema>;

 

Here's a concise breakdown of the code:

1. coerceDate Schema:

  • Purpose: This schema is designed to coerce a value into a Date object.
  • How it works:
    • z.preprocess() allows preprocessing of input before applying the base schema (z.date()).
    • If the input is a string or an instance of Date, it converts it into a Date object.
    • If the input is neither of these, it returns the original input without modification.
  • Use: The coerceDate is used later in the userSchema to ensure that the createdAt field is always a valid Date object.

2. userSchema:

  • Purpose: Defines the structure and validation rules for a user object.
  • Fields:
    • id: A required string that must be a valid UUID (z.string().uuid()).
    • fullname: A required string.
    • email: A required string that must be a valid email format (z.string().email()).
    • address: A required string.
    • createdAt: A Date field, which defaults to the current date/time if not provided (z.date() with default(() => new Date())), and uses coerceDate for preprocessing to ensure the value is a valid Date object.

3. responseSchema:

  • Purpose: Defines the structure of a response object.
  • Fields:
    • statusCode: A required number (z.number()).
    • message: A required string.

4. Type Inference:

  • TResponse and TUser are TypeScript types that are automatically inferred from the responseSchema and userSchema, respectively.
  • z.infer<typeof schema> generates TypeScript types based on the Zod schema, so:
    • TResponse will be inferred as { statusCode: number, message: string }.
    • TUser will be inferred as { id: string, fullname: string, email: string, address: string, createdAt: Date }.

Let's implement Create Read Delete and Update

Create user.service.ts and add the code below

// ./user.service.ts

import { SqlQuerySpec } from '@azure/cosmos';
import { getUsersContainer, handleCosmosError } from './cosmosClient';
import { TResponse, TUser } from './user.schema';
// Save user service
export const saveUserService = async (user: TUser): Promise<Partial<TUser>> => {
    try {
        const usersContainer = getUsersContainer();
        const res = await usersContainer.items.create<TUser>(user);
        if (!res.resource) {
            throw new Error('Failed to save user.');
        }
        return res.resource;
    } catch (error: any) {
        return handleCosmosError(error);
    }
};
// Update user service
export const updateUserService = async (user: Partial<TUser>): Promise<Partial<TUser>> => {
    try {
        const usersContainer = getUsersContainer();
        const { resource } = await usersContainer.items.upsert<Partial<TUser>>(user);
        if (!resource) {
            throw new Error('Failed to update user.');
        }
        return resource;
    } catch (error: any) {
        return handleCosmosError(error);
    }
};
// Fetch users service
export const fetchUsersService = async (): Promise<TUser[] | null> => {
    try {

        const usersContainer = getUsersContainer();

        const querySpec: SqlQuerySpec = {
            query: 'SELECT * FROM c ORDER BY c._ts DESC',
        };
        const { resources } = await usersContainer.items.query<TUser[]>(querySpec).fetchAll();
        return resources.flat();
    } catch (error: any) {
        return handleCosmosError(error);
    }
};
// Fetch user by email service
export const fetchUserByEmailService = async (email: string): Promise<TUser | null> => {
    try {
        const usersContainer = getUsersContainer();
        const querySpec: SqlQuerySpec = {
            query: 'SELECT * FROM c WHERE c.email = ',
            parameters: [
                { name: '@email', value: email },
            ],
        };
        const { resources } = await usersContainer.items.query<TUser>(querySpec).fetchAll();
        return resources.length > 0 ? resources[0] : null;
    } catch (error: any) {
        return handleCosmosError(error);
    }
}
// Fetch user by ID service
export const fetchUserByIdService = async (id: string): Promise<TUser | null> => {
    try {
        const usersContainer = getUsersContainer();
        const { resource } = await usersContainer.item(id, id).read<TUser>();
        if (!resource) {
            return null;
        }
        return resource;
    } catch (error: any) {
        return handleCosmosError(error);
    }
};
// Delete user by ID service
export const deleteUserByIdService = async (id: string): Promise<TResponse> => {
    try {
        const usersContainer = getUsersContainer();
        const userIsAvailable = fetchUserByIdService(id);
        if (!userIsAvailable) {
            throw new Error('User not found');
        }
        const { statusCode } = await usersContainer.item(id, id).delete();

        if (statusCode !== 204) {
            throw new Error('Failed to delete user.');
        }
        return {
            statusCode,
            message: 'User deleted successfully',
        }
    } catch (error: any) {
        return handleCosmosError(error);
    }
};

 

This code provides a set of service functions to interact with the Cosmos DB container for managing user data, including create, update, fetch, and delete operations. Here's a brief breakdown of each function:

1. saveUserService:

  • Purpose: Saves a new user to the Cosmos DB container.
  • How it works:
    1. Retrieves the usersContainer using getUsersContainer().
    2. Uses items.create<TUser>(user) to create a new user document in the container.
    3. If the operation fails (i.e., no resource is returned), it throws an error.
    4. Returns the saved user object (with partial properties).
  • Error Handling: Catches any error and passes it to handleCosmosError().

2. updateUserService:

  • Purpose: Updates an existing user in the Cosmos DB container.
  • How it works:
    1. Retrieves the usersContainer.
    2. Uses items.upsert<Partial<TUser>>(user) to either insert or update the user data.
    3. If no resource is returned, an error is thrown.
    4. Returns the updated user object.
  • Error Handling: Catches any error and passes it to handleCosmosError().

3. fetchUsersService:

  • Purpose: Fetches all users from the Cosmos DB container.
  • How it works:
    1. Retrieves the usersContainer.
    2. Executes a SQL query (SELECT * FROM c ORDER BY c._ts DESC) to fetch all users ordered by timestamp (_ts).
    3. If the query is successful, it returns the list of users.
    4. If an error occurs, it is passed to handleCosmosError().
  • Return Type: Returns an array of TUser[] or null if no users are found.

4. fetchUserByEmailService:

  • Purpose: Fetches a user by their email address.
  • How it works:
    1. Retrieves the usersContainer.
    2. Executes a SQL query to search for a user by email (SELECT * FROM c WHERE c.email = Email).
    3. If the query finds a matching user, it returns the user object, otherwise returns null.
  • Error Handling: Catches any error and passes it to handleCosmosError().

5. fetchUserByIdService:

  • Purpose: Fetches a user by their unique id.
  • How it works:
    1. Retrieves the usersContainer.
    2. Uses item(id, id).read<TUser>() to read a user by its id.
    3. If no user is found, returns null.
    4. If the user is found, returns the user object.
  • Error Handling: Catches any error and passes it to handleCosmosError().

6. deleteUserByIdService:

  • Purpose: Deletes a user by their unique id.
  • How it works:
    1. Retrieves the usersContainer.
    2. Checks if the user exists by calling fetchUserByIdService(id).
    3. If the user is not found, throws an error.
    4. Deletes the user using item(id, id).delete().
    5. Returns a response object with statusCode and a success message if the deletion is successful.
  • Error Handling: Catches any error and passes it to handleCosmosError().

Summary of the Service Functions:

  • Save a new user (saveUserService).
  • Update an existing user (updateUserService).
  • Fetch all users (fetchUsersService), a user by email (fetchUserByEmailService), or by id (fetchUserByIdService).
  • Delete a user by id (deleteUserByIdService).

Key Points:

  • Upsert operation (upsert): If the user exists, it is updated; if not, it is created.
  • Error Handling: All errors are passed to a centralized handleCosmosError() function, which ensures consistent error responses.
  • Querying: Uses SQL-like queries in Cosmos DB to fetch users based on conditions (e.g., email or id).
  • Type Safety: The services rely on the TUser and TResponse types from the schema, ensuring that the input and output adhere to the expected structure.

This structure makes the service functions reusable and maintainable, while providing clean, type-safe interactions with the Azure Cosmos DB.

Let's Create Server.ts 

Create server.ts and add the code below.

//./server.ts
import { initializeCosmosDB } from "./cosmosClient";
import { v4 as uuidv4 } from 'uuid';
import { TUser } from "./user.schema";
import { fetchUsersService, fetchUserByIdService, deleteUserByIdService, saveUserService, updateUserService, fetchUserByEmailService } from "./user.service";

// Start server
(async () => {
    try {
        // Initialize CosmosDB
        await initializeCosmosDB();

        // Create a new user
        const newUser: TUser = {
            id: uuidv4(),
            fullname: "John Doe",
            email: "john.doe@example.com",
            address: "Nairobi, Kenya",
            createdAt: new Date()
        };

        const createdUser = await saveUserService(newUser);
        console.log('User created:', createdUser);

        // Fetch all users
        const users = await fetchUsersService();
        console.log('Fetched users:', users);

        let userID = "81b4c47c-f222-487b-a5a1-805463c565a0";

        // Fetch user by ID
        const user = await fetchUserByIdService(userID);
        console.log('Fetched user with ID:', user);

        //search for user by email
        const userByEmail = await fetchUserByEmailService("john.doe@example.com");
        console.log('Fetched user with email:', userByEmail);

        // Update user
        const updatedUser = await updateUserService({ id: userID, fullname: "Jonathan Doe" });
        console.log('User updated:', updatedUser);

        // Delete user
        const deleteResponse = await deleteUserByIdService(userID);
        console.log('Delete response:', deleteResponse);

    } catch (error: any) {
        console.error('Error:', error.message);
    } finally {
        process.exit(0);
    }
})();

 

This server.ts file is the entry point of an application that interacts with Azure Cosmos DB to manage user data. It initializes the Cosmos DB connection and performs various CRUD operations (Create, Read, Update, Delete) on user records.

Breakdown of the Code:

1. Imports:

  • initializeCosmosDB: Initializes the Cosmos DB connection and sets up the database and container.
  • uuidv4: Generates a unique identifier (UUID) for the id field of the user object.
  • TUser: Type definition for a user, ensuring that the user object follows the correct structure (from user.schema.ts).
  • Service Functions: These are the CRUD operations that interact with the Cosmos DB (fetchUsersService, fetchUserByIdService, etc.).

2. Asynchronous IIFE (Immediately Invoked Function Expression):

  • The entire script runs inside an async IIFE, which is an asynchronous function that executes immediately when the file is run.

3. Workflow:

Here’s what the script does step-by-step:

  1. Initialize Cosmos DB:
    • The initializeCosmosDB() function is called to set up the connection to Cosmos DB. If the connection is successful, it logs Cosmos DB initialized. to the console.
  2. Create a New User:
    • A new user is created with a unique ID (uuidv4()), full name, email, address, and a createdAt timestamp.
    • The saveUserService(newUser) function is called to save the new user to the Cosmos DB container.
    • If successful, the created user is logged to the console.
  3. Fetch All Users:
    • The fetchUsersService() function is called to fetch all users from the Cosmos DB.
    • The list of users is logged to the console.
  4. Fetch User by ID:
    • The fetchUserByIdService(userID) function is called with a hardcoded userID to fetch a specific user by their unique ID.
    • The user (if found) is logged to the console.
  5. Fetch User by Email:
    • The fetchUserByEmailService(email) function is called to find a user by their email address ("john.doe@example.com").
    • The user (if found) is logged to the console.
  6. Update User:
    • The updateUserService({ id: userID, fullname: "Jonathan Doe" }) function is called to update the user's full name.
    • The updated user is logged to the console.
  7. Delete User:
    • The deleteUserByIdService(userID) function is called to delete the user with the specified ID.
    • The response from the deletion (status code and message) is logged to the console.

4. Error Handling:

  • If any operation fails, the catch block catches the error and logs the error message to the console. This ensures that any issues (e.g., database connection failure, user not found, etc.) are reported.

5. Exit Process:

  • After all operations are completed (or if an error occurs), the script exits the process with process.exit(0) to ensure the Node.js process terminates cleanly.

Example Output:

If everything runs successfully, the console output would look like this (assuming the hardcoded userID exists in the database and the operations succeed):

Cosmos DB initialized.
User created: { id: 'some-uuid', fullname: 'John Doe', email: 'john.doe@example.com', address: 'Nairobi, Kenya', createdAt: 2024-11-28T12:34:56.789Z } 
Fetched users: [{ id: 'some-uuid', fullname: 'John Doe', email: 'john.doe@example.com', address: 'Nairobi, Kenya', createdAt: 2024-11-28T12:34:56.789Z }] 
Fetched user with ID: { id: '81b4c47c-f222-487b-a5a1-805463c565a0', fullname: 'John Doe', email: 'john.doe@example.com', address: 'Nairobi, Kenya', createdAt: 2024-11-28T12:34:56.789Z } 
Fetched user with email: { id: 'some-uuid', fullname: 'John Doe', email: 'john.doe@example.com', address: 'Nairobi, Kenya', createdAt: 2024-11-28T12:34:56.789Z } User updated: { id: '81b4c47c-f222-487b-a5a1-805463c565a0', fullname: 'Jonathan Doe', email: 'john.doe@example.com', address: 'Nairobi, Kenya', createdAt: 2024-11-28T12:34:56.789Z } 
Delete response: { statusCode: 204, message: 'User deleted successfully' }

 

Error Handling

The SDK generates various types of errors that can occur during an operation.

  1. ErrorResponse is thrown if the response of an operation returns an error code of >=400.
  2. TimeoutError is thrown if Abort is called internally due to timeout.
  3. AbortError is thrown if any user passed signal caused the abort.
  4. RestError is thrown in case of failure of underlying system call due to network issues.
  5. Errors generated by any devDependencies. For Eg. azure/identity package could throw CredentialUnavailableError.

Following is an example for handling errors of type ErrorResponse, TimeoutError, AbortError, and RestError.

import { ErrorResponse, RestError, AbortError, TimeoutError } from '@azure/cosmos'; 

const handleCosmosError = (error: any) => {
  if (error instanceof RestError) {
    throw new Error(`error: ${error.name},  message: ${error.message}`);
  } else if (error instanceof ErrorResponse) {
    throw new Error(`Error: ${error.message}, message: ${error.message}`);
  } else if (error instanceof AbortError) {
    throw new Error(error.message);
  } else if (error instanceof TimeoutError) {
    throw new Error(`TimeoutError code: ${error.code}, message: ${error.message}`);
  } else if (error.code === 409) {
    //if you try to create an item using an id that's already in use in your Cosmos DB database, a 409 error is returned
    throw new Error('Conflict occurred while creating an item using an existing ID.');
  } else {
    console.log(JSON.stringify(error));
    throw new Error('An error occurred while processing your request.');
  }
};


Read More

  1.  Quickstart Guide for Azure Cosmos DB Javascript SDK v4
  2. Best practices for JavaScript SDK in Azure Cosmos DB for NoSQL
  3. Visit the JavaScript SDK v4 Release Notes page for the rest of our documentation and sample code.
  4. Announcing JavaScript SDK v4 for Azure Cosmos DB
Updated Nov 28, 2024
Version 1.0
No CommentsBe the first to comment