import { env } from "cloudflare:workers"; type D1Value = string | number | null; export function stmt(sql: string, ...params: D1Value[]): D1PreparedStatement { return env.DB.prepare(sql).bind(...params); } export async function first(sql: string, ...params: D1Value[]): Promise { return stmt(sql, ...params).first(); } export async function all(sql: string, ...params: D1Value[]): Promise { const result = await stmt(sql, ...params).all(); return result.results; } export async function run(sql: string, ...params: D1Value[]): Promise { return stmt(sql, ...params).run(); } export async function batch(statements: D1PreparedStatement[]): Promise { if (statements.length === 0) return []; return env.DB.batch(statements); } export function placeholders(count: number): string { return Array.from({ length: count }, () => "?").join(", "); } /** D1 allows at most 100 bound parameters per statement; keep IN-lists well below that. */ export const MAX_IN_LIST = 90; export function chunks(items: T[], size = MAX_IN_LIST): T[][] { const out: T[][] = []; for (let index = 0; index < items.length; index += size) out.push(items.slice(index, index + size)); return out; } export type ReadSession = { first(sql: string, ...params: D1Value[]): Promise; all(sql: string, ...params: D1Value[]): Promise; }; /** * D1 Sessions API: reads may be served by a nearby read replica (when replication is enabled) while staying * sequentially consistent within the session. Only for read-heavy paths that tolerate replica lag. */ export function withSession(constraint: D1SessionConstraint = "first-unconstrained"): ReadSession { const session = env.DB.withSession(constraint); return { first: (sql: string, ...params: D1Value[]) => session .prepare(sql) .bind(...params) .first(), all: async (sql: string, ...params: D1Value[]) => ( await session .prepare(sql) .bind(...params) .all() ).results, }; }