@bernierllc/content-storage-service
v1.2.2
Published
Content storage orchestrator with soft-delete, versioning, and autosave
Readme
@bernierllc/content-storage-service
Content storage orchestrator with soft-delete, versioning, and autosave capabilities.
Overview
Service-layer orchestrator for content management operations. Coordinates content storage, versioning, autosave, and soft-delete workflows. Provides business logic layer on top of @bernierllc/content-storage-adapter.
Features
- Event-Driven Architecture - Publishes events for content lifecycle (created, updated, published)
- Automatic Versioning - Creates versions on save with autosave support
- Soft-Delete by Default - Prevents data loss, supports restore
- Autosave Management - Configurable autosave with debouncing
- Optimistic Locking - Prevents concurrent modification conflicts
- Publishing Workflows - Support for immediate publish and scheduled publishing
Installation
npm install @bernierllc/content-storage-serviceUsage
Basic Setup
import { ContentStorageService } from '@bernierllc/content-storage-service';
import { PostgreSQLAdapter } from '@bernierllc/database-adapter-postgresql';
const dbAdapter = new PostgreSQLAdapter(config);
await dbAdapter.connect();
const service = new ContentStorageService(dbAdapter, {
autosaveIntervalMs: 30000, // 30 seconds
enableVersioning: true,
enableSoftDelete: true
});Create Content
const result = await service.createContent({
userId: 'user123',
title: 'My Blog Post',
body: 'Content goes here...',
excerpt: 'A brief summary'
});
if (result.success) {
console.log('Created:', result.data.id);
}Update Content
const result = await service.updateContent('content-id', {
title: 'Updated Title',
body: 'Updated content'
}, {
createVersion: true // Save this as a new version
});Autosave
// Start autosave
service.startAutosave('content-id', async () => ({
title: editor.getTitle(),
body: editor.getContent()
}));
// Stop autosave when done
service.stopAutosave('content-id');Autosave with Debouncing
import { AutosaveManager } from '@bernierllc/content-storage-service';
const autosave = new AutosaveManager(service, {
debounceMs: 2000 // Wait 2 seconds after typing stops
});
// Queue autosave (debounced)
autosave.queueAutosave('content-id', async () => ({
title: editor.getTitle(),
body: editor.getContent()
}));
// Force immediate save (on blur, navigation)
await autosave.forceAutosave('content-id', async () => ({
title: editor.getTitle(),
body: editor.getContent()
}));Soft Delete and Restore
// Soft delete (default)
await service.deleteContent('content-id');
// Restore
await service.restoreContent('content-id');
// Hard delete (permanent)
await service.deleteContent('content-id', true);Publishing Workflows
// Publish immediately
await service.publishContent('content-id');
// Schedule for later
const scheduledDate = new Date('2025-12-31T00:00:00Z');
await service.scheduleContent('content-id', scheduledDate);Version Management
// Get version history
const result = await service.getVersionHistory('content-id');
// Restore to specific version
await service.restoreToVersion('content-id', versionNumber);Event Handling
// Subscribe to events
const unsubscribe = service.on('content.created', (event) => {
console.log('Content created:', event.contentId);
});
// Available events:
// - content.created
// - content.updated
// - content.autosaved
// - content.deleted
// - content.restored
// - content.published
// - content.scheduled
// - content.version.restored
// Unsubscribe when done
unsubscribe();Cleanup
// Stop all autosave intervals
await service.cleanup();API Reference
ContentStorageService
Configuration Options
interface IContentStorageServiceConfig {
autosaveIntervalMs?: number; // Default: 30000 (30 seconds)
enableVersioning?: boolean; // Default: true
enableSoftDelete?: boolean; // Default: true
}Methods
createContent(data)- Create new contentupdateContent(id, data, options)- Update contentgetContent(id, options)- Get content by IDdeleteContent(id, hardDelete?)- Delete contentrestoreContent(id)- Restore soft-deleted contentlistContent(filters)- List content with filterspublishContent(id)- Publish contentscheduleContent(id, date)- Schedule contentgetVersionHistory(id)- Get version historyrestoreToVersion(id, versionNumber)- Restore to versionstartAutosave(id, getData)- Start autosavestopAutosave(id)- Stop autosaveon(event, handler)- Subscribe to eventscleanup()- Cleanup resources
AutosaveManager
Configuration Options
{
debounceMs?: number; // Default: 2000 (2 seconds)
}Methods
queueAutosave(id, getData)- Queue debounced autosaveforceAutosave(id, getData)- Force immediate savecancelAutosave(id)- Cancel pending autosavecleanup()- Cleanup all pending saves
Service Result Pattern
All service methods return a consistent result pattern:
interface IServiceResult<T> {
success: boolean;
data?: T;
error?: string;
}Dependencies
@bernierllc/content-storage-adapter- Content CRUD operations@bernierllc/database-adapter-core- Database abstractions@bernierllc/database-adapter-postgresql- PostgreSQL implementation@bernierllc/event-emitter- Event publishing@bernierllc/logger- Structured logging@bernierllc/retry-policy- Retry logic
License
Copyright (c) 2025 Bernier LLC. All rights reserved.
