import { type LuaCollectionQuery, queryLua, } from "../space_lua/query_collection.ts"; import { LuaEnv, LuaStackFrame } from "../space_lua/runtime.ts"; import type { KvPrimitives, KvQueryOptions } from "./kv_primitives.ts"; import type { Config } from "../config.ts"; import type { KV, KvKey } from "../../plug-api/types/datastore.ts"; /** * This is the data store class you'll actually want to use, wrapping the primitives * in a more user-friendly way */ export class DataStore { constructor(readonly kv: KvPrimitives) {} async get(key: KvKey): Promise { return (await this.batchGet([key]))[0]; } batchGet(keys: KvKey[]): Promise<(T | null)[]> { if (keys.length === 0) { return Promise.resolve([]); } return this.kv.batchGet(keys); } set(key: KvKey, value: any): Promise { return this.batchSet([{ key, value }]); } batchSet(entries: KV[]): Promise { if (entries.length === 0) { return Promise.resolve(); } const allKeyStrings = new Set(); const uniqueEntries: KV[] = []; for (const { key, value } of entries) { const keyString = JSON.stringify(key); if (allKeyStrings.has(keyString)) { console.warn(`Duplicate key ${keyString} in batchSet, skipping`); } else { allKeyStrings.add(keyString); uniqueEntries.push({ key, value }); } } return this.kv.batchSet(uniqueEntries); } delete(key: KvKey): Promise { return this.batchDelete([key]); } batchDelete(keys: KvKey[]): Promise { if (keys.length === 0) { return Promise.resolve(); } return this.kv.batchDelete(keys); } async batchDeletePrefix(prefix: KvKey): Promise { const keys: KvKey[] = []; for await (const { key } of this.kv.query({ prefix })) { keys.push(key); } return this.batchDelete(keys); } query(options: KvQueryOptions): AsyncIterableIterator> { return this.kv.query(options); } luaQuery( prefix: KvKey, query: LuaCollectionQuery, env: LuaEnv = new LuaEnv(), sf: LuaStackFrame = LuaStackFrame.lostFrame, enricher?: (key: KvKey, item: any) => any, config?: Config, ): Promise { return queryLua(this.kv, prefix, query, env, sf, enricher, config); } }