@db4/core
v0.1.2
Published
Core types, interfaces, and utilities for db4 document database
Maintainers
Readme
@db4/core
Type-safe primitives for edge databases.
Your edge database has no safety net. One malformed document corrupts production. One swapped ID cascades into data loss. Runtime type errors surface at 3am, not compile time.
@db4/core is the type foundation for db4. Every document, query, transaction, and CDC event flows through these primitives—catching bugs before deployment.
Installation
npm install @db4/coreQuick Start
1. Define Documents
import { type Document, type StoredDocument } from '@db4/core'
interface User extends Document {
id: string
email: string
name: string
createdAt: number
}
// Stored documents get metadata automatically
type StoredUser = StoredDocument & User2. Prevent ID Swaps with Branded Types
import {
type DocumentId,
type CollectionName,
createDocumentId,
createCollectionName
} from '@db4/core'
function getUser(collection: CollectionName, id: DocumentId) { /* ... */ }
const userId = createDocumentId('user_123')
const collection = createCollectionName('users')
getUser(collection, userId) // Compiles
getUser(userId, collection) // TypeScript error—caught at build3. Handle Errors Explicitly
import { ok, err, isOk, type Result } from '@db4/core'
function parseUser(data: unknown): Result<User, Error> {
if (!data || typeof data !== 'object') {
return err(new Error('Invalid user data'))
}
return ok(data as User)
}
const result = parseUser(rawData)
if (isOk(result)) {
console.log(result.data.email) // Type-safe
}Capabilities
Branded Types
Eliminate ID-swap bugs. TypeScript treats these as distinct types:
import {
type DocumentId, type BatchId, type ShardId,
type Timestamp, type Version,
createDocumentId, createTimestamp
} from '@db4/core'
const docId: DocumentId = createDocumentId('doc_abc123')
const timestamp: Timestamp = createTimestamp(Date.now())Structured Errors
Categorized errors with retry guidance:
import {
DocumentNotFoundError,
isRetryableError,
withRetry
} from '@db4/core'
try {
await db.get('users', 'nonexistent')
} catch (error) {
if (error instanceof DocumentNotFoundError) {
console.log(`${error.documentId} not found in ${error.collection}`)
}
if (isRetryableError(error)) {
await withRetry(() => db.get('users', 'id'), { maxRetries: 3 })
}
}Engine Interfaces
Build custom storage backends with standardized contracts:
import type { StorageEngine, QueryEngine } from '@db4/core'
class MyStorageEngine implements StorageEngine {
async get(collection: string, documentId: string) { /* ... */ }
async insert(collection: string, document: Document) { /* ... */ }
}
class MyQueryEngine implements QueryEngine {
async query<T>(collection: string, options: QueryOptions) { /* ... */ }
explain(collection: string, options: QueryOptions) { /* ... */ }
}Cursor Pagination
Relay-style pagination built in:
import { CursorPagination } from '@db4/core'
const pagination = new CursorPagination()
const firstPage = pagination.paginate(documents, {
first: 10,
sortFields: ['createdAt'],
sortDirections: ['desc'],
})
const nextPage = pagination.paginate(documents, {
first: 10,
after: firstPage.pageInfo.endCursor,
sortFields: ['createdAt'],
sortDirections: ['desc'],
})Change Data Capture
Track every mutation for sync and analytics:
import { createCDCCursor, filterCDCEntries } from '@db4/core'
const cursor = createCDCCursor('shard-1', 0)
const userChanges = filterCDCEntries(entries, {
collections: ['users'],
operations: ['INSERT', 'UPDATE'],
})Observability
Structured logging with auto-redaction and OpenTelemetry:
import { createLogger, instrumentQuery } from '@db4/core'
const logger = createLogger({
level: 'info',
redaction: { enabled: true, useDefaults: true }
})
logger.info('User created', { userId: 'abc', email: '[email protected]' })
const result = await instrumentQuery(
async () => db.query('users', { limit: 10 }),
{ collection: 'users', operation: 'query' }
)With @db4/core
- Type errors caught at build time—not 3am
- Consistent types across every db4 package
- Automatic retry for transient failures
- Full visibility into every operation
- Relay pagination that just works
Without It
- Malformed documents corrupt production silently
- Each package invents incompatible types
- Ad-hoc error handling, inconsistent retry logic
- Blind database operations
- Custom pagination in every project
API Reference
Types
| Type | Description |
|------|-------------|
| Document | Base document interface with required id field |
| StoredDocument | Document with _meta (version, timestamps) |
| DocumentMeta | Metadata type with version, createdAt, updatedAt |
| DocumentId, BatchId, ShardId, CollectionName | Branded string types |
| Timestamp, Version | Branded number types |
| QueryOptions, QueryResult | Query configuration and results |
| CDCLogEntry, CDCBatch, CDCCursor | Change data capture types |
| Result<T, E> | Generic result type for error handling |
Error Classes
| Class | Error Code | When It's Thrown |
|-------|------------|------------------|
| DocumentNotFoundError | DOCUMENT_NOT_FOUND | Document doesn't exist |
| DocumentTooLargeError | DOCUMENT_TOO_LARGE | Exceeds 100KB limit |
| MemoryLimitExceededError | MEMORY_LIMIT_EXCEEDED | Query result exceeds memory limit |
| ConflictError | TRANSACTION_CONFLICT | Concurrent modification |
| ValidationError | VALIDATION_ERROR | Invalid input data |
| QueryTimeoutError | QUERY_TIMEOUT | Query exceeded time limit |
| TransactionTimeoutError | TRANSACTION_TIMEOUT | Transaction exceeded time limit |
| BatchError | BATCH_OPERATION_ERROR | Batch operation failures |
Engine Interfaces
| Interface | Purpose |
|-----------|---------|
| StorageEngine | Low-level document storage (CRUD, batch ops) |
| QueryEngine | Query execution and optimization |
| TransactionManager | Transaction lifecycle and conflict detection |
| CDCEngine | Change data capture and streaming |
| IndexManager | Index creation and management |
Constants
import {
MAX_DOCUMENT_SIZE, // 100KB
MAX_BATCH_SIZE, // 900KB
MAX_RESULT_SIZE, // 10MB
DEFAULT_QUERY_LIMIT, // 100
MAX_QUERY_LIMIT, // 10,000
} from '@db4/core'Utilities
import {
generateId, // Time-sortable unique IDs
generateUUID, // UUID v4
jsonSize, // Calculate JSON byte size
deepClone, // Clone objects safely
chunk, // Split arrays into batches
groupBy, // Group array by key function
} from '@db4/core'db4 Ecosystem
@db4/core powers:
@db4/schema- IceType schema compiler@db4/do- Durable Object implementation@db4/query- TypeScript query engine@db4/storage- Three-tier storage@db4/iceberg- CDC to Apache Iceberg
License
MIT
