diff --git a/docs/KVPeer.md b/docs/KVPeer.md index 33bcda6..1dd9e84 100644 --- a/docs/KVPeer.md +++ b/docs/KVPeer.md @@ -25,6 +25,8 @@ export interface KVOptions, K ext adapter: DatabaseConnection; type?: KVType; mapValue?: KVMapper; + prefix?: string; + prefixSeparator?: string; } export type KVPeerSetValueOptions = Omit< diff --git a/src/class/KVPeer.class.ts b/src/class/KVPeer.class.ts index 7529720..02cb3dd 100644 --- a/src/class/KVPeer.class.ts +++ b/src/class/KVPeer.class.ts @@ -24,6 +24,8 @@ export interface KVOptions, K ext adapter: DatabaseConnection; type?: KVType; mapValue?: KVMapper; + prefix?: string; + prefixSeparator?: string; } export type KVPeerSetValueOptions = Omit< @@ -47,13 +49,17 @@ export class KVPeer; protected adapter: DatabaseConnection; + protected prefix: string; + protected prefixSeparator: string; constructor(options: KVOptions) { super(); - const { type, mapValue, adapter } = options; + const { type, mapValue, adapter, prefix = "", prefixSeparator = "-" } = options; this.adapter = adapter; + this.prefix = prefix; + this.prefixSeparator = prefix.length ? prefixSeparator : ""; this.type = type ?? kDefaultKVType; this.mapValue = mapValue ?? this.defaultMapValue; @@ -63,7 +69,7 @@ export class KVPeer | null> { - const result = await this.adapter.getValue(key, this.type); + const result = await this.adapter.getValue(this.keyWithPrefix(key), this.type); return result === null ? null : this.mapValue(result as T); } async deleteValue(key: KeyType): Promise { - return this.adapter.deleteValue(key); + return this.adapter.deleteValue(this.keyWithPrefix(key)); } private defaultMapValue(value: T): MappedValue { return value as MappedValue; } + + protected keyWithPrefix(key: KeyType) { + return `${this.prefix}${this.prefixSeparator}${key}`; + } } diff --git a/test/class/KVPeer.spec.ts b/test/class/KVPeer.spec.ts index 149929f..a2204de 100644 --- a/test/class/KVPeer.spec.ts +++ b/test/class/KVPeer.spec.ts @@ -205,6 +205,43 @@ describe("KVPeer", () => { }); }); }); + + test("With prefix", async() => { + const kvPeer = new KVPeer({ + type: "raw", + adapter: redisAdapter, + prefix: "super-prefix" + }); + await kvPeer.setValue({ key: "super-key", value: "boo" }); + + const valueWithNoPrefix = await redisAdapter.getValue("super-key", "raw"); + assert.strictEqual(valueWithNoPrefix, null); + + const valueWithPrefix = await redisAdapter.getValue("super-prefix-super-key", "raw"); + assert.strictEqual(valueWithPrefix, "boo"); + + const valueFromKVPeer = await kvPeer.getValue("super-key"); + assert.strictEqual(valueFromKVPeer, "boo"); + }); + + test("With prefix and prefixSeparator", async() => { + const kvPeer = new KVPeer({ + type: "raw", + adapter: redisAdapter, + prefix: "super-prefix", + prefixSeparator: ":::" + }); + await kvPeer.setValue({ key: "super-key", value: "boo" }); + + const valueWithNoPrefix = await redisAdapter.getValue("super-key", "raw"); + assert.strictEqual(valueWithNoPrefix, null); + + const valueWithPrefix = await redisAdapter.getValue("super-prefix:::super-key", "raw"); + assert.strictEqual(valueWithPrefix, "boo"); + + const valueFromKVPeer = await kvPeer.getValue("super-key"); + assert.strictEqual(valueFromKVPeer, "boo"); + }); }); describe("MemoryAdapter", () => {