import type { ElyAnalyticsDataPoint, ElyD1Database, ElyD1PreparedStatement, ElyR2PutOptions, Env, } from "../src/bindings.js"; export const ACCESS_TOKEN = "D".repeat(48); export const PUBLIC_KEY = "a".repeat(64); export interface TestEnvOptions { auditEvents?: ElyAnalyticsDataPoint[]; diagnosticEvents?: ElyAnalyticsDataPoint[]; d1?: RecordedD1Database; kvEntries?: [string, string][]; kvDeletes?: string[]; kvPuts?: [string, string][]; kvReads?: string[]; r2Deletes?: string[]; r2Gets?: string[]; r2Objects?: [string, ArrayBuffer][]; r2Puts?: RecordedR2Put[]; } export interface RecordedD1Database extends ElyD1Database { batches: number[]; binds: unknown[][]; queries: string[]; } export interface RecordedR2Put { key: string; payload: ArrayBuffer; options: ElyR2PutOptions; } interface TestD1DatabaseOptions { allRows?: unknown[]; firstRows?: unknown[]; } export function testEnv(options: TestEnvOptions): Env { const values = new Map(options.kvEntries ?? []); return { ELY_ENVIRONMENT: "local", ELY_AUTH_BASE_URL: "https://elydora.test", ELY_AUTH_SECRET: "test-auth-secret-for-worker-routes", ELY_DB: options.d1 ?? testD1Database([]), ELY_KV: { get(key: string): Promise { options.kvReads?.push(key); return Promise.resolve(values.get(key) ?? null); }, put(key: string, value: string): Promise { options.kvPuts?.push([key, value]); values.set(key, value); return Promise.resolve(); }, delete(key: string): Promise { options.kvDeletes?.push(key); values.delete(key); return Promise.resolve(); }, }, ELY_STORAGE: testR2Bucket( options.r2Puts, options.r2Objects, options.r2Gets, options.r2Deletes, ), ELY_RATE_LIMITER: { limit(): Promise<{ success: boolean }> { return Promise.resolve({ success: true }); }, }, ELY_API_AUDIT: { writeDataPoint(event?: ElyAnalyticsDataPoint): void { if (event !== undefined) { options.auditEvents?.push(event); } }, }, ELY_DIAGNOSTICS: { writeDataPoint(event?: ElyAnalyticsDataPoint): void { if (event !== undefined) { options.diagnosticEvents?.push(event); } }, }, }; } export function testD1Database(rows: unknown[] | TestD1DatabaseOptions): RecordedD1Database { const binds: unknown[][] = []; const batches: number[] = []; const queries: string[] = []; const allRows = Array.isArray(rows) ? rows : rows.allRows ?? []; const firstRows = Array.isArray(rows) ? rows : rows.firstRows ?? []; let firstIndex = 0; return { batches, binds, queries, prepare(query: string) { queries.push(query); return testD1PreparedStatement(allRows, firstRows, () => firstIndex++, binds); }, batch(statements: ElyD1PreparedStatement[]) { batches.push(statements.length); return Promise.resolve([]); }, exec() { return Promise.resolve({}); }, }; } export function sessionDocument(deviceId: string | null = "device-01"): string { return JSON.stringify({ version: 1, user_id: "user-01", session_id: "session-01", ...(deviceId === null ? {} : { device_id: deviceId }), expires_at: "2099-01-01T00:00:00.000Z", }); } function testD1PreparedStatement( allRows: unknown[], firstRows: unknown[], nextFirstIndex: () => number, binds: unknown[][], ): ElyD1PreparedStatement { return { bind(...values: unknown[]) { binds.push(values); return this; }, first() { return Promise.resolve((firstRows[nextFirstIndex()] as T | undefined) ?? null); }, all() { return Promise.resolve({ results: allRows as T[] }); }, run() { return Promise.resolve({}); }, }; } function testR2Bucket( puts: RecordedR2Put[] = [], objects: [string, ArrayBuffer][] = [], gets: string[] = [], deletes: string[] = [], ): Env["ELY_STORAGE"] { const values = new Map(objects); return { get(key: string) { gets.push(key); const value = values.get(key); if (value === undefined) { return Promise.resolve(null); } return Promise.resolve({ arrayBuffer() { return Promise.resolve(value); }, }); }, put(key: string, value: ArrayBuffer, options: ElyR2PutOptions = {}) { puts.push({ key, payload: value, options }); values.set(key, value); return Promise.resolve({ arrayBuffer() { return Promise.resolve(value); }, }); }, delete(key: string) { deletes.push(key); values.delete(key); return Promise.resolve(); }, }; }