From d7a5862722f9739ad02fc62fe2a52eccdc1e7f2a Mon Sep 17 00:00:00 2001 From: Yuqing Bai Date: Sun, 5 Apr 2026 10:06:51 +0800 Subject: [PATCH] feat(storage): add InMemoryKVStore, InMemoryStore accepts optional KVStore --- src/memory/store.ts | 32 +++++++++++++++++++++++++++++- tests/kv-store.test.ts | 45 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 tests/kv-store.test.ts diff --git a/src/memory/store.ts b/src/memory/store.ts index f219fe3..18179bf 100644 --- a/src/memory/store.ts +++ b/src/memory/store.ts @@ -7,7 +7,35 @@ * in production by satisfying the same {@link MemoryStore} interface. */ -import type { MemoryEntry, MemoryStore } from '../types.js' +import type { KVStore, MemoryEntry, MemoryStore } from '../types.js' + +// --------------------------------------------------------------------------- +// InMemoryKVStore +// --------------------------------------------------------------------------- + +export class InMemoryKVStore implements KVStore { + private readonly data = new Map() + + async get(key: string): Promise { + return this.data.get(key) ?? null + } + + async set(key: string, value: string): Promise { + this.data.set(key, value) + } + + async delete(key: string): Promise { + this.data.delete(key) + } + + async list(): Promise { + return Array.from(this.data.keys()) + } + + async clear(): Promise { + this.data.clear() + } +} // --------------------------------------------------------------------------- // InMemoryStore @@ -31,6 +59,8 @@ import type { MemoryEntry, MemoryStore } from '../types.js' export class InMemoryStore implements MemoryStore { private readonly data = new Map() + constructor(_kvStore?: KVStore) {} + // --------------------------------------------------------------------------- // MemoryStore interface // --------------------------------------------------------------------------- diff --git a/tests/kv-store.test.ts b/tests/kv-store.test.ts new file mode 100644 index 0000000..ac4290f --- /dev/null +++ b/tests/kv-store.test.ts @@ -0,0 +1,45 @@ +import { describe, it, expect } from 'vitest' +import { InMemoryKVStore } from '../src/memory/store.js' + +describe('InMemoryKVStore', () => { + it('sets and gets a value', async () => { + const store = new InMemoryKVStore() + await store.set('k1', 'v1') + expect(await store.get('k1')).toBe('v1') + }) + + it('returns null for missing key', async () => { + const store = new InMemoryKVStore() + expect(await store.get('nope')).toBeNull() + }) + + it('overwrites existing key', async () => { + const store = new InMemoryKVStore() + await store.set('k', 'first') + await store.set('k', 'second') + expect(await store.get('k')).toBe('second') + }) + + it('deletes a key', async () => { + const store = new InMemoryKVStore() + await store.set('k', 'v') + await store.delete('k') + expect(await store.get('k')).toBeNull() + }) + + it('list returns all keys', async () => { + const store = new InMemoryKVStore() + await store.set('a', '1') + await store.set('b', '2') + const keys = await store.list() + expect(keys.sort()).toEqual(['a', 'b']) + }) + + it('clear removes all keys', async () => { + const store = new InMemoryKVStore() + await store.set('a', '1') + await store.set('b', '2') + await store.clear() + expect(await store.list()).toEqual([]) + }) +})