Skip to main content

azure-cosmos-ts

"Implement — Azure Cosmos DB JavaScript/TypeScript SDK (@azure/cosmos) for data plane operations. Use for CRUD operations"

Quellinformationen

Repository
thiagofernandes1987-create/APEX
Letzte Quellaktivität
18. April 2026 um 09:35
Erkannte Sprache von SKILL.md
Englisch
Sterne
2
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
azure-cosmos-ts
description
"Implement — Azure Cosmos DB JavaScript/TypeScript SDK (@azure/cosmos) for data plane operations. Use for CRUD operations"
# @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> ``` ## Authentication ### AAD with DefaultAzureCredential (Recommended) ```typescript import { CosmosClient } from "@azure/cosmos"; import { DefaultAzureCredential } from "@azure/identity"; const client = new CosmosClient({ endpoint: process.env.COSMOS_ENDPOINT!, aadCredentials: new DefaultAzureCredential(), }); ``` ### 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 AAD authentication** — Prefer `DefaultAzureCredential` over keys 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",
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen