2.0 KiB
sync-queue/memory-store.ts
Purpose
Fastest possible SyncQueueStore implementation, backed by a private array.
Used as the default in unit tests and as a fallback in environments where
neither localStorage nor indexedDB is available (notably inside a Service
Worker global scope, where persistence must be managed via Cache or a side
channel). Entries are deep-copied on every read and write so callers cannot
mutate the store's internal state by retaining a reference.
Features
- Synchronous semantics wrapped in
Promise.resolveso it conforms to the asyncSyncQueueStorecontract identically to the IDB-backed store. - Optional
seedarray for tests that want a pre-populated queue. - Defensive copies on
load()andsave().
Usage: Basic
import { MemoryStore, SyncQueue } from "@suaveplan/pwa";
const queue = new SyncQueue({ store: new MemoryStore() });
Usage: Advanced
Seed a queue with entries that need processing on the very first process()
call (useful for replaying a snapshot):
import { MemoryStore } from "@suaveplan/pwa";
const seeded = new MemoryStore([
{
id: "sq_1",
url: "/api/x",
method: "POST",
createdAt: Date.now(),
retryCount: 0,
maxRetries: 3,
schemaVersion: 2,
},
]);
API Reference
new MemoryStore(seed?: readonly SyncQueueEntry[]).load(): Promise<Record<string, unknown>[]>.save(entries: readonly SyncQueueEntry[]): Promise<void>.
Implementation Notes
The store always copies entries via { ...e } rather than returning the raw
array, so a caller that mutates a returned entry never corrupts the store's
internal state. The shallow copy is sufficient because SyncQueueEntry
contains only primitives, optional plain records, and optional plain strings —
no nested mutable references that need a deeper clone. The synchronous body
wrapped in async keeps the interface trivially substitutable with the IDB
and LocalStorage stores without any caller-side branching.