UNPKG

@variablesoftware/mock-d1

Version:

๐ŸŽ›๏ธ๐Ÿ—‚๏ธ๐Ÿง  Mock D1 Database implementation for testing Cloudflare Workers

87 lines (86 loc) โ€ข 3.33 kB
/** * mockD1Database.ts v3 ๐Ÿงˆ (updated for named bind support) * * A lightweight, test-optimized mock of Cloudflare's D1Database interface. * Designed for Workers unit testing without requiring a live D1 instance. * * โœ… Supported SQL commands (simplified parsing): * - CREATE TABLE [IF NOT EXISTS] * - DROP TABLE (stubbed via `delete db[table]` expected externally) * - INSERT INTO ... VALUES (...) * - SELECT * FROM ... WHERE ... (supports AND/OR + named binds) * - DELETE FROM ... WHERE ... (with accurate changes count) * * ๐Ÿงฉ Internal mechanics: * - Tables stored in `Map<string, { rows: D1Row[] }>` * - Uses basic regex parsing โ€” not SQL-standards compliant * - No type coercion โ€” binds and data are raw JS primitives * - Validation of :bind args occurs during execution, not .bind() * - Logs behavior when LOG includes "D1" at level 3 or above * * ๐Ÿงช Test-only helpers: * - `inject(table, rows[])`: manually preload test data * - `dump()`: returns full mock DB snapshot * - `batch()`: stubbed to return empty D1Result[] * * ๐Ÿงฑ Design notes: * - Safe for isolated tests (no persistence between runs) * - Reflects Cloudflare D1 runtime quirks (bind usage, defer errors) * - Implements prepare().bind().run()/all()/first()/raw() interface * * ๐Ÿง  Future support ideas: * - UPDATE ... SET ... WHERE ... * - LIKE, BETWEEN, NOT, nested conditions * - JOIN or mock link handling * - ORDER BY, LIMIT */ import { log } from "@variablesoftware/logface"; import { createPreparedStatement } from "./engine/preparedStatement.js"; import { mockInject } from "./helpers/mockInject.js"; import { mockBatch } from "./helpers/mockBatch.js"; /** * Creates a new mock D1 database instance. * * @returns An object implementing the mock D1Database interface, including: * - prepare(sql): prepares a statement for execution * - batch(statements): executes multiple statements in parallel * - dump(): returns a snapshot of the current database state * - inject(table, rows): preloads data into a table * - withSession(): returns a session-scoped interface */ export function mockD1Database() { const db = new Map(); log.debug("mockD1Database created", { db }); /** * Prepares a SQL statement for execution. * @param sql - The SQL statement string. * @returns A mock prepared statement. */ function prepare(sql) { return createPreparedStatement(sql, db); } /** * Preloads data into a table for testing (mock/test helper only). * @warning This is a mock/test-only API. Emits a warning if used outside test. * @param table - The table name. * @param columns - The explicit table schema columns (required). * @param rows - The rows to inject. */ function inject(tableName, columns, rows) { mockInject(db, tableName, columns, rows); } /** * Returns a snapshot of the current database state (mock/test helper only). * @warning This is a mock/test-only API. Emits a warning if used outside test. * @returns An object mapping table names to their rows. */ function dump() { return Object.fromEntries(db.entries()); } return { prepare, batch: mockBatch, dump, inject, }; }