@probitas/client-deno-kv
Deno KV client for Probitas scenario testing framework.
This package provides a Deno KV client designed for integration testing of applications using Deno KV storage.
Features
- Key-Value Operations: get, set, delete with structured keys
- Listing: Iterate over keys by prefix, start, end
- Atomic Transactions: Atomic operations with version checking
- Type Safety: Generic type parameters for stored values
- Resource Management: Implements
AsyncDisposablefor proper cleanup
Installation
deno add jsr:@probitas/client-deno-kv
Quick Start
import { createDenoKvClient } from "@probitas/client-deno-kv";
const kv = await createDenoKvClient();
// Set a value
const setResult = await kv.set(["users", "1"], { name: "Alice", age: 30 });
console.log("Versionstamp:", setResult.versionstamp);
// Get a value with type
const getResult = await kv.get<{ name: string; age: number }>(["users", "1"]);
console.log("User:", getResult.value);
// List entries by prefix
const listResult = await kv.list<{ name: string }>({ prefix: ["users"] });
console.log("Entries:", listResult.entries);
await kv.close();
Atomic Operations
import { createDenoKvClient } from "@probitas/client-deno-kv";
const kv = await createDenoKvClient();
// Atomic transaction with version check
const atomic = kv.atomic();
atomic.check({ key: ["counter"], versionstamp: null }); // Only if key doesn't exist
atomic.set(["counter"], 1n);
await atomic.commit();
// Atomic increment
const current = await kv.get<bigint>(["counter"]);
const atomic2 = kv.atomic();
atomic2.check({ key: ["counter"], versionstamp: current.versionstamp });
atomic2.set(["counter"], (current.value ?? 0n) + 1n);
await atomic2.commit();
await kv.close();
Using with using Statement
import { createDenoKvClient } from "@probitas/client-deno-kv";
await using kv = await createDenoKvClient();
await kv.set(["test"], "value");
const result = await kv.get(["test"]);
console.log(result.value);
// Client automatically closed when block exits
Related Packages
| Package | Description |
|---|---|
| `@probitas/client` | Core utilities and types |
| `@probitas/client-redis` | Redis client |
Links
Installation
deno add jsr:@probitas/client-deno-kvClasses
#DenoKvAtomicBuilderImpl
class DenoKvAtomicBuilderImpl implements DenoKvAtomicBuilderDenoKvAtomicBuilderImplementation of DenoKvAtomicBuilder.
Constructor
new DenoKvAtomicBuilderImpl(kv: Deno.Kv, options?: AtomicBuilderOptions)Methods
check(): unknownset(): unknowndelete(): unknownsum(): unknownmin(): unknownmax(): unknowncommit(): unknown#DenoKvConnectionError
class DenoKvConnectionError extends DenoKvErrorDenoKvErrorError thrown when a connection to Deno KV fails.
This typically occurs when:
- Network errors prevent reaching Deno Deploy KV
- Authentication/authorization fails
- Service is unavailable
Constructor
new DenoKvConnectionError(message: string, options?: ErrorOptions)Properties
- readonly
namestring - readonly
kind"connection"
#DenoKvError
class DenoKvError extends ClientErrorClientErrorBase error class for Deno KV operations.
Use the kind property to distinguish between error types:
"kv": General KV operation error"quota": Quota limit exceeded"connection": Network/connection failure
| Name | Description |
|---|---|
name | — |
Constructor
new DenoKvError(message: string, _: unknown, options?: ErrorOptions)Properties
- readonly
namestring
Interfaces
#AtomicBuilderOptions
interface AtomicBuilderOptionsOptions for atomic operations.
| Name | Description |
|---|---|
throwOnError | Whether to throw errors instead of returning them in the result. |
Properties
- readonly
throwOnError?booleanWhether to throw errors instead of returning them in the result.
#DenoKvAtomicBuilder
interface DenoKvAtomicBuilderBuilder for atomic KV operations.
| Name | Description |
|---|---|
check() | Add version checks to the atomic operation. |
set() | Set a value in the KV store. |
delete() | Delete a key from the KV store. |
sum() | Atomically add to a bigint value (Deno.KvU64). |
min() | Atomically set to minimum of current and provided value. |
max() | Atomically set to maximum of current and provided value. |
commit() | Commit the atomic operation. |
Methods
check(_: Deno.AtomicCheck[]): thisAdd version checks to the atomic operation. If any check fails, the entire operation will fail.
Parameters
_Deno.AtomicCheck[]
set<T = any>(key: Deno.KvKey, value: T, options?: { expireIn?: number }): thisSet a value in the KV store.
Parameters
keyDeno.KvKeyvalueToptions?{ expireIn?: number }
delete(key: Deno.KvKey): thisDelete a key from the KV store.
Parameters
keyDeno.KvKey
sum(key: Deno.KvKey, n: bigint): thisAtomically add to a bigint value (Deno.KvU64).
Parameters
keyDeno.KvKeynbigint
min(key: Deno.KvKey, n: bigint): thisAtomically set to minimum of current and provided value.
Parameters
keyDeno.KvKeynbigint
max(key: Deno.KvKey, n: bigint): thisAtomically set to maximum of current and provided value.
Parameters
keyDeno.KvKeynbigint
commit(): Promise<DenoKvAtomicResult>Commit the atomic operation.
#DenoKvAtomicOptions
interface DenoKvAtomicOptions extends DenoKvOptionsOptions for atomic operations.
#DenoKvAtomicResultCheckFailed
interface DenoKvAtomicResultCheckFailed extends DenoKvAtomicResultBaseAtomic operation check failed (version mismatch).
This is NOT an error - it's an expected outcome when using optimistic concurrency. Retry the operation with updated versionstamps.
| Name | Description |
|---|---|
processed | — |
ok | — |
error | — |
versionstamp | — |
Properties
- readonly
processedtrue - readonly
okfalse - readonly
errornull - readonly
versionstampnull
#DenoKvAtomicResultCommitted
interface DenoKvAtomicResultCommitted extends DenoKvAtomicResultBaseAtomic operation successfully committed.
| Name | Description |
|---|---|
processed | — |
ok | — |
error | — |
versionstamp | — |
Properties
- readonly
processedtrue - readonly
oktrue - readonly
errornull - readonly
versionstampstring
#DenoKvAtomicResultError
interface DenoKvAtomicResultError extends DenoKvAtomicResultBaseAtomic operation failed with KV error.
| Name | Description |
|---|---|
processed | — |
ok | — |
error | — |
versionstamp | — |
Properties
- readonly
processedtrue - readonly
okfalse - readonly
versionstampnull
#DenoKvAtomicResultFailure
interface DenoKvAtomicResultFailure extends DenoKvAtomicResultBaseAtomic operation failed with connection error.
| Name | Description |
|---|---|
processed | — |
ok | — |
error | — |
versionstamp | — |
Properties
- readonly
processedfalse - readonly
okfalse - readonly
versionstampnull
#DenoKvClient
interface DenoKvClient extends AsyncDisposableDeno KV client for Probitas scenario testing.
| Name | Description |
|---|---|
config | Client configuration. |
get() | Get a single value by key. |
getMany() | Get multiple values by keys. |
set() | Set a value. |
delete() | Delete a key. |
list() | List entries by selector. |
atomic() | Create an atomic operation builder. |
close() | Close the KV connection. |
Properties
Client configuration.
Methods
get<T = any>(
key: Deno.KvKey,
options?: DenoKvGetOptions,
): Promise<DenoKvGetResult<T>>Get a single value by key.
Parameters
keyDeno.KvKeyoptions?DenoKvGetOptions
getMany<T extends readonly any[]>(
keys: readonly [unknown],
options?: DenoKvGetOptions,
): Promise<unknown>Get multiple values by keys.
Parameters
keysreadonly [unknown]options?DenoKvGetOptions
set<T = any>(
key: Deno.KvKey,
value: T,
options?: DenoKvSetOptions,
): Promise<DenoKvSetResult>Set a value.
Parameters
keyDeno.KvKeyvalueToptions?DenoKvSetOptions
delete(
key: Deno.KvKey,
options?: DenoKvDeleteOptions,
): Promise<DenoKvDeleteResult>Delete a key.
Parameters
keyDeno.KvKeyoptions?DenoKvDeleteOptions
list<T = any>(
selector: Deno.KvListSelector,
options?: DenoKvListOptions,
): Promise<DenoKvListResult<T>>List entries by selector.
Parameters
selectorDeno.KvListSelectoroptions?DenoKvListOptions
atomic(options?: DenoKvAtomicOptions): DenoKvAtomicBuilderCreate an atomic operation builder.
Parameters
options?DenoKvAtomicOptions
close(): Promise<void>Close the KV connection.
#DenoKvClientConfig
interface DenoKvClientConfig extends DenoKvOptionsConfiguration for DenoKvClient.
| Name | Description |
|---|---|
path | Path to the KV database file. |
Properties
- readonly
path?stringPath to the KV database file. If not specified, uses in-memory storage or Deno Deploy's KV.
#DenoKvDeleteOptions
interface DenoKvDeleteOptions extends DenoKvOptionsOptions for delete operations.
#DenoKvDeleteResultError
interface DenoKvDeleteResultError extends DenoKvDeleteResultBaseDelete operation result with KV error.
Properties
- readonly
processedtrue - readonly
okfalse
#DenoKvDeleteResultFailure
interface DenoKvDeleteResultFailure extends DenoKvDeleteResultBaseDelete operation result with connection failure.
Properties
- readonly
processedfalse - readonly
okfalse
#DenoKvDeleteResultSuccess
interface DenoKvDeleteResultSuccess extends DenoKvDeleteResultBaseSuccessful delete operation result.
Properties
- readonly
processedtrue - readonly
oktrue - readonly
errornull
#DenoKvEntry
interface DenoKvEntry<T = any>A single entry in the KV store.
| Name | Description |
|---|---|
key | — |
value | — |
versionstamp | — |
Properties
- readonly
keyDeno.KvKey - readonly
valueT - readonly
versionstampstring
#DenoKvGetOptions
interface DenoKvGetOptions extends DenoKvOptionsOptions for get operations.
#DenoKvGetResultError
interface DenoKvGetResultError<T = any> extends DenoKvGetResultBase<T>Get operation result with KV error (quota exceeded, etc.).
Properties
- readonly
processedtrue - readonly
okfalse - readonly
keyDeno.KvKey - readonly
valuenull - readonly
versionstampnull
#DenoKvGetResultFailure
interface DenoKvGetResultFailure<T = any> extends DenoKvGetResultBase<T>Get operation result with connection failure.
Properties
- readonly
processedfalse - readonly
okfalse - readonly
keynull - readonly
valuenull - readonly
versionstampnull
#DenoKvGetResultSuccess
interface DenoKvGetResultSuccess<T = any> extends DenoKvGetResultBase<T>Successful get operation result.
Properties
- readonly
processedtrue - readonly
oktrue - readonly
errornull - readonly
keyDeno.KvKey - readonly
valueT | null - readonly
versionstampstring | null
#DenoKvListOptions
interface DenoKvListOptions extends DenoKvOptionsOptions for list operations.
| Name | Description |
|---|---|
limit | Maximum number of entries to return. |
cursor | Cursor for pagination. |
reverse | Whether to iterate in reverse order. |
Properties
- readonly
limit?numberMaximum number of entries to return.
- readonly
cursor?stringCursor for pagination.
- readonly
reverse?booleanWhether to iterate in reverse order.
#DenoKvListResultError
interface DenoKvListResultError<T = any> extends DenoKvListResultBase<T>List operation result with KV error.
Properties
- readonly
processedtrue - readonly
okfalse
#DenoKvListResultFailure
interface DenoKvListResultFailure<T = any> extends DenoKvListResultBase<T>List operation result with connection failure.
Properties
- readonly
processedfalse - readonly
okfalse
#DenoKvListResultSuccess
interface DenoKvListResultSuccess<T = any> extends DenoKvListResultBase<T>Successful list operation result.
Properties
- readonly
processedtrue - readonly
oktrue - readonly
errornull
#DenoKvOptions
interface DenoKvOptions extends CommonOptionsOptions for Deno KV operations.
Extends CommonOptions with error handling behavior configuration.
| Name | Description |
|---|---|
throwOnError | Whether to throw errors instead of returning them in the result. |
Properties
- readonly
throwOnError?booleanWhether to throw errors instead of returning them in the result.
false(default): Errors are returned in the result'serrorpropertytrue: Errors are thrown as exceptions
This applies to both KV errors (quota exceeded, etc.) and connection errors. Note: Atomic check failures are NOT errors and will never be thrown.
#DenoKvSetOptions
interface DenoKvSetOptions extends DenoKvOptionsOptions for set operations.
| Name | Description |
|---|---|
expireIn | Time-to-live in milliseconds. |
Properties
- readonly
expireIn?numberTime-to-live in milliseconds. The entry will automatically expire after this duration.
#DenoKvSetResultError
interface DenoKvSetResultError extends DenoKvSetResultBaseSet operation result with KV error (quota exceeded, etc.).
| Name | Description |
|---|---|
processed | — |
ok | — |
error | — |
versionstamp | — |
Properties
- readonly
processedtrue - readonly
okfalse - readonly
versionstampnull
#DenoKvSetResultFailure
interface DenoKvSetResultFailure extends DenoKvSetResultBaseSet operation result with connection failure.
| Name | Description |
|---|---|
processed | — |
ok | — |
error | — |
versionstamp | — |
Properties
- readonly
processedfalse - readonly
okfalse - readonly
versionstampnull
#DenoKvSetResultSuccess
interface DenoKvSetResultSuccess extends DenoKvSetResultBaseSuccessful set operation result.
| Name | Description |
|---|---|
processed | — |
ok | — |
error | — |
versionstamp | — |
Properties
- readonly
processedtrue - readonly
oktrue - readonly
errornull - readonly
versionstampstring
Functions
#createDenoKvClient
async function createDenoKvClient(
config?: DenoKvClientConfig,
): Promise<DenoKvClient>Create a new Deno KV client instance.
The client provides key-value operations with support for atomic transactions, time-to-live (TTL), and prefix-based listing.
Parameters
config?DenoKvClientConfig- Deno KV client configuration (optional)
Returns
Promise<DenoKvClient> — A promise resolving to a new Deno KV client instance
Examples
Basic usage with in-memory database
import { createDenoKvClient } from "@probitas/client-deno-kv";
interface User {
name: string;
email: string;
}
const kv = await createDenoKvClient();
await kv.set(["users", "123"], { name: "Alice", email: "alice@example.com" });
const result = await kv.get<User>(["users", "123"]);
if (result.ok) {
console.log(result.value); // { name: "Alice", email: "alice@example.com" }
}
await kv.close();
Using persistent storage
import { createDenoKvClient } from "@probitas/client-deno-kv";
const kv = await createDenoKvClient({
path: "./data.kv",
});
await kv.close();
Set with expiration (TTL)
import { createDenoKvClient } from "@probitas/client-deno-kv";
const kv = await createDenoKvClient();
const sessionId = "abc123";
const sessionData = { userId: "123", token: "xyz" };
await kv.set(["sessions", sessionId], sessionData, {
expireIn: 3600_000, // Expire in 1 hour
});
await kv.close();
List entries by prefix
import { createDenoKvClient } from "@probitas/client-deno-kv";
interface User {
name: string;
email: string;
}
const kv = await createDenoKvClient();
const result = await kv.list<User>({ prefix: ["users"] });
if (result.ok) {
for (const entry of result.entries) {
console.log(entry.key, entry.value);
}
}
await kv.close();
Atomic transactions
import { createDenoKvClient } from "@probitas/client-deno-kv";
const kv = await createDenoKvClient();
const atomicResult = await kv.atomic()
.check({ key: ["counter"], versionstamp: null })
.set(["counter"], 1)
.commit();
await kv.close();
Using await using for automatic cleanup
import { createDenoKvClient } from "@probitas/client-deno-kv";
await using kv = await createDenoKvClient();
await kv.set(["test"], "value");
// Client automatically closed when scope exits
Error handling with Failure pattern
import { createDenoKvClient } from "@probitas/client-deno-kv";
async function example() {
const kv = await createDenoKvClient();
const result = await kv.get<string>(["key"]);
if (!result.ok) {
if (!result.processed) {
// Connection failure
console.error("Connection failed:", result.error.message);
} else {
// KV error (quota exceeded, etc.)
console.error("KV error:", result.error.message);
}
await kv.close();
return;
}
console.log("Value:", result.value);
await kv.close();
}
Using throwOnError for traditional exception handling
import { createDenoKvClient, DenoKvError } from "@probitas/client-deno-kv";
const kv = await createDenoKvClient({ throwOnError: true });
try {
const result = await kv.get<string>(["key"]);
console.log("Value:", result.value);
} catch (error) {
if (error instanceof DenoKvError) {
console.error("KV error:", error.message);
}
}
await kv.close();
Types
#DenoKvAtomicResult
type DenoKvAtomicResult = DenoKvAtomicResultCommitted
| DenoKvAtomicResultCheckFailed
| DenoKvAtomicResultError
| DenoKvAtomicResultFailureResult of an atomic operation.
Use ok and error to distinguish between outcomes:
ok === true: Committed successfullyok === false && error === null: Check failed (retry with new versionstamp)ok === false && error !== null: KV error or connection failure
#DenoKvDeleteResult
type DenoKvDeleteResult = DenoKvDeleteResultSuccess | DenoKvDeleteResultError | DenoKvDeleteResultFailureResult of a delete operation.
#DenoKvFailureError
type DenoKvFailureError = DenoKvConnectionError | AbortError | TimeoutErrorError types that indicate the operation was not processed. These are errors that occur before the operation reaches the Deno KV server.
#DenoKvGetResult
type DenoKvGetResult<T = any> = DenoKvGetResultSuccess<T> | DenoKvGetResultError<T> | DenoKvGetResultFailure<T>Result of a get operation.
Use ok to check for success, then narrow the type:
ok === true: Success - value may be presentok === false && processed === true: KV error (quota, etc.)ok === false && processed === false: Connection failure
#DenoKvListResult
type DenoKvListResult<T = any> = DenoKvListResultSuccess<T>
| DenoKvListResultError<T>
| DenoKvListResultFailure<T>Result of a list operation.
#DenoKvResult
type DenoKvResult<T = any> = DenoKvGetResult<T>
| DenoKvSetResult
| DenoKvDeleteResult
| DenoKvListResult<T>
| DenoKvAtomicResultUnion of all Deno KV result types.
#DenoKvSetResult
type DenoKvSetResult = DenoKvSetResultSuccess | DenoKvSetResultError | DenoKvSetResultFailureResult of a set operation.
