npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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-service

Usage

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 content
  • updateContent(id, data, options) - Update content
  • getContent(id, options) - Get content by ID
  • deleteContent(id, hardDelete?) - Delete content
  • restoreContent(id) - Restore soft-deleted content
  • listContent(filters) - List content with filters
  • publishContent(id) - Publish content
  • scheduleContent(id, date) - Schedule content
  • getVersionHistory(id) - Get version history
  • restoreToVersion(id, versionNumber) - Restore to version
  • startAutosave(id, getData) - Start autosave
  • stopAutosave(id) - Stop autosave
  • on(event, handler) - Subscribe to events
  • cleanup() - Cleanup resources

AutosaveManager

Configuration Options

{
  debounceMs?: number;  // Default: 2000 (2 seconds)
}

Methods

  • queueAutosave(id, getData) - Queue debounced autosave
  • forceAutosave(id, getData) - Force immediate save
  • cancelAutosave(id) - Cancel pending autosave
  • cleanup() - 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.