import { type Chunk, StorageAdapter, type StorageKey, } from "./storage-adapter.js" export class InMemoryStorageAdapter extends StorageAdapter { #data = new Map() constructor( sharedDataOrOptions?: | Map | { sharedData?: Map adapterType?: string /** * Unique identifier for this adapter instance. * If not provided, auto-generated as `{adapterType}-{uuid}`. */ adapterId?: string }, ) { // Handle both old API (just sharedData) and new API (options object) const options = sharedDataOrOptions instanceof Map ? { sharedData: sharedDataOrOptions, adapterType: "in-memory" } : { adapterType: "in-memory", ...sharedDataOrOptions } super({ adapterType: options.adapterType, adapterId: options.adapterId }) if (options.sharedData) { this.#data = options.sharedData } } /** * Get the underlying storage map for sharing between instances */ getStorage(): Map { return this.#data } async load(key: StorageKey): Promise { return this.#data.get(this.#keyToString(key)) } async save(key: StorageKey, data: Uint8Array): Promise { this.#data.set(this.#keyToString(key), data) } async remove(key: StorageKey): Promise { this.#data.delete(this.#keyToString(key)) } async loadRange(keyPrefix: StorageKey): Promise { const results: Chunk[] = [] for (const [keyStr, data] of this.#data.entries()) { const key = this.#stringToKey(keyStr) if (this.#isPrefix(keyPrefix, key)) { results.push({ key, data }) } } return results } async removeRange(keyPrefix: StorageKey): Promise { for (const keyStr of this.#data.keys()) { const key = this.#stringToKey(keyStr) if (this.#isPrefix(keyPrefix, key)) { this.#data.delete(keyStr) } } } #isPrefix(prefix: StorageKey, key: StorageKey): boolean { if (prefix.length > key.length) { return false } return prefix.every((val, i) => val === key[i]) } #keyToString(key: StorageKey): string { return JSON.stringify(key) } #stringToKey(key: string): StorageKey { return JSON.parse(key) } }