import { env } from "cloudflare:workers"; import { evictDurableObject } from "cloudflare:test"; import { describe, expect, it } from "vitest"; import { M, matches, mustMatch } from "../src/patterns.js"; type TestEnv = { STORE_DO: DurableObjectNamespace }; const testEnv = env as unknown as TestEnv; const SECRET = "session=s3kr1t"; /** the message an RPC call fails with, or "" if it succeeds */ async function errorOf(call: Promise): Promise { try { await call; return ""; } catch (err) { return String(err); } } describe("patterns", () => { it("M.string() matches strings only; a literal matches only itself", () => { expect(matches("x", M.string())).toBe(true); expect(matches(1, M.string())).toBe(false); expect(matches(undefined, M.any())).toBe(true); expect(matches("cookie", "cookie")).toBe(true); expect(matches("authorization", "cookie")).toBe(false); }); it("mustMatch names the shape but not the specimen", () => { expect(() => mustMatch(SECRET, "cookie", "jar: key")).toThrow('jar: key: must match "cookie"'); expect(() => mustMatch(SECRET, "cookie", "jar: key")).not.toThrow(SECRET); }); }); describe("MapStore over RPC", () => { const fresh = () => testEnv.STORE_DO.get(testEnv.STORE_DO.newUniqueId()); it("rotates: the admin's set is what the read-only view sees next", async () => { const store = await fresh().cookies(); const rd = await store.readOnly(); await store.init("cookie", "session=old"); expect(await rd.get("cookie")).toBe("session=old"); await store.set("cookie", "session=new"); expect(await rd.entries()).toEqual([["cookie", "session=new"]]); }); it("the read-only view has no write methods", async () => { const store = await fresh().cookies(); const rd = (await store.readOnly()) as unknown as { set(k: string, v: string): Promise }; expect(await errorOf(rd.set("cookie", SECRET))).not.toBe(""); expect(await store.has("cookie")).toBe(false); }); it("the key shape admits only `cookie`; errors carry no values", async () => { const store = await fresh().cookies(); const err = await errorOf(store.init("authorization", SECRET)); expect(err).toContain('cookie: key: must match "cookie"'); expect(err).not.toContain(SECRET); expect(await errorOf(store.init("cookie", 42 as unknown as string))).toContain("cookie: value: must match M.string()"); }); it("init refuses a present key; set and get refuse a missing one", async () => { const store = await fresh().cookies(); expect(await errorOf(store.set("cookie", SECRET))).toContain("cookie: key not found"); expect(await errorOf(store.get("cookie"))).toContain("cookie: key not found"); await store.init("cookie", SECRET); const err = await errorOf(store.init("cookie", SECRET)); expect(err).toContain("cookie: key already registered"); expect(err).not.toContain(SECRET); }); it("survives eviction: entries live in DO storage", async () => { const stub = fresh(); { // disposed before eviction: a live store stub holds the DO open using store = await stub.cookies(); await store.init("cookie", "session=durable"); } await evictDurableObject(stub); using again = await stub.cookies(); expect(await again.get("cookie")).toBe("session=durable"); expect(await again.getSize()).toBe(1); await again.delete("cookie"); expect(await again.keys()).toEqual([]); }); });