azure-cosmos-ts
azure-cosmos-ts
Azure Cosmos DB JavaScript/TypeScript SDK (@azure/cosmos) for data plane operations. Use for CRUD operations on documents, queries, bulk operations, and container management. Triggers: "Cosmos DB", "@azure/cosmos", "CosmosClient", "document CRUD", "NoSQL queries", "bulk operations", "partition key", "container.items".
Introduction source: author · microsoft · 3f5b461b2314e01c400564051e92469114c5b68f Reference
Author's original introduction
Azure Cosmos DB JavaScript/TypeScript SDK (@azure/cosmos) for data plane operations. Use for CRUD operations on documents, queries, bulk operations, and container management. Triggers: "Cosmos DB", "@azure/cosmos", "CosmosClient", "document CRUD", "NoSQL queries", "bulk operations", "partition key", "container.items".
SkillPi interpretation
- Tasks
- azure-cosmos-ts
- Audience
- Use the scope in the original author introduction.
- Inputs and outputs
- See the complete source; users must confirm cloud data transfers.
- Software, accounts and paid services
- This azure-cosmos-ts package contains Microsoft Azure SDK documentation and examples, not a runtime-verified installer. Check SDK names/versions, tenant/subscription and actual endpoints; grant only task-specific least privilege. Never put administrator credentials or real secrets in samples, logs or commits. Connected cloud services may receive selected text, documents, audio, messages, logs or other input and incur charges; confirm scope, redaction and costs first. Ask the user to confirm each resource creation/update/deletion, key/access change or outbound message and test with disposable resources before production. Replace and verify placeholder endpoints and samples. SkillPi checked pinned source, complete attachments and static/antivirus evidence only; it did not run the SDK, verify service compatibility or authorize cloud access.
- Limits and differences
- Original author introduction preserved; Chinese is a corresponding translation. Examples were not run by SkillPi; versions, compatibility and outcomes are author claims.
- Testing
- Not tested
Permissions and checks before use
Automatically summarized from this main document. Matches may be examples or defensive advice; they are not actual permission declarations. Attachments, external dependencies and runtime behavior are not covered.
-
Install or fetch external dependencies
Use official sources and pin versions. Check install scripts in an isolated environment. This document check does not cover code downloaded later.
Mentioned in main document · lines 23, 480, 481, 482 -
Accounts, secrets or authorization
Use a dedicated least-privilege account. Keep secrets out of public content and command logs; verify the receiving service and tenant.
Mentioned in main document · lines 37, 42, 46, 48, 49
Domains or addresses referenced in the document
These addresses may be documentation links or examples, not an approved network allowlist. Verify actual destinations and outgoing data before use.
- learn.microsoft.com
Security rating and access scope
caution · Static evidence review; not a runtime safety guarantee.
This azure-cosmos-ts package contains Microsoft Azure SDK documentation and examples, not a runtime-verified installer. Check SDK names/versions, tenant/subscription and actual endpoints; grant only task-specific least privilege. Never put administrator credentials or real secrets in samples, logs or commits. Connected cloud services may receive selected text, documents, audio, messages, logs or other input and incur charges; confirm scope, redaction and costs first. Ask the user to confirm each resource creation/update/deletion, key/access change or outbound message and test with disposable resources before production. Replace and verify placeholder endpoints and samples. SkillPi checked pinned source, complete attachments and static/antivirus evidence only; it did not run the SDK, verify service compatibility or authorize cloud access.
Before use, confirm and authorize actual file access, external services and network destinations in your host. This review grants no runtime permissions.
Original SKILL.md
---
name: azure-cosmos-ts
description: |
Azure Cosmos DB JavaScript/TypeScript SDK (@azure/cosmos) for data plane operations. Use for CRUD operations on documents, queries, bulk operations, and container management. Triggers: "Cosmos DB", "@azure/cosmos", "CosmosClient", "document CRUD", "NoSQL queries", "bulk operations", "partition key", "container.items".
license: MIT
metadata:
author: Microsoft
version: "1.0.0"
package: '@azure/cosmos'
---
# @azure/cosmos (TypeScript/JavaScript)
Data plane SDK for Azure Cosmos DB NoSQL API operations — CRUD on documents, queries, bulk operations.
> **⚠️ Data vs Management Plane**
> - **This SDK (@azure/cosmos)**: CRUD operations on documents, queries, stored procedures
> - **Management SDK (@azure/arm-cosmosdb)**: Create accounts, databases, containers via ARM
## Installation
```bash
npm install @azure/cosmos @azure/identity
```
**Current Version**: 4.9.0
**Node.js**: >= 20.0.0
## Environment Variables
```bash
COSMOS_ENDPOINT=https://<account>.documents.azure.com:443/
COSMOS_DATABASE=<database-name>
COSMOS_CONTAINER=<container-name>
# For key-based auth only (prefer AAD)
COSMOS_KEY=<account-key>
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
```
## Authentication
### Microsoft Entra Token Credential (Recommended)
```typescript
import { CosmosClient } from "@azure/cosmos";
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();
const client = new CosmosClient({
endpoint: process.env.COSMOS_ENDPOINT!,
aadCredentials: credential,
});
```
### Key-Based Authentication
```typescript
import { CosmosClient } from "@azure/cosmos";
// Option 1: Endpoint + Key
const client = new CosmosClient({
endpoint: process.env.COSMOS_ENDPOINT!,
key: process.env.COSMOS_KEY!,
});
// Option 2: Connection String
const client = new CosmosClient(process.env.COSMOS_CONNECTION_STRING!);
```
## Resource Hierarchy
```
CosmosClient
└── Database
└── Container
├── Items (documents)
├── Scripts (stored procedures, triggers, UDFs)
└── Conflicts
```
## Core Operations
### Database & Container Setup
```typescript
const { database } = await client.databases.createIfNotExists({
id: "my-database",
});
const { container } = await database.containers.createIfNotExists({
id: "my-container",
partitionKey: { paths: ["/partitionKey"] },
});
```
### Create Document
```typescript
interface Product {
id: string;
partitionKey: string;
name: string;
price: number;
}
const item: Product = {
id: "product-1",
partitionKey: "electronics",
name: "Laptop",
price: 999.99,
};
const { resource } = await container.items.create<Product>(item);
```
### Read Document
```typescript
const { resource } = await container
.item("product-1", "electronics") // id, partitionKey
.read<Product>();
if (resource) {
console.log(resource.name);
}
```
### Update Document (Replace)
```typescript
const { resource: existing } = await container
.item("product-1", "electronics")
.read<Product>();
if (existing) {
existing.price = 899.99;
const { resource: updated } = await container
.item("product-1", "electronics")
.replace<Product>(existing);
}
```
### Upsert Document
```typescript
const item: Product = {
id: "product-1",
partitionKey: "electronics",
name: "Laptop Pro",
price: 1299.99,
};
const { resource } = await container.items.upsert<Product>(item);
```
### Delete Document
```typescript
await container.item("product-1", "electronics").delete();
```
### Patch Document (Partial Update)
```typescript
import { PatchOperation } from "@azure/cosmos";
const operations: PatchOperation[] = [
{ op: "replace", path: "/price", value: 799.99 },
{ op: "add", path: "/discount", value: true },
{ op: "remove", path: "/oldField" },
];
const { resource } = await container
.item("product-1", "electronics")
.patch<Product>(operations);
```
## Queries
### Simple Query
```typescript
const { resources } = await container.items
.query<Product>("SELECT * FROM c WHERE c.price < 1000")
.fetchAll();
```
### Parameterized Query (Recommended)
```typescript
import { SqlQuerySpec } from "@azure/cosmos";
const querySpec: SqlQuerySpec = {
query: "SELECT * FROM c WHERE c.partitionKey = @category AND c.price < @maxPrice",
parameters: [
{ name: "@category", value: "electronics" },
{ name: "@maxPrice", value: 1000 },
],
};
const { resources } = await container.items
.query<Product>(querySpec)
.fetchAll();
```
### Query with Pagination
```typescript
const queryIterator = container.items.query<Product>(querySpec, {
maxItemCount: 10, // Items per page
});
while (queryIterator.hasMoreResults()) {
const { resources, continuationToken } = await queryIterator.fetchNext();
console.log(`Page with ${resources?.length} items`);
// Use continuationToken for next page if needed
}
```
### Cross-Partition Query
```typescript
const { resources } = await container.items
.query<Product>(
"SELECT * FROM c WHERE c.price > 500",
{ enableCrossPartitionQuery: true }
)
.fetchAll();
```
## Bulk Operations
### Execute Bulk Operations
```typescript
import { BulkOperationType, OperationInput } from "@azure/cosmos";
const operations: OperationInput[] = [
{
operationType: BulkOperationType.Create,
resourceBody: { id: "1", partitionKey: "cat-a", name: "Item 1" },
},
{
operationType: BulkOperationType.Upsert,
resourceBody: { id: "2", partitionKey: "cat-a", name: "Item 2" },
},
{
operationType: BulkOperationType.Read,
id: "3",
partitionKey: "cat-b",
},
{
operationType: BulkOperationType.Replace,
id: "4",
partitionKey: "cat-b",
resourceBody: { id: "4", partitionKey: "cat-b", name: "Updated" },
},
{
operationType: BulkOperationType.Delete,
id: "5",
partitionKey: "cat-c",
},
{
operationType: BulkOperationType.Patch,
id: "6",
partitionKey: "cat-c",
resourceBody: {
operations: [{ op: "replace", path: "/name", value: "Patched" }],
},
},
];
const response = await container.items.executeBulkOperations(operations);
response.forEach((result, index) => {
if (result.statusCode >= 200 && result.statusCode < 300) {
console.log(`Operation ${index} succeeded`);
} else {
console.error(`Operation ${index} failed: ${result.statusCode}`);
}
});
```
## Partition Keys
### Simple Partition Key
```typescript
const { container } = await database.containers.createIfNotExists({
id: "products",
partitionKey: { paths: ["/category"] },
});
```
### Hierarchical Partition Key (MultiHash)
```typescript
import { PartitionKeyDefinitionVersion, PartitionKeyKind } from "@azure/cosmos";
const { container } = await database.containers.createIfNotExists({
id: "orders",
partitionKey: {
paths: ["/tenantId", "/userId", "/sessionId"],
version: PartitionKeyDefinitionVersion.V2,
kind: PartitionKeyKind.MultiHash,
},
});
// Operations require array of partition key values
const { resource } = await container.items.create({
id: "order-1",
tenantId: "tenant-a",
userId: "user-123",
sessionId: "session-xyz",
total: 99.99,
});
// Read with hierarchical partition key
const { resource: order } = await container
.item("order-1", ["tenant-a", "user-123", "session-xyz"])
.read();
```
## Error Handling
```typescript
import { ErrorResponse } from "@azure/cosmos";
try {
const { resource } = await container.item("missing", "pk").read();
} catch (error) {
if (error instanceof ErrorResponse) {
switch (error.code) {
case 404:
console.log("Document not found");
break;
case 409:
console.log("Conflict - document already exists");
break;
case 412:
console.log("Precondition failed (ETag mismatch)");
break;
case 429:
console.log("Rate limited - retry after:", error.retryAfterInMs);
break;
default:
console.error(`Cosmos error ${error.code}: ${error.message}`);
}
}
throw error;
}
```
## Optimistic Concurrency (ETags)
```typescript
// Read with ETag
const { resource, etag } = await container
.item("product-1", "electronics")
.read<Product>();
if (resource && etag) {
resource.price = 899.99;
try {
// Replace only if ETag matches
await container.item("product-1", "electronics").replace(resource, {
accessCondition: { type: "IfMatch", condition: etag },
});
} catch (error) {
if (error instanceof ErrorResponse && error.code === 412) {
console.log("Document was modified by another process");
}
}
}
```
## TypeScript Types Reference
```typescript
import {
// Client & Resources
CosmosClient,
Database,
Container,
Item,
Items,
// Operations
OperationInput,
BulkOperationType,
PatchOperation,
// Queries
SqlQuerySpec,
SqlParameter,
FeedOptions,
// Partition Keys
PartitionKeyDefinition,
PartitionKeyDefinitionVersion,
PartitionKeyKind,
// Responses
ItemResponse,
FeedResponse,
ResourceResponse,
// Errors
ErrorResponse,
} from "@azure/cosmos";
```
## Best Practices
1. **Use Microsoft Entra Token Credential** — Use `DefaultAzureCredential` for local development; use `ManagedIdentityCredential` or `WorkloadIdentityCredential` for production
2. **Always use parameterized queries** — Prevents injection, improves plan caching
3. **Specify partition key** — Avoid cross-partition queries when possible
4. **Use bulk operations** — For multiple writes, use `executeBulkOperations`
5. **Handle 429 errors** — Implement retry logic with exponential backoff
6. **Use ETags for concurrency** — Prevent lost updates in concurrent scenarios
7. **Close client on shutdown** — Call `client.dispose()` in cleanup
## Common Patterns
### Service Layer Pattern
```typescript
export class ProductService {
private container: Container;
constructor(client: CosmosClient) {
this.container = client
.database(process.env.COSMOS_DATABASE!)
.container(process.env.COSMOS_CONTAINER!);
}
async getById(id: string, category: string): Promise<Product | null> {
try {
const { resource } = await this.container
.item(id, category)
.read<Product>();
return resource ?? null;
} catch (error) {
if (error instanceof ErrorResponse && error.code === 404) {
return null;
}
throw error;
}
}
async create(product: Omit<Product, "id">): Promise<Product> {
const item = { ...product, id: crypto.randomUUID() };
const { resource } = await this.container.items.create<Product>(item);
return resource!;
}
async findByCategory(category: string): Promise<Product[]> {
const querySpec: SqlQuerySpec = {
query: "SELECT * FROM c WHERE c.partitionKey = @category",
parameters: [{ name: "@category", value: category }],
};
const { resources } = await this.container.items
.query<Product>(querySpec)
.fetchAll();
return resources;
}
}
```
## Related SDKs
| SDK | Purpose | Install |
|-----|---------|---------|
| `@azure/cosmos` | Data plane (this SDK) | `npm install @azure/cosmos` |
| `@azure/arm-cosmosdb` | Management plane (ARM) | `npm install @azure/arm-cosmosdb` |
| `@azure/identity` | Authentication | `npm install @azure/identity` |
Copyright and license notice
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
User discussion