// Generated by bynkc — do not edit by hand.
// bynk.cloudflare platform adapter binding.
import type { Kv } from "./cloudflare.js";
import { None, Some, type KVNamespace, type Option } from "../runtime.js";

export class WorkersKv implements Kv {
  constructor(private env?: unknown) {}

  private ns(): KVNamespace {
    const kv = (this.env as { KV?: KVNamespace } | undefined)?.KV;
    if (!kv) {
      throw new Error(
        "bynk.cloudflare.Kv requires a KV namespace binding (env.KV) — deploy with the generated [[kv_namespaces]] wrangler stanza",
      );
    }
    return kv;
  }

  async get(key: string): Promise<Option<string>> {
    const v = await this.ns().get(key);
    return v === null ? None : Some(v);
  }

  async put(key: string, value: string): Promise<void> {
    await this.ns().put(key, value);
  }

  // v0.23 (0051): TTL as a distinct op — Bynk has no optional parameters,
  // and a distinct method beats an options record until options proliferate.
  async putTtl(key: string, value: string, ttlSeconds: number): Promise<void> {
    await this.ns().put(key, value, { expirationTtl: ttlSeconds });
  }

  async delete(key: string): Promise<void> {
    await this.ns().delete(key);
  }

  // v0.23 (0050): a binding-side *drain* — the cursor loops here, in host
  // code, because no Bynk routine can both recurse and hold a capability
  // (the given-on-free-functions gap). Eager and unbounded by design;
  // cursor-paging is deferred until the language can consume it.
  async list(prefix: Option<string>): Promise<readonly string[]> {
    const p = prefix.tag === "Some" ? prefix.value : undefined;
    const out: string[] = [];
    let cursor: string | undefined = undefined;
    for (;;) {
      const page = await this.ns().list({ prefix: p, cursor });
      for (const k of page.keys) {
        out.push(k.name);
      }
      if (page.list_complete || page.cursor === undefined) {
        break;
      }
      cursor = page.cursor;
    }
    return out;
  }
}
