import type { EntriesIterable, KVEntry, KVGetResult, KVLike, KVSetResult, KeysIterable, SetOptions } from "./types.js"; export interface IndexDef { /** Extract index key(s) from value. Return string for single-value, string[] for multi-value. */ key: (value: V, primaryKey: string) => string | string[]; /** Unique constraint. Default: false */ unique?: boolean; } /** * When I = never (no indexes), resolves to never — so `string | never` = `string`. * When I has values, resolves to a record of optional index keys. */ export type IndexQuery = [I] extends [never] ? never : { [K in I]?: string; }; /** * A typed sub-store that wraps any KVLike (KV2 or UpstreamKV) with a prefix. * * TypedKV implements KVLike, so it can be nested via getStore() to create * hierarchical key structures. * * Optionally supports secondary indexes: pass an `indexes` record to * `getStore()` or the constructor to auto-maintain index entries on set/delete. * * @typeParam V - Value type * @typeParam M - Metadata type (undefined = no metadata) * @typeParam I - Union of index names (never = no indexes) * * @example * ```ts * const kv = createKV({ prefix: "app/" }); * * // Sub-store with indexes * const usersKV = kv.getStore("users/", { * byEmail: { key: (u) => u.email, unique: true }, * byRole: { key: (u) => u.role }, * }); * * await usersKV.set("alice", { email: "a@b.com", role: "admin" }); * const user = await usersKV.get({ byEmail: "a@b.com" }); * for await (const key of usersKV.keys({ byRole: "admin" })) { ... } * ``` */ export declare class TypedKV implements KVLike { private parent; private prefix; private indexes?; private indexStores?; constructor(parent: KVLike, prefix: string, indexes?: Record>); private prefixKey; /** * Get by primary key or by unique index. * * @example * ```ts * // By primary key * const result = await store.get("page/123"); * * // By unique index * const result = await store.get({ bySlug: "hello-world" }); * ``` */ get(keyOrFilter: string | IndexQuery): Promise>; set(key: string, value: T | ReadableStream, ...[metadata, options]: undefined extends M ? [M?, SetOptions?] : [M, SetOptions?]): Promise; delete(key: string): Promise; /** * List keys by prefix or by index. * * @example * ```ts * // All keys * for await (const key of store.keys()) { ... } * * // By prefix * for await (const key of store.keys("page/")) { ... } * * // By index * for await (const key of store.keys({ byStatus: "draft" })) { ... } * ``` */ keys(filter?: string | IndexQuery): KeysIterable; /** * List entries by prefix or by index. * * @example * ```ts * // All entries * for await (const [key, entry] of store.entries()) { ... } * * // By index * const { entries } = await store.entries({ byStatus: "draft" }).page(20); * ``` */ entries(filter?: string | IndexQuery): EntriesIterable; getMany(keys: string[], concurrency?: number): Promise>>; /** * List only direct children (keys without "/" after the optional prefix). */ keysShallow(prefix?: string): AsyncIterable; /** * Create a nested sub-store with an accumulated prefix. * Pass `indexes` to enable secondary index maintenance. */ getStore(subPrefix: string, indexes?: Record>): TypedKV; /** * Rebuild index entries by scanning all data. Idempotent. * Use after adding a new index to an existing store. * * @param indexName - Specific index to rebuild, or omit for all indexes. * @returns Number of entries indexed. */ reindex(indexName?: I extends never ? never : I): Promise<{ indexed: number; }>; private keysByPrefix; private entriesByPrefix; private getByIndex; private keysByIndex; private entriesByIndex; } //# sourceMappingURL=typed-kv.d.ts.map