import { ulid } from "./deps.ts"; export class Store { constructor( private readonly db: Deno.Kv, private readonly storeKey: Deno.KvKeyPart, ) { } async create(value: T): Promise> { const id = ulid(); await this.db.set([this.storeKey, id], value); return new Model(this.db, this.storeKey, id, value); } async get(id: Deno.KvKeyPart): Promise | null> { const entry = await this.db.get([this.storeKey, id]); if (entry.versionstamp == null) return null; return new Model(this.db, this.storeKey, id, entry.value); } async list(): Promise>> { const models: Array> = []; for await (const entry of this.db.list({ prefix: [this.storeKey] })) { models.push(new Model(this.db, this.storeKey, entry.key[1], entry.value)); } return models; } } export class Model { #value: T; constructor( private readonly db: Deno.Kv, private readonly storeKey: Deno.KvKeyPart, private readonly entryKey: Deno.KvKeyPart, value: T, ) { this.#value = value; } get value(): T { return this.#value; } async get(): Promise { const entry = await this.db.get([this.storeKey, this.entryKey]); if (entry.versionstamp == null) return null; this.#value = entry.value; return entry.value; } async set(value: T): Promise { await this.db.set([this.storeKey, this.entryKey], value); this.#value = value; return value; } async update(value: Partial | ((value: T) => T)): Promise { const entry = await this.db.get([this.storeKey, this.entryKey]); if (entry.versionstamp == null) return null; if (typeof value === "function") { entry.value = value(entry.value); } else { entry.value = { ...entry.value, ...value }; } await this.db.set([this.storeKey, this.entryKey], entry.value); this.#value = entry.value; return entry.value; } async delete(): Promise { await this.db.delete([this.storeKey, this.entryKey]); } }