@unikvs/key-prefix
Middleware that prepends a fixed string to every key, enabling tenant isolation.
Overview
KeyPrefix prepends a fixed string to every key, enabling tenant isolation.Middleware
Use it to share one storage across tenants without key collisions. By prefixing physical keys, this middleware separates logical keys.
nameisKeyPrefix.isOpenis alwaystrue.mapKeyprefixes keys, anduserejectsclearwhen range-scoped deletion cannot be guaranteed.encode/decode/encodeStream/decodeStreampass data through.
Install with:
npm install @unikvs/key-prefixpnpm add @unikvs/key-prefixyarn add @unikvs/key-prefixbun add @unikvs/key-prefixnub add @unikvs/key-prefixaube add @unikvs/key-prefixUsage
KeyPrefix implements IMiddleware. Pass it to UniKvs with use().
import { KeyPrefix } from "@unikvs/key-prefix";
Constructor arguments:
prefixstring
Fixed string prepended to every key. An empty string passes keys through.
stringallowClear?boolean
Whether to reject clear when the prefix is non-empty. True rejects; false (default) passes through.
booleanfalseThe following isolates keys per tenant:
import { KeyPrefix } from "@unikvs/key-prefix";
import { Memory } from "@unikvs/memory";
import * as unikvs from "unikvs";
const kvs = new unikvs.Builder<{ k1: unikvs.PlainValue<string> }>()
.use(new KeyPrefix("tenant-a:"))
.persist(new Memory())
.build();
await kvs.open();
await kvs.set("k1", "hello");
console.log(await kvs.get("k1")); // "hello"
// Stored downstream as tenant-a:k1
await kvs.close();
KeyPrefix
Middleware that prepends a fixed prefix to keys. It extends PassThrough and performs no data conversion.
KeyPrefixOptions
Options accepted by the KeyPrefix constructor. allowClear defaults to false.
Data types
| Method | Input | Output |
|---|---|---|
encode |
any |
any |
decode |
any |
any |
encodeStream |
any |
any |
decodeStream |
any |
any |
encodeanddecodereturn the input by reference without conversion.encodeStreamanddecodeStreampass chunks through, preserving order and references.- Key mapping happens in
mapKey, returning`${prefix}${key}`. An empty prefix returns the key unchanged.
Errors
Errors thrown by this package:
KeyPrefixClearDeniedError
prefixstring
The prefix at rejection time.
stringallowClearboolean
The allowClear value at rejection time.
booleanMeaning
Thrown when clear is called while the prefix is non-empty and allowClear is true. Prefixed clear cannot guarantee range-scoped deletion and might delete other tenants’ data, so it is rejected.
How to fix
In shared environments, use per-key delete instead of clear. When a single tenant is guaranteed exclusive, or whole-store deletion is intended, set allowClear to false (default) to pass through.
Example
Catching KeyPrefixClearDeniedError:
import { KeyPrefix, KeyPrefixClearDeniedError } from "@unikvs/key-prefix";
const prefix = new KeyPrefix("tenant-a:", { allowClear: true });
try {
await kvs.clear();
} catch (ex) {
if (ex instanceof KeyPrefixClearDeniedError) {
console.log(ex.meta); // { prefix: "tenant-a:", allowClear: true }
} else {
throw ex;
}
}