import { expect } from "bun:test"; import type { Db } from "@stc/db"; import { bunSqlAdapter } from "../src/server/auth/adapter"; import { forEachDb } from "./helpers"; // biome-ignore lint/suspicious/noExplicitAny: adapter is generic over Better Auth options const make = (db: Db): any => bunSqlAdapter(db)({}); async function seed(a: ReturnType) { const people = [ { name: "Ada", email: "ada@example.com", emailVerified: true }, { name: "Bob", email: "bob@Example.org", emailVerified: false }, { name: "Cyd", email: "cyd@example.com", emailVerified: false }, ]; const out = []; for (const p of people) out.push(await a.create({ model: "user", data: { ...p, createdAt: new Date(), updatedAt: new Date() } })); return out; } forEachDb("adapter create and findOne round-trip types", async (db) => { const a = make(db); const [ada] = await seed(a); expect(typeof ada.id).toBe("string"); const found = await a.findOne({ model: "user", where: [{ field: "email", value: "ada@example.com" }] }); expect(found.name).toBe("Ada"); expect(found.emailVerified).toBe(true); expect(found.createdAt).toBeInstanceOf(Date); expect(await a.findOne({ model: "user", where: [{ field: "email", value: "nobody@x" }] })).toBeNull(); }); forEachDb("adapter where operators", async (db) => { const a = make(db); await seed(a); const names = async (where: unknown[], extra: Record = {}) => (await a.findMany({ model: "user", where, sortBy: { field: "name", direction: "asc" }, ...extra })).map((u: { name: string }) => u.name); expect(await names([{ field: "name", operator: "ne", value: "Ada" }])).toEqual(["Bob", "Cyd"]); expect(await names([{ field: "name", operator: "in", value: ["Ada", "Cyd"] }])).toEqual(["Ada", "Cyd"]); expect(await names([{ field: "name", operator: "not_in", value: ["Ada"] }])).toEqual(["Bob", "Cyd"]); expect(await names([{ field: "name", operator: "in", value: [] }])).toEqual([]); expect(await names([{ field: "email", operator: "contains", value: "example" }])).toEqual(["Ada", "Cyd"]); expect(await names([{ field: "email", operator: "contains", value: "Example" }])).toEqual(["Bob"]); expect(await names([{ field: "email", operator: "contains", value: "EXAMPLE.ORG", mode: "insensitive" }])).toEqual(["Bob"]); expect(await names([{ field: "email", operator: "starts_with", value: "cy" }])).toEqual(["Cyd"]); expect(await names([{ field: "email", operator: "ends_with", value: ".com" }])).toEqual(["Ada", "Cyd"]); expect(await names([{ field: "email", value: "BOB@example.org", mode: "insensitive" }])).toEqual(["Bob"]); expect(await names([{ field: "name", operator: "gt", value: "Ada" }])).toEqual(["Bob", "Cyd"]); expect(await names([{ field: "name", operator: "lte", value: "Bob" }])).toEqual(["Ada", "Bob"]); expect(await names([{ field: "emailVerified", value: false }])).toEqual(["Bob", "Cyd"]); // AND clauses AND-ed, OR clauses grouped expect(await names([ { field: "emailVerified", value: false }, { field: "name", value: "Ada", connector: "OR" }, { field: "name", value: "Cyd", connector: "OR" }, ])).toEqual(["Cyd"]); expect(await names([], { limit: 1, offset: 1 })).toEqual(["Bob"]); expect(await names([], { limit: 2, sortBy: { field: "name", direction: "desc" } })).toEqual(["Cyd", "Bob"]); expect(await names([{ field: "image", value: null }])).toEqual(["Ada", "Bob", "Cyd"]); }); forEachDb("adapter update, count, delete, consume, increment", async (db) => { const a = make(db); const [ada, bob] = await seed(a); const up = await a.update({ model: "user", where: [{ field: "id", value: ada.id }], update: { name: "Ada L." } }); expect(up.name).toBe("Ada L."); expect(await a.updateMany({ model: "user", where: [{ field: "emailVerified", value: false }], update: { image: "x.png" } })).toBe(2); expect(await a.count({ model: "user", where: [{ field: "image", value: "x.png" }] })).toBe(2); expect(await a.count({ model: "user" })).toBe(3); await a.delete({ model: "user", where: [{ field: "id", value: bob.id }] }); expect(await a.count({ model: "user" })).toBe(2); expect(await a.deleteMany({ model: "user", where: [{ field: "image", value: "x.png" }] })).toBe(1); const exp = new Date(Date.now() + 60_000); await a.create({ model: "verification", data: { identifier: "k", value: "v1", expiresAt: exp, createdAt: new Date(), updatedAt: new Date() } }); const consumed = await a.consumeOne({ model: "verification", where: [{ field: "identifier", value: "k" }] }); expect(consumed?.value).toBe("v1"); expect(await a.consumeOne({ model: "verification", where: [{ field: "identifier", value: "k" }] })).toBeNull(); const live = await a.findMany({ model: "verification", where: [{ field: "expiresAt", operator: "gt", value: new Date() }] }); expect(live.length).toBe(0); });