@writewhisker/storage
v0.1.0
Published
Framework-agnostic storage layer for Whisker interactive fiction
Maintainers
Readme
@writewhisker/storage
Framework-agnostic storage layer for Whisker interactive fiction.
Features
- Multiple Backends: IndexedDB, localStorage, and extensible to filesystem, cloud, and database storage
- Event-Driven: Emits events for all storage operations, enabling reactive UIs
- Framework Agnostic: Works with any UI framework (Svelte, React, Vue, etc.)
- Type-Safe: Full TypeScript support with comprehensive type definitions
- Async/Await: Modern async API for all operations
Installation
pnpm add @writewhisker/storageQuick Start
import { createIndexedDBStorage, StorageEventType } from '@writewhisker/storage';
// Create storage service with IndexedDB backend
const storage = createIndexedDBStorage();
// Initialize
await storage.initialize();
// Listen to events
storage.on(StorageEventType.STORY_SAVED, (event) => {
console.log('Story saved:', event.storyId, event.title);
});
// Save a story
await storage.saveStory('story-1', {
id: 'story-1',
title: 'My First Story',
passages: [],
// ... other story data
});
// Load a story
const story = await storage.loadStory('story-1');
// List all stories
const stories = await storage.listStories();Backends
IndexedDB (Recommended for browsers)
Best for browser environments. No size limitations (unlike localStorage).
import { IndexedDBBackend, StorageService } from '@writewhisker/storage';
const storage = new StorageService(new IndexedDBBackend());
await storage.initialize();localStorage (Simple alternative)
Simple but has ~5-10MB size limit.
import { LocalStorageBackend, StorageService } from '@writewhisker/storage';
const storage = new StorageService(new LocalStorageBackend());
await storage.initialize();Events
The storage service emits events for all operations:
STORY_SAVED- When a story is savedSTORY_LOADED- When a story is loadedSTORY_DELETED- When a story is deletedSTORY_CREATED- When a new story is createdSTORY_UPDATED- When an existing story is updatedMETADATA_UPDATED- When story metadata is updatedSTORAGE_CLEARED- When all storage is clearedERROR- When an error occurs
storage.on(StorageEventType.STORY_SAVED, (event) => {
console.log('Story saved:', event);
});
storage.on(StorageEventType.ERROR, (event) => {
console.error('Storage error:', event.error, event.operation);
});API Reference
StorageService
Methods
initialize(): Promise<void>- Initialize the backendsaveStory(id: string, data: StoryData, isNew?: boolean): Promise<void>- Save a storyloadStory(id: string): Promise<StoryData>- Load a storydeleteStory(id: string): Promise<void>- Delete a storylistStories(): Promise<StorageMetadata[]>- List all storieshasStory(id: string): Promise<boolean>- Check if story existsgetMetadata(id: string): Promise<StorageMetadata>- Get story metadataupdateMetadata(id: string, metadata: Partial<StorageMetadata>): Promise<void>- Update metadataexportStory(id: string): Promise<Blob>- Export story as JSON blobimportStory(data: Blob | File): Promise<string>- Import story from filegetStorageUsage(): Promise<number>- Get storage usage in bytesclear(): Promise<void>- Clear all storage
Custom Backends
Implement the IStorageBackend interface to create custom backends:
import type { IStorageBackend, StorageMetadata } from '@writewhisker/storage';
import type { StoryData } from '@writewhisker/core-ts';
class MyCustomBackend implements IStorageBackend {
async initialize(): Promise<void> {
// Initialize your backend
}
async saveStory(id: string, data: StoryData): Promise<void> {
// Save implementation
}
// Implement other required methods...
}
const storage = new StorageService(new MyCustomBackend());License
MIT
