Skip to content

Custom storage driver (StorageDriver)

Overview

A storage driver (StorageDriver) is an interface dedicated to storing and managing data. It is responsible for:

  • Storing and reading data
  • Deleting data
  • Partitioning data
  • Monitoring data changes

For detailed storage API information, see the developer reference for storage.

Core type definitions

StorageContext base class

typescript
class StorageContext {
    public id: string;
    public feature: string;
}

The StorageContext class identifies stored data and its feature.

typescript
interface PDFViewer {
    getInstanceId(): string;
}

interface PDFViewerConstructor {
    new(options: {
        instanceId: string,
        customs: {
            storageDriver: StorageDriver;
        }
    }): PDFViewer;
}

Instance ID

The getInstanceId() method returns a unique identifier for the PDFViewer instance. When multiple instances exist, ensure each instance has a unique ID.

StorageDriver interface

typescript
interface StorageDriver {
    getAll(context: StorageContext): Promise<Record<string, any>>;

    get<T>(context: StorageContext, key: string): Promise<T | null>;

    set<T>(context: StorageContext, key: string, value: T): Promise<void>;

    removeAll(context: StorageContext): Promise<void>;

    remove(context: StorageContext, key: string): Promise<void>;

    onChange<T>(callback: (event: StorageDriverChangeEvent<T>) => void): Function;

    onRemove(callback: (event: StorageDriverRemoveEvent) => void): Function;
}

Core methods:

  • getAll: Get all data for the given context
  • get: Get data for a key
  • set: Set data for a key
  • removeAll: Remove all data
  • remove: Remove data for a key
  • onChange: Register a data change listener
  • onRemove: Register a data removal listener

Event interfaces

typescript
interface StorageDriverChangeEvent<T> {
    context: StorageContext;
    key: string;
    oldValue: T;
    newValue: T;
}

interface StorageDriverRemoveEvent {
    context: StorageContext;
    key: string;
}

Implement a custom storage driver

Below is an example based on sessionStorage:

typescript
class MyStorageDriver extends StorageDriver {
    private readonly eventEmitter = new EventEmitter();

    / 生成存储空间名称
    private getSpace(context: StorageContext): string {
        return [context.id, context.feature].join('.');
    }

    / ... existing code ...

    / 核心存储方法实现
    async set<T>(context: StorageContext, key: string, value: T): Promise<void> {
        const storageKey = this.generateUniqueKey(context, key);
        const oldValueJSON = sessionStorage.getItem(storageKey);
        const oldValue = oldValueJSON ? JSON.parse(oldValueJSON) : undefined;
        const newValue = JSON.stringify(value);

        if (oldValueJSON === newValue) return;

        sessionStorage.setItem(storageKey, newValue);
        this.emitChangeEvent({
            context,
            key,
            oldValue,
            newValue: value
        });
    }

    / ... existing code ...
}

Full implementation

See the MyStorageDriver class implementation above for a complete example. It demonstrates how to:

  • Use EventEmitter for events
  • Partition stored data
  • Emit data change notifications

Use a custom storage driver

When creating a PDFViewer instance, pass your custom StorageDriver through the customs option:

typescript
const storageDriver = new MyStorageDriver();

const pdfViewer = new PDFViewer({
    instanceId: 'pdf-viewer-1',
    customs: {
        storageDriver: storageDriver
    }
});

Best practices

  • Assign a unique instanceId to each PDFViewer instance
  • Choose a storage backend that fits your needs (localStorage, IndexedDB, etc.)
  • Partition data so instances do not share or overwrite each other's state