StorageObject API Documentation (Complete)
Table of Contents
Quick Start
The simplest way to use StorageObject:
import { storage } from '@yihuangdb/storage-object';
const users = await storage('users', {
name: 'text',
email: 'string',
age: 'number',
isActive: 'boolean'
});
const user = await users.create({
name: 'John Doe',
email: 'john@example.com',
age: 30,
isActive: true
});
const found = await users.findById(user.entityId);
const johns = await users.find({ name: 'John' });
const all = await users.findAll();
await users.update(user.entityId, { age: 31 });
await users.delete(user.entityId);
const backup = await users.backup();
const result = await users.restore(backup);
Core API
StorageSystem
The main entry point for managing storage instances:
import { StorageSystem, StorageSchema } from '@yihuangdb/storage-object';
const users = await StorageSystem.create('users', {
name: 'text',
email: 'string',
age: 'number'
});
const users = await StorageSystem.get('users');
const users = await StorageSystem.open('users');
const users = await StorageSystem.getOrCreate('users', schema);
if (await StorageSystem.exists('users')) {
}
const schemas = await StorageSystem.list();
const names = await StorageSystem.names();
await StorageSystem.delete('users');
await StorageSystem.clear('users');
const exported = await StorageSystem.exportAll('./backup');
const imported = await StorageSystem.importAll('./backup');
StorageSchema
Define schemas with validation and advanced options:
import { StorageSchema } from '@yihuangdb/storage-object';
const schema = StorageSchema.define({
name: 'text',
email: 'string',
age: 'number'
});
const schema = StorageSchema.define({
email: {
type: 'string',
indexed: true,
required: true,
validate: (value) => value.includes('@') || 'Invalid email'
},
age: {
type: 'number',
indexed: true,
validate: (value) => value >= 0 || 'Age must be positive'
},
role: {
type: 'string',
indexed: true,
default: 'user'
},
tags: {
type: 'string[]',
separator: ',',
indexed: true
},
createdAt: {
type: 'date',
indexed: true,
default: () => new Date()
}
});
const result = schema.validate(data);
if (!result.valid) {
console.error('Validation errors:', result.errors);
}
const fields = schema.getFields();
const indexedFields = schema.getIndexedFields();
const extended = schema.extend({ newField: 'string' });
const merged = schema1.merge(schema2);
const diff = schema1.diff(schema2);
const migrationPlan = oldSchema.migrateTo(newSchema);
Schema Definition
Field Types
string
- Exact match string field
text
- Full-text searchable string field
number
- Numeric field with range queries
boolean
- Boolean field (true/false)
date
- Date field stored as timestamp
point
- Geographic point field (lon,lat)
string[]
- Array of strings
number[]
- Array of numbers
Field Options
{
type: 'string',
indexed: true,
required: true,
default: 'value',
validate: (v) => true,
sortable: true,
normalized: true,
separator: ',',
description: 'Field desc'
}
Note: Validation functions run client-side in Node.js, not in Redis.
CRUD Operations
Create Operations
const user = await users.create({
name: 'John',
email: 'john@example.com'
});
const created = await users.createMany([
{ name: 'John', email: 'john@example.com' },
{ name: 'Jane', email: 'jane@example.com' }
]);
const result = await users.batchCreate(data, {
atomic: true,
chunkSize: 100
});
Read Operations
const user = await users.findById('uuid-here');
const johns = await users.find({ name: 'John' });
const admin = await users.findOne({ role: 'admin' });
const all = await users.findAll();
const results = await users.find(
{ age: { $gte: 18 } },
{
limit: 10,
offset: 0,
sortBy: 'createdAt',
sortOrder: 'DESC'
}
);
const total = await users.count();
const adults = await users.count({ age: { $gte: 18 } });
const exists = await users.exists('user-id');
Update Operations
const updated = await users.update('user-id', {
age: 31
});
const updated = await users.update('user-id',
{ age: 31 },
{
version: user.__version,
retries: 3
}
);
const results = await users.updateMany(
{ role: 'user' },
{ role: 'member' }
);
const result = await users.batchUpdate(updates, {
atomic: true
});
Delete Operations
await users.delete('user-id');
const deleted = await users.deleteMany({
isActive: false
});
const result = await users.batchDelete(ids, {
atomic: true
});
await users.clear();
Export/Import
Comprehensive export/import functionality at both storage and system levels.
Storage-Level Export/Import
const metadata = await users.export('./users-backup.json');
console.log(`Exported ${metadata.exportedEntityCount} entities`);
const metadata = await users.export('./users.ndjson', {
exportFormat: 'ndjson',
compressOutput: true,
includeSchema: true,
includeData: true
});
const metadata = await users.export('./changes.json', {
incrementalExport: true,
fromStorageVersion: 100,
toStorageVersion: 200
});
const result = await users.import('./users-backup.json');
console.log(`Imported ${result.importedEntityCount} entities`);
console.log(`Failed: ${result.failedEntityCount}`);
const result = await users.import('./users.ndjson', {
validateSchemaVersion: true,
entityMergeStrategy: 'merge',
continueOnError: true,
dryRun: false
});
const backupPath = await users.backup('before-migration');
const result = await users.restore(backupPath);
Incremental Export/Import (Version-Based)
const metadata = await users.exportIncremental(
'./changes-100-200.json',
100,
200
);
console.log(`Exported changes from v${metadata.fromStorageVersion} to v${metadata.toStorageVersion}`);
const metadata = await users.exportIncremental(
'./changes.json.gz',
lastSyncVersion,
undefined,
{ compressOutput: true }
);
const result = await users.importIncremental('./changes.json');
console.log(`Applied ${result.importedEntityCount} changes`);
console.log(`Now at version ${result.endStorageVersion}`);
const result = await users.importIncremental('./changes.json', {
validateSchemaVersion: true,
continueOnError: true,
entityMergeStrategy: 'merge'
});
Storage Synchronization
const sourceStorage = await StorageSystem.get('users');
const targetStorage = await StorageSystem.get('users-replica');
const syncResult = await sourceStorage.sync(targetStorage, {
fromVersion: lastSyncVersion,
toVersion: undefined,
strategy: 'merge',
batchSize: 100
});
console.log(`Synced ${syncResult.syncedCount} entities`);
console.log(`Failed: ${syncResult.failedCount}`);
console.log(`Source version: ${syncResult.sourceVersion}`);
console.log(`Target version: ${syncResult.targetVersion}`);
const sync1 = await storage1.sync(storage2, { fromVersion: lastSync1 });
const sync2 = await storage2.sync(storage1, { fromVersion: lastSync2 });
Version Management
const version = await storage.enableChangeTrackingAsync();
console.log(`Change tracking enabled at version ${version}`);
const currentVersion = await storage.getCurrentStorageVersion();
console.log(`Storage is at version ${currentVersion}`);
const changes = await storage.getChangesSinceVersion(100, 50);
console.log(`Found ${changes.storageChanges.length} changes`);
const summary = await storage.getChangeSummary(100, 200);
console.log(`Changes: ${summary.created} created, ${summary.updated} updated, ${summary.deleted} deleted`);
console.log(`Total: ${summary.totalChanges} changes affecting ${summary.affectedEntityIds.length} entities`);
const history = await storage.getVersionHistory(10);
history.forEach(entry => {
console.log(`Version ${entry.version}: ${entry.changeCount} changes at ${new Date(entry.timestamp)}`);
});
System-Level Export/Import
const result = await StorageSystem.exportAll('./backup', {
compressOutput: true,
includeSchema: true,
includeData: true,
schemasToExport: ['users', 'products']
});
console.log(`Exported ${result.totalExportedEntities} entities`);
console.log('Schemas:', result.exportedSchemas);
const imported = await StorageSystem.importAll('./backup', {
validateSchemaVersion: true,
entityMergeStrategy: 'replace',
continueOnError: false,
schemasToImport: ['users']
});
console.log(`Imported ${imported.totalImportedEntities} entities`);
console.log(`Failed: ${imported.totalFailedEntities}`);
const lastVersions = new Map([
['users', 100],
['products', 50]
]);
const incremental = await StorageSystem.exportIncremental(
'./incremental',
lastVersions,
{ compressOutput: true }
);
const backupDir = await StorageSystem.systemBackup('full-backup');
console.log(`Backup created: ${backupDir}`);
const restored = await StorageSystem.systemRestore(backupDir);
console.log(`Restored ${restored.totalImportedEntities} entities`);
Export Formats
- JSON - Standard JSON format, human-readable
- NDJSON - Newline-delimited JSON, streaming-friendly
- Binary - Compact binary format for large datasets
Merge Strategies
- replace - Replace existing entities completely
- merge - Merge new fields with existing entities
- skip - Skip entities that already exist
Advanced Features
Optimistic Locking
Prevent concurrent update conflicts:
const storage = await StorageSystem.create('users', schema, {
enableOptimisticLocking: true
});
try {
await storage.update('id', data, {
version: entity.__version
});
} catch (error) {
if (error instanceof OptimisticLockError) {
}
}
Change Tracking & Versioning
Comprehensive change tracking for audit trails and synchronization:
const storage = await StorageSystem.create('users', schema, {
enableChangeTracking: true
});
const version = await storage.enableChangeTrackingAsync();
const currentVersion = await storage.getCurrentStorageVersion();
const changes = await storage.getChangesSinceVersion(100, 50);
const summary = await storage.getChangeSummary(100, 200);
console.log(`${summary.created} created, ${summary.updated} updated, ${summary.deleted} deleted`);
const history = await storage.getVersionHistory(10);
history.forEach(v => console.log(`v${v.version}: ${v.changeCount} changes`));
await storage.exportIncremental('./changes.json', lastVersion);
await storage.importIncremental('./changes.json');
await sourceStorage.sync(targetStorage, {
fromVersion: lastSyncVersion,
strategy: 'merge'
});
Use Cases
-
Audit Trail
const startOfDay = await getVersionAtTimestamp(startTime);
const endOfDay = await storage.getCurrentStorageVersion();
await storage.exportIncremental(`./audit/${date}.json`, startOfDay, endOfDay);
-
Multi-Region Sync
setInterval(async () => {
const lastSync = await getLastSyncVersion();
await usEast.sync(euWest, { fromVersion: lastSync });
}, 60000);
-
Real-time Replication
async function replicate() {
const changes = await primary.getChangesSinceVersion(lastVersion);
for (const change of changes.storageChanges) {
if (change.operation === 'c') await replica.create(...);
if (change.operation === 'u') await replica.update(...);
if (change.operation === 'd') await replica.delete(...);
}
}
-
Conflict Resolution
await base.sync(branch1, { strategy: 'merge' });
const result = await base.sync(branch2, {
strategy: 'merge',
continueOnError: true
});
if (result.errors) await handleConflicts(result.errors);
Batch Operations
High-performance batch operations:
const result = await storage.batchCreate(items, {
atomic: true,
chunkSize: 1000
});
if (result.success) {
console.log(`Created ${result.successful} items`);
} else {
console.error(`Failed items:`, result.errors);
}
Performance Monitoring
Track operation performance:
import { profiler } from '@yihuangdb/storage-object';
profiler.enable();
const metrics = profiler.getMetrics();
console.log('Average create time:', metrics.create.avg);
const report = profiler.getReport();
Schema Migration
Migrate between schema versions:
const oldSchema = StorageSchema.define({
firstName: 'string',
lastName: 'string'
});
const newSchema = StorageSchema.define({
fullName: 'string',
email: 'string'
});
const plan = oldSchema.migrateTo(newSchema, {
transformers: {
fullName: (data) => `${data.firstName} ${data.lastName}`
}
});
const result = await StorageSystem.migrate('users', newSchema, {
transform: plan.steps[0].transform,
validateData: true
});
TypeScript Support
Full TypeScript support with type inference:
interface User {
name: string;
email: string;
age: number;
isActive: boolean;
}
const users = await StorageSystem.create<User>('users', {
name: 'text',
email: 'string',
age: 'number',
isActive: 'boolean'
});
const user = await users.create({
name: 'John',
email: 'john@example.com',
age: 30,
isActive: true
});
await users.update(user.entityId, {
age: 31
});
Connection Management
Configure Redis connection:
await StorageSystem.initialize({
redis: {
host: 'localhost',
port: 6379,
password: 'secret',
db: 0
},
connectionPool: {
maxSize: 20,
idleTimeout: 30000
},
defaultOptions: {
useJSON: true,
enableOptimisticLocking: true
}
});
StorageSystem.configure((config) => {
config.redis = {
host: process.env.REDIS_HOST || 'localhost'
};
});
Error Handling
import { OptimisticLockError } from '@yihuangdb/storage-object';
try {
await storage.update(id, data);
} catch (error) {
if (error instanceof OptimisticLockError) {
console.log('Conflict detected, retrying...');
} else {
console.error('Update failed:', error);
}
}
Best Practices
-
Use the Quick Start API for simple cases
const users = await storage('users', { name: 'text', email: 'string' });
-
Define schemas separately for reuse
const userSchema = StorageSchema.define({ });
const users = await StorageSystem.create('users', userSchema);
-
Enable optimistic locking for concurrent environments
const storage = await StorageSystem.create('users', schema, {
enableOptimisticLocking: true
});
-
Use batch operations for bulk data
await storage.batchCreate(largeDataSet, { atomic: true });
-
Add validation to schemas
email: {
type: 'string',
validate: (v) => v.includes('@') || 'Invalid email'
}
-
Use TypeScript interfaces for type safety
interface User { }
const users = await StorageSystem.create<User>('users', schema);
-
Regular backups
setInterval(async () => {
await storage.backup(`daily-${new Date().toISOString()}`);
}, 24 * 60 * 60 * 1000);
-
Clean up connections when done
await storage.disconnect();
Version Tracking API Reference
Core Version Methods
getCurrentStorageVersion() | Get current version number | number | null |
getChangesSinceVersion(from, limit?) | Get changes since version | StorageVersionBatch |
getChangeSummary(from, to?) | Summarize changes between versions | ChangeSummary |
getVersionHistory(limit?) | Get version history | Array<VersionEntry> |
enableChangeTrackingAsync() | Enable version tracking | Promise<number> |
Export/Import Methods
export(path, options?) | Full/Incremental | General export with options |
exportIncremental(path, from, to?, options?) | Incremental | Export changes between versions |
import(path, options?) | Full/Incremental | General import with options |
importIncremental(path, options?) | Incremental | Import and apply changes |
backup(name?) | Full | Quick compressed backup |
restore(path) | Full | Quick restore from backup |
Synchronization
sync(target, options?) | Synchronize with another storage instance |
Sync Options
interface SyncOptions {
fromVersion?: number;
toVersion?: number;
strategy?: 'replace' | 'merge' | 'skip';
batchSize?: number;
}
Complete Example
import { StorageSystem, StorageSchema } from '@yihuangdb/storage-object';
interface User {
name: string;
email: string;
age: number;
role: string;
tags: string[];
isActive: boolean;
createdAt: Date;
}
const userSchema = StorageSchema.define<User>({
name: { type: 'text', indexed: true, required: true },
email: {
type: 'string',
indexed: true,
required: true,
validate: (email) => email.includes('@') || 'Invalid email'
},
age: {
type: 'number',
indexed: true,
validate: (age) => age >= 0 && age <= 150 || 'Invalid age'
},
role: {
type: 'string',
indexed: true,
default: 'user'
},
tags: { type: 'string[]', separator: ',' },
isActive: { type: 'boolean', indexed: true, default: true },
createdAt: { type: 'date', indexed: true, default: () => new Date() }
});
const users = await StorageSystem.create<User>('users', userSchema, {
enableOptimisticLocking: true,
enableChangeTracking: true,
useJSON: true
});
const john = await users.create({
name: 'John Doe',
email: 'john@example.com',
age: 30,
role: 'admin',
tags: ['vip', 'early-adopter']
});
const v1 = await users.getCurrentStorageVersion();
const admins = await users.find({ role: 'admin' });
const activeVips = await users.find({
isActive: true,
tags: ['vip']
});
const backupPath = await users.backup('before-role-migration');
await users.updateMany(
{ role: 'user' },
{ role: 'member' }
);
const v2 = await users.getCurrentStorageVersion();
const summary = await users.getChangeSummary(v1, v2);
console.log(`Updated ${summary.updated} users from 'user' to 'member'`);
await users.exportIncremental('./role-migration-changes.json', v1, v2);
const replica = await StorageSystem.create<User>('users-replica', userSchema, {
enableChangeTracking: true
});
const syncResult = await users.sync(replica, {
fromVersion: 0,
strategy: 'replace'
});
console.log(`Synced ${syncResult.syncedCount} entities to replica`);
await users.export('./users-export.json', {
compressOutput: true,
includeSchema: true
});
Incremental Sync Example
const primary = await StorageSystem.create('users-primary', schema, {
enableChangeTracking: true
});
const replica = await StorageSystem.create('users-replica', schema, {
enableChangeTracking: true
});
await primary.create({ name: 'Alice', email: 'alice@example.com' });
await primary.create({ name: 'Bob', email: 'bob@example.com' });
const v1 = await primary.getCurrentStorageVersion();
await primary.update(aliceId, { role: 'admin' });
await primary.delete(bobId);
await primary.create({ name: 'Charlie', email: 'charlie@example.com' });
const v2 = await primary.getCurrentStorageVersion();
const changesPath = './changes-v1-v2.json';
await primary.exportIncremental(changesPath, v1, v2);
await replica.importIncremental(changesPath);
const syncResult = await primary.sync(replica, {
fromVersion: v1,
strategy: 'merge'
});
const primaryCount = await primary.count();
const replicaCount = await replica.count();
console.log(`Sync complete: Primary=${primaryCount}, Replica=${replicaCount}`);
const history = await primary.getVersionHistory(5);
history.forEach(entry => {
console.log(`Version ${entry.version}: ${entry.changeCount} changes`);
});