Quick Start
Install cosmoose, connect to Cosmos DB, and perform CRUD operations in minutes
Prerequisites
- Node.js 18 or later
- An Azure Cosmos DB account (or the Cosmos DB Emulator)
Install
pnpm add @cosmoose/coreyarn add @cosmoose/corenpm install @cosmoose/coreThe package has the following peer dependencies that are installed automatically:
@azure/cosmos— Azure Cosmos DB SDKzod— Schema validationuuid— ID generation
Cosmoose is written in TypeScript and ships type definitions out of the box. No additional @types packages are needed.
Usage
This guide walks you through the core workflow: connect, define a schema, register a model, sync containers, and perform CRUD operations.
Connect to Cosmos DB
import { Cosmoose } from '@cosmoose/core';
const cosmoose = new Cosmoose({
endpoint: process.env.COSMOS_ENDPOINT!,
key: process.env.COSMOS_KEY!,
databaseName: 'my-app',
});
await cosmoose.connect();The database is created automatically if it doesn't exist.
Define a Schema
import { Schema, Type } from '@cosmoose/core';
interface User {
name: string;
email: string;
age: number;
role: string;
}
const userSchema = new Schema<User>(
{
name: { type: Type.STRING, trim: true },
email: { type: Type.EMAIL },
age: { type: Type.NUMBER },
role: { type: Type.STRING, default: 'member' },
},
{
timestamps: true,
container: {
partitionKey: '/email',
},
},
);Schemas validate data before it reaches Cosmos DB. The timestamps option automatically manages createdAt and updatedAt fields.
Register a Model
const User = cosmoose.model('users', userSchema);The first argument is the container name in Cosmos DB. The model provides type-safe CRUD operations for that container.
Sync Containers
Before inserting data, ensure the container exists with the correct configuration:
const report = await cosmoose.syncContainers();
for (const result of report) {
console.log(`${result.name}: ${result.status}`);
// "users: created" on first run
// "users: unchanged" on subsequent runs
}syncContainers() creates missing containers and detects drift between your schema and the actual container configuration.
Create and Query Documents
// Create a document
const user = await User.create({
name: 'Alice',
email: 'alice@example.com',
age: 30,
});
console.log(user.id); // auto-generated UUID v7
console.log(user.createdAt); // auto-set timestamp// Get by ID
const found = await User.getById(user.id, {
partitionKeyValue: user.email,
});
// Query with filters
const results = await User.find({ age: { $gte: 18 } })
.sort({ name: 1 })
.limit(10);
// Count
const count = await User.count({ role: 'member' });Update and Patch
// Full replacement
await User.updateById(user.id, {
...user,
age: 31,
}, { partitionKeyValue: user.email });// Partial patch (only updates specified fields)
await User.patchById(user.id, {
$set: { age: 31 },
$incr: { loginCount: 1 },
}, { partitionKeyValue: user.email });Patches are more efficient than full replacements — they only update the fields you specify.