# @probitas/client-deno-kv > Version: 0.5.0 Deno KV client for [Probitas](https://github.com/probitas-test/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 `AsyncDisposable` for proper cleanup ## Installation ```bash deno add jsr:@probitas/client-deno-kv ``` ## Quick Start ```ts 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 ```ts 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(["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 ```ts 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`](https://jsr.io/@probitas/client) | Core utilities and types | | [`@probitas/client-redis`](https://jsr.io/@probitas/client-redis) | Redis client | ## Links - [GitHub Repository](https://github.com/probitas-test/probitas-client) - [Probitas Framework](https://github.com/probitas-test/probitas) - [Deno KV](https://deno.land/manual/runtime/kv) ## Classes ### `DenoKvError` ```typescript class DenoKvError extends ClientError ``` Base 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 **Constructor:** ```typescript new DenoKvError(message: string, _: unknown, options?: ErrorOptions) ``` **Properties:** - [readonly] `name`: `string` --- ### `DenoKvConnectionError` ```typescript class DenoKvConnectionError extends DenoKvError ``` Error 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:** ```typescript new DenoKvConnectionError(message: string, options?: ErrorOptions) ``` **Properties:** - [readonly] `name`: `string` - [readonly] `kind`: `"connection"` --- ### `DenoKvAtomicBuilderImpl` ```typescript class DenoKvAtomicBuilderImpl implements DenoKvAtomicBuilder ``` Implementation of DenoKvAtomicBuilder. **Constructor:** ```typescript new DenoKvAtomicBuilderImpl(kv: Deno.Kv, options?: AtomicBuilderOptions) ``` **Methods:** ```typescript check(): unknown ``` ```typescript set(): unknown ``` ```typescript delete(): unknown ``` ```typescript sum(): unknown ``` ```typescript min(): unknown ``` ```typescript max(): unknown ``` ```typescript commit(): unknown ``` --- ## Interfaces ### `DenoKvOptions` ```typescript interface DenoKvOptions extends CommonOptions ``` Options for Deno KV operations. Extends CommonOptions with error handling behavior configuration. **Properties:** - [readonly] `throwOnError?`: `boolean` — Whether to throw errors instead of returning them in the result. - `false` (default): Errors are returned in the result's `error` property - `true`: 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. --- ### `DenoKvClientConfig` ```typescript interface DenoKvClientConfig extends DenoKvOptions ``` Configuration for DenoKvClient. **Properties:** - [readonly] `path?`: `string` — Path to the KV database file. If not specified, uses in-memory storage or Deno Deploy's KV. --- ### `DenoKvGetOptions` ```typescript interface DenoKvGetOptions extends DenoKvOptions ``` Options for get operations. --- ### `DenoKvSetOptions` ```typescript interface DenoKvSetOptions extends DenoKvOptions ``` Options for set operations. **Properties:** - [readonly] `expireIn?`: `number` — Time-to-live in milliseconds. The entry will automatically expire after this duration. --- ### `DenoKvDeleteOptions` ```typescript interface DenoKvDeleteOptions extends DenoKvOptions ``` Options for delete operations. --- ### `DenoKvListOptions` ```typescript interface DenoKvListOptions extends DenoKvOptions ``` Options for list operations. **Properties:** - [readonly] `limit?`: `number` — Maximum number of entries to return. - [readonly] `cursor?`: `string` — Cursor for pagination. - [readonly] `reverse?`: `boolean` — Whether to iterate in reverse order. --- ### `DenoKvAtomicOptions` ```typescript interface DenoKvAtomicOptions extends DenoKvOptions ``` Options for atomic operations. --- ### `DenoKvGetResultSuccess` ```typescript interface DenoKvGetResultSuccess extends DenoKvGetResultBase ``` Successful get operation result. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `true` - [readonly] `error`: `null` - [readonly] `key`: `Deno.KvKey` - [readonly] `value`: `T | null` - [readonly] `versionstamp`: `string | null` --- ### `DenoKvGetResultError` ```typescript interface DenoKvGetResultError extends DenoKvGetResultBase ``` Get operation result with KV error (quota exceeded, etc.). **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvError` - [readonly] `key`: `Deno.KvKey` - [readonly] `value`: `null` - [readonly] `versionstamp`: `null` --- ### `DenoKvGetResultFailure` ```typescript interface DenoKvGetResultFailure extends DenoKvGetResultBase ``` Get operation result with connection failure. **Properties:** - [readonly] `processed`: `false` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvFailureError` - [readonly] `key`: `null` - [readonly] `value`: `null` - [readonly] `versionstamp`: `null` --- ### `DenoKvSetResultSuccess` ```typescript interface DenoKvSetResultSuccess extends DenoKvSetResultBase ``` Successful set operation result. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `true` - [readonly] `error`: `null` - [readonly] `versionstamp`: `string` --- ### `DenoKvSetResultError` ```typescript interface DenoKvSetResultError extends DenoKvSetResultBase ``` Set operation result with KV error (quota exceeded, etc.). **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvError` - [readonly] `versionstamp`: `null` --- ### `DenoKvSetResultFailure` ```typescript interface DenoKvSetResultFailure extends DenoKvSetResultBase ``` Set operation result with connection failure. **Properties:** - [readonly] `processed`: `false` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvFailureError` - [readonly] `versionstamp`: `null` --- ### `DenoKvDeleteResultSuccess` ```typescript interface DenoKvDeleteResultSuccess extends DenoKvDeleteResultBase ``` Successful delete operation result. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `true` - [readonly] `error`: `null` --- ### `DenoKvDeleteResultError` ```typescript interface DenoKvDeleteResultError extends DenoKvDeleteResultBase ``` Delete operation result with KV error. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvError` --- ### `DenoKvDeleteResultFailure` ```typescript interface DenoKvDeleteResultFailure extends DenoKvDeleteResultBase ``` Delete operation result with connection failure. **Properties:** - [readonly] `processed`: `false` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvFailureError` --- ### `DenoKvEntry` ```typescript interface DenoKvEntry ``` A single entry in the KV store. **Properties:** - [readonly] `key`: `Deno.KvKey` - [readonly] `value`: `T` - [readonly] `versionstamp`: `string` --- ### `DenoKvListResultSuccess` ```typescript interface DenoKvListResultSuccess extends DenoKvListResultBase ``` Successful list operation result. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `true` - [readonly] `error`: `null` - [readonly] `entries`: `readonly DenoKvEntry[]` --- ### `DenoKvListResultError` ```typescript interface DenoKvListResultError extends DenoKvListResultBase ``` List operation result with KV error. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvError` - [readonly] `entries`: `readonly DenoKvEntry[]` --- ### `DenoKvListResultFailure` ```typescript interface DenoKvListResultFailure extends DenoKvListResultBase ``` List operation result with connection failure. **Properties:** - [readonly] `processed`: `false` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvFailureError` - [readonly] `entries`: `readonly DenoKvEntry[]` --- ### `DenoKvAtomicResultCommitted` ```typescript interface DenoKvAtomicResultCommitted extends DenoKvAtomicResultBase ``` Atomic operation successfully committed. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `true` - [readonly] `error`: `null` - [readonly] `versionstamp`: `string` --- ### `DenoKvAtomicResultCheckFailed` ```typescript interface DenoKvAtomicResultCheckFailed extends DenoKvAtomicResultBase ``` Atomic 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. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `false` - [readonly] `error`: `null` - [readonly] `versionstamp`: `null` --- ### `DenoKvAtomicResultError` ```typescript interface DenoKvAtomicResultError extends DenoKvAtomicResultBase ``` Atomic operation failed with KV error. **Properties:** - [readonly] `processed`: `true` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvError` - [readonly] `versionstamp`: `null` --- ### `DenoKvAtomicResultFailure` ```typescript interface DenoKvAtomicResultFailure extends DenoKvAtomicResultBase ``` Atomic operation failed with connection error. **Properties:** - [readonly] `processed`: `false` - [readonly] `ok`: `false` - [readonly] `error`: `DenoKvFailureError` - [readonly] `versionstamp`: `null` --- ### `AtomicBuilderOptions` ```typescript interface AtomicBuilderOptions ``` Options for atomic operations. **Properties:** - [readonly] `throwOnError?`: `boolean` — Whether to throw errors instead of returning them in the result. --- ### `DenoKvAtomicBuilder` ```typescript interface DenoKvAtomicBuilder ``` Builder for atomic KV operations. **Methods:** ```typescript check(_: Deno.AtomicCheck[]): this ``` Add version checks to the atomic operation. If any check fails, the entire operation will fail. ```typescript set(key: Deno.KvKey, value: T, options?: { expireIn?: number }): this ``` Set a value in the KV store. ```typescript delete(key: Deno.KvKey): this ``` Delete a key from the KV store. ```typescript sum(key: Deno.KvKey, n: bigint): this ``` Atomically add to a bigint value (Deno.KvU64). ```typescript min(key: Deno.KvKey, n: bigint): this ``` Atomically set to minimum of current and provided value. ```typescript max(key: Deno.KvKey, n: bigint): this ``` Atomically set to maximum of current and provided value. ```typescript commit(): Promise ``` Commit the atomic operation. --- ### `DenoKvClient` ```typescript interface DenoKvClient extends AsyncDisposable ``` Deno KV client for Probitas scenario testing. **Properties:** - [readonly] `config`: `DenoKvClientConfig` — Client configuration. **Methods:** ```typescript get( key: Deno.KvKey, options?: DenoKvGetOptions, ): Promise> ``` Get a single value by key. ```typescript getMany( keys: readonly [unknown], options?: DenoKvGetOptions, ): Promise ``` Get multiple values by keys. ```typescript set( key: Deno.KvKey, value: T, options?: DenoKvSetOptions, ): Promise ``` Set a value. ```typescript delete( key: Deno.KvKey, options?: DenoKvDeleteOptions, ): Promise ``` Delete a key. ```typescript list( selector: Deno.KvListSelector, options?: DenoKvListOptions, ): Promise> ``` List entries by selector. ```typescript atomic(options?: DenoKvAtomicOptions): DenoKvAtomicBuilder ``` Create an atomic operation builder. ```typescript close(): Promise ``` Close the KV connection. --- ## Functions ### `createDenoKvClient` ```typescript async function createDenoKvClient( config?: DenoKvClientConfig, ): Promise ``` 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` (optional) — - Deno KV client configuration (optional) **Returns:** `Promise` A promise resolving to a new Deno KV client instance **Example:** Basic usage with in-memory database ```ts 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(["users", "123"]); if (result.ok) { console.log(result.value); // { name: "Alice", email: "alice@example.com" } } await kv.close(); ``` Using persistent storage ```ts import { createDenoKvClient } from "@probitas/client-deno-kv"; const kv = await createDenoKvClient({ path: "./data.kv", }); await kv.close(); ``` Set with expiration (TTL) ```ts 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 ```ts import { createDenoKvClient } from "@probitas/client-deno-kv"; interface User { name: string; email: string; } const kv = await createDenoKvClient(); const result = await kv.list({ prefix: ["users"] }); if (result.ok) { for (const entry of result.entries) { console.log(entry.key, entry.value); } } await kv.close(); ``` Atomic transactions ```ts 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 ```ts 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 ```ts import { createDenoKvClient } from "@probitas/client-deno-kv"; async function example() { const kv = await createDenoKvClient(); const result = await kv.get(["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 ```ts import { createDenoKvClient, DenoKvError } from "@probitas/client-deno-kv"; const kv = await createDenoKvClient({ throwOnError: true }); try { const result = await kv.get(["key"]); console.log("Value:", result.value); } catch (error) { if (error instanceof DenoKvError) { console.error("KV error:", error.message); } } await kv.close(); ``` --- ## Types ### `DenoKvFailureError` ```typescript type DenoKvFailureError = DenoKvConnectionError | AbortError | TimeoutError ``` Error types that indicate the operation was not processed. These are errors that occur before the operation reaches the Deno KV server. --- ### `DenoKvGetResult` ```typescript type DenoKvGetResult = DenoKvGetResultSuccess | DenoKvGetResultError | DenoKvGetResultFailure ``` Result of a get operation. Use `ok` to check for success, then narrow the type: - `ok === true`: Success - value may be present - `ok === false && processed === true`: KV error (quota, etc.) - `ok === false && processed === false`: Connection failure --- ### `DenoKvSetResult` ```typescript type DenoKvSetResult = DenoKvSetResultSuccess | DenoKvSetResultError | DenoKvSetResultFailure ``` Result of a set operation. --- ### `DenoKvDeleteResult` ```typescript type DenoKvDeleteResult = DenoKvDeleteResultSuccess | DenoKvDeleteResultError | DenoKvDeleteResultFailure ``` Result of a delete operation. --- ### `DenoKvListResult` ```typescript type DenoKvListResult = DenoKvListResultSuccess | DenoKvListResultError | DenoKvListResultFailure ``` Result of a list operation. --- ### `DenoKvAtomicResult` ```typescript type DenoKvAtomicResult = DenoKvAtomicResultCommitted | DenoKvAtomicResultCheckFailed | DenoKvAtomicResultError | DenoKvAtomicResultFailure ``` Result of an atomic operation. Use `ok` and `error` to distinguish between outcomes: - `ok === true`: Committed successfully - `ok === false && error === null`: Check failed (retry with new versionstamp) - `ok === false && error !== null`: KV error or connection failure --- ### `DenoKvResult` ```typescript type DenoKvResult = DenoKvGetResult | DenoKvSetResult | DenoKvDeleteResult | DenoKvListResult | DenoKvAtomicResult ``` Union of all Deno KV result types. --- ## Related Links ### This Package - [`AtomicBuilderOptions`](https://probitas-test.github.io/documents/api/client-deno-kv#AtomicBuilderOptions) - [`DenoKvAtomicBuilder`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvAtomicBuilder) - [`DenoKvAtomicOptions`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvAtomicOptions) - [`DenoKvAtomicResult`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvAtomicResult) - [`DenoKvAtomicResultCheckFailed`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvAtomicResultCheckFailed) - [`DenoKvAtomicResultCommitted`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvAtomicResultCommitted) - [`DenoKvAtomicResultError`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvAtomicResultError) - [`DenoKvAtomicResultFailure`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvAtomicResultFailure) - [`DenoKvClient`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvClient) - [`DenoKvClientConfig`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvClientConfig) - [`DenoKvConnectionError`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvConnectionError) - [`DenoKvDeleteOptions`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvDeleteOptions) - [`DenoKvDeleteResult`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvDeleteResult) - [`DenoKvDeleteResultError`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvDeleteResultError) - [`DenoKvDeleteResultFailure`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvDeleteResultFailure) - [`DenoKvDeleteResultSuccess`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvDeleteResultSuccess) - [`DenoKvEntry`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvEntry) - [`DenoKvError`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvError) - [`DenoKvFailureError`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvFailureError) - [`DenoKvGetOptions`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvGetOptions) - [`DenoKvGetResult`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvGetResult) - [`DenoKvGetResultError`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvGetResultError) - [`DenoKvGetResultFailure`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvGetResultFailure) - [`DenoKvGetResultSuccess`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvGetResultSuccess) - [`DenoKvListOptions`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvListOptions) - [`DenoKvListResult`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvListResult) - [`DenoKvListResultError`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvListResultError) - [`DenoKvListResultFailure`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvListResultFailure) - [`DenoKvListResultSuccess`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvListResultSuccess) - [`DenoKvOptions`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvOptions) - [`DenoKvSetOptions`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvSetOptions) - [`DenoKvSetResult`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvSetResult) - [`DenoKvSetResultError`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvSetResultError) - [`DenoKvSetResultFailure`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvSetResultFailure) - [`DenoKvSetResultSuccess`](https://probitas-test.github.io/documents/api/client-deno-kv#DenoKvSetResultSuccess) ### Other Packages - [`AbortError`](https://probitas-test.github.io/documents/api/client#AbortError) (@probitas/client) - [`CommonOptions`](https://probitas-test.github.io/documents/api/client#CommonOptions) (@probitas/client) - [`TimeoutError`](https://probitas-test.github.io/documents/api/client#TimeoutError) (@probitas/client) ### Built-in Types - [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) --- *Last updated: 2026-01-12*