API Reference
Complete API reference for CosmosQL field types, container methods, and query options
Complete reference for CosmosQL's API, including field types, container methods, query operators, and configuration options.
Field Types
CosmosQL provides a fluent API for defining field types in your schema:
// Primitive types
field.string() // String type
field.number() // Number type
field.boolean() // Boolean type
field.date() // Date type (stored as ISO strings)
// Complex types
field.array(type) // Array of any field type
field.object(schema) // Nested object with its own schema
// Modifiers
.optional() // Makes field optional (can be undefined)
.default(value) // Provides default value for optional fieldsExample Schema with All Field Types:
const users = container('users', {
// Required fields
id: field.string(),
email: field.string(),
name: field.string(),
age: field.number(),
isActive: field.boolean(),
createdAt: field.date(),
// Optional fields
bio: field.string().optional(),
lastLoginAt: field.date().optional(),
// Fields with defaults
viewCount: field.number().default(0),
settings: field.object({
theme: field.string().default('light'),
notifications: field.boolean().default(true)
}).optional(),
// Arrays
tags: field.array(field.string()),
scores: field.array(field.number()),
// Nested objects
profile: field.object({
website: field.string().optional(),
location: field.string().optional()
}).optional()
}).partitionKey('email');Container Configuration
Containers can be configured with throughput, indexing policies, and more:
const posts = container('posts', {
id: field.string(),
userId: field.string(),
title: field.string(),
content: field.string(),
tags: field.array(field.string()),
createdAt: field.date()
})
.partitionKey('userId')
.throughput(400) // Optional: Set RU/s (Request Units per second)
.indexing({ // Optional: Configure indexing policy
automatic: true,
includedPaths: [
{ path: '/title/?' },
{ path: '/tags/[]/?' }
],
excludedPaths: [
{ path: '/content/?' }
],
compositeIndexes: [
[
{ path: '/createdAt', order: 'ascending' },
{ path: '/userId', order: 'ascending' }
]
]
});Container Configuration Options:
.partitionKey(field)- Required: Specifies the partition key field.throughput(ru)- Optional: Sets RU/s for the container (default: auto-scale).indexing(policy)- Optional: Configures indexing policy
Indexing Policy Options:
indexing: {
automatic: boolean; // Enable automatic indexing
includedPaths?: Array<{ // Paths to index
path: string; // Path pattern (e.g., '/title/?')
indexes?: Array<{
kind: 'Range' | 'Hash'; // Index kind
precision?: number; // Precision for range indexes
dataType: 'String' | 'Number' // Data type
}>
}>;
excludedPaths?: Array<{ // Paths to exclude from indexing
path: string;
}>;
compositeIndexes?: Array< // Composite indexes for multi-field sorting
Array<{
path: string;
order: 'ascending' | 'descending';
}>
>;
spatialIndexes?: Array<{ // Spatial indexes (advanced)
path: string;
types: Array<'Point' | 'LineString' | 'Polygon' | 'MultiPolygon'>;
}>;
}Container Methods
Query Operations
findUnique(options)
Retrieves a single document by ID and partition key. This is the most efficient operation (point read).
const user = await db.users.findUnique({
where: {
id: 'user_123',
email: 'john@example.com' // Partition key required
},
select: {
name: true,
email: true
}
});
// Returns: { name: string; email: string } | nullfindMany(options)
Queries multiple documents with filtering, sorting, and pagination. Optionally include aggregations to get both data and statistics in a single query.
// Without aggregations
const users = await db.users.findMany({
partitionKey: 'john@example.com',
where: {
isActive: true,
age: { gte: 18 }
},
select: { id: true, name: true },
orderBy: { age: 'desc' },
take: 10,
skip: 0
});
// Returns: Array<{ id: string; name: string }>
// With aggregations
const result = await db.users.findMany({
partitionKey: 'john@example.com',
where: { isActive: true },
aggregate: {
_count: true,
_avg: { age: true },
_sum: { score: true },
_min: { createdAt: true },
_max: { createdAt: true }
}
});
// Returns: {
// data: User[],
// _count: number,
// _avg: { age: number | null },
// _sum: { score: number | null },
// _min: { createdAt: Date | null },
// _max: { createdAt: Date | null }
// }See Aggregations Guide for complete documentation.
query<T>(options)
Execute raw SQL queries for advanced use cases.
const result = await db.users.query<{ count: number }>({
sql: 'SELECT COUNT(1) as count FROM c WHERE c.isActive = true',
parameters: [
{ name: '@active', value: true }
],
partitionKey: 'john@example.com' // Optional: for partition-scoped queries
});
// Returns: Array<T>Write Operations
create(options)
Creates a single document.
const user = await db.users.create({
data: {
id: 'user_123',
email: 'john@example.com',
name: 'John Doe',
age: 30,
createdAt: new Date()
// isActive will use default value if defined
}
});
// Returns: Full user object (fully typed)createMany(options)
Creates multiple documents in a single operation. All documents must share the same partition key.
await db.users.createMany({
data: [
{ id: 'user_1', email: 'user1@test.com', name: 'User 1', age: 25 },
{ id: 'user_2', email: 'user2@test.com', name: 'User 2', age: 30 }
],
partitionKey: 'shared@email.com' // All must share partition key
});update(options)
Updates a single document by ID and partition key.
await db.users.update({
where: {
id: 'user_123',
email: 'john@example.com' // Partition key required
},
data: {
age: 31,
name: 'John Smith'
}
});
// Returns: Updated user objectupsert(options)
Updates a document if it exists, creates it if it doesn't.
await db.users.upsert({
where: {
id: 'user_123',
email: 'john@example.com'
},
create: {
id: 'user_123',
email: 'john@example.com',
name: 'New User',
age: 25
},
update: {
age: 26,
name: 'Updated Name'
}
});delete(options)
Deletes a single document by ID and partition key.
await db.users.delete({
where: {
id: 'user_123',
email: 'john@example.com' // Partition key required
}
});Aggregation Operations
count(options)
Count documents matching criteria.
const count = await db.users.count({
partitionKey: 'john@example.com',
where: { isActive: true }
});
// Returns: numberaggregate(options)
Perform aggregation operations (count, sum, avg, min, max).
const stats = await db.orders.aggregate({
partitionKey: 'customer-123',
where: { status: 'completed' },
_count: true,
_sum: { amount: true, tax: true },
_avg: { amount: true },
_min: { createdAt: true },
_max: { amount: true }
});
// Returns: {
// _count: number,
// _sum: { amount: number | null, tax: number | null },
// _avg: { amount: number | null },
// _min: { createdAt: Date | null },
// _max: { amount: number | null }
// }groupBy(options)
Group data and perform aggregations on each group.
const salesByCategory = await db.sales.groupBy({
by: 'category',
enableCrossPartitionQuery: true,
_count: true,
_sum: { amount: true },
_avg: { amount: true },
orderBy: { _sum_amount: 'desc' },
take: 10
});
// Returns: Array<{
// category: string,
// _count: number,
// _sum: { amount: number | null },
// _avg: { amount: number | null }
// }>Convenience Methods:
// Quick aggregations for single fields
const totalRevenue = await db.orders.sum('amount', {
partitionKey: 'customer-123',
where: { status: 'completed' }
});
// Returns: number | null
const avgAge = await db.users.avg('age', {
partitionKey: 'tenant-1'
});
// Returns: number | null
const minPrice = await db.products.min('price', {
partitionKey: 'category-electronics'
});
// Returns: number | null
const maxPrice = await db.products.max('price', {
partitionKey: 'category-electronics'
});
// Returns: number | nullSee Aggregations Guide for complete documentation.
Query Operators
String Operators
where: {
name: { contains: 'John' }, // CONTAINS(c.name, 'John')
email: { startsWith: 'user' }, // STARTSWITH(c.email, 'user')
bio: { endsWith: 'developer' } // ENDSWITH(c.bio, 'developer')
}Number Operators
where: {
age: { gt: 21 }, // c.age > 21 (greater than)
score: { gte: 85 }, // c.score >= 85 (greater than or equal)
rating: { lt: 5 }, // c.rating < 5 (less than)
count: { lte: 100 }, // c.count <= 100 (less than or equal)
// Multiple conditions (range)
age: { gte: 18, lte: 65 } // 18 <= c.age <= 65
}Array Operators
where: {
tags: { contains: 'javascript' }, // CONTAINS(c.tags, 'javascript')
skills: { containsAny: ['react', 'node'] }, // Any element matches (planned)
permissions: { containsAll: ['read', 'write'] } // All elements must match (planned)
}Note: containsAny and containsAll are planned features. Currently, use contains for single element checks or raw SQL queries for complex array operations.
Boolean Operators
where: {
isActive: true, // Exact match
isActive: { equals: true }, // Explicit equals (same as above)
isVerified: false
}Date Operators
where: {
createdAt: { gte: new Date('2024-01-01') }, // Greater than or equal
publishedAt: { lt: new Date() }, // Less than
lastLoginAt: { lte: new Date() } // Less than or equal
}Nested Object Queries
where: {
profile: {
settings: {
theme: 'dark',
notifications: true
}
}
}Combining Operators
where: {
// Multiple conditions (AND logic)
isActive: true,
age: { gte: 18, lte: 65 },
name: { startsWith: 'John' },
tags: { contains: 'developer' }
}Query Options
where - Filter conditions
where: {
// Exact match
isActive: true,
// Comparisons
age: { gte: 18, lte: 65 },
// String operations
name: { startsWith: 'John' },
bio: { contains: 'developer' },
// Array operations
tags: { contains: 'javascript' },
// Nested objects
profile: {
settings: { theme: 'dark' }
}
}select - Choose fields to return
select: {
id: true,
name: true,
email: true,
profile: {
website: true
}
}
// Returns only selected fieldsorderBy - Sort results
orderBy: {
age: 'desc', // Sort by age descending
name: 'asc' // Then by name ascending
}take - Limit results (maximum number)
take: 10 // Return maximum 10 documentsskip - Offset results
skip: 20 // Skip first 20 documents (for pagination)partitionKey - Scope query to partition
partitionKey: 'john@example.com' // Single value
partitionKey: ['tenant_1', 'org_a'] // Composite partition key (array)enableCrossPartitionQuery - Allow expensive cross-partition queries
enableCrossPartitionQuery: true // Must explicitly opt-inClient Configuration
Connection Options:
const db = await createClient({
// Option 1: Connection string (recommended)
connectionString: process.env.COSMOS_CONNECTION_STRING!,
// Option 2: Explicit endpoint + key
endpoint: 'https://myaccount.documents.azure.com:443/',
key: process.env.COSMOS_KEY!,
// Required: Database name
database: 'myapp',
// Optional: Container validation mode
mode: 'auto-create', // 'auto-create' | 'verify' | 'skip'
// Optional: Retry configuration
retryOptions: {
maxRetries: 3, // Default: 3
initialDelay: 100, // Default: 100ms
maxDelay: 5000 // Default: 5000ms
}
}).withContainers({ users, posts });Configuration Options:
| Option | Type | Default | Description |
|---|---|---|---|
endpoint | string | - | Azure CosmosDB endpoint URL |
key | string | - | Azure CosmosDB master key |
connectionString | string | - | Full connection string (alternative to endpoint+key) |
database | string | Required | Database name |
mode | ContainerMode | 'verify' | Container management mode |
retryOptions | object | See below | Retry configuration |
Container Modes:
'auto-create'- Automatically creates database and containers if they don't exist'verify'- Validates that database and containers exist with correct configuration (production default)'skip'- Skips all checks for maximum performance
Retry Options:
retryOptions: {
maxRetries?: number; // Default: 3
initialDelay?: number; // Default: 100ms
maxDelay?: number; // Default: 5000ms
}Note: Client creation is async. It validates and optionally creates containers based on the mode parameter. See Getting Started Guide for detailed mode documentation.
Container Registration:
.withContainers({
users,
posts,
comments
// Add all your container schemas here
})Database Operations
Container Management
listOrphanedContainers()
Lists containers in the database that are not registered in your schema. Useful for identifying containers that may need cleanup.
const orphaned = await db.listOrphanedContainers();
// Returns: string[] - Array of container names not in schemadeleteContainers(names)
Deletes specific containers by name. Use with caution as this permanently removes containers and all their data.
await db.deleteContainers(['old_container', 'temp_container']);pruneContainers(options)
Removes all orphaned containers (containers not in your schema). Requires explicit confirmation.
// Prune all orphaned containers (requires confirmation)
await db.pruneContainers({ confirm: true });
// Get list of containers that would be pruned without deleting
const orphaned = await db.listOrphanedContainers();
console.log('Would delete:', orphaned);⚠️ Warning: These operations permanently delete containers and all their data. Always back up important data before using these methods.
This documentation provides comprehensive coverage of CosmosQL's API. The library enforces CosmosDB best practices at the type level, preventing costly mistakes before they reach production.
Next Steps:
-
Install CosmosQL:
npm install cosmosql -
Define your schema using the field types above
-
Start querying with full type safety
For questions or issues, visit the GitHub repository or Discord community.