1import type * as Effect from "effect/Effect";
2import type { SQLiteErrorType } from "./SQLiteError.ts";
3import type { SQLiteStatement } from "./SQLiteStatement.ts";
4
5/**
6 * SQL database connection interface abstraction.
7 *
8 * This interface decouples from specific SQLite implementations (Bun, better-sqlite3, etc.)
9 * and uses Effects for all operations to support async interfaces in the future.
10 */
11export interface SQLiteConnection {
12 /**
13 * Prepare a SQL statement for execution.
14 */
15 prepare<R = unknown>(
16 sql: string,
17 ): Effect.Effect<SQLiteStatement<R>, SQLiteErrorType>;
18
19 /**
20 * Execute raw SQL statements (e.g., for DDL operations).
21 */
22 exec(sql: string): Effect.Effect<void, SQLiteErrorType>;
23
24 /**
25 * Execute a function within a transaction.
26 * If the effect fails, the transaction is rolled back.
27 * If the effect succeeds, the transaction is committed.
28 *
29 * The callback receives a connection that should be used for all operations
30 * within the transaction to avoid deadlocks with async implementations.
31 *
32 * Note: For synchronous implementations (like Bun SQLite), the effect
33 * must have no requirements (R = never). Async implementations may
34 * support effects with requirements.
35 */
36 transaction<A, E>(
37 fn: (conn: SQLiteConnection) => Effect.Effect<A, E, never>,
38 ): Effect.Effect<A, E | SQLiteErrorType, never>;
39
40 /**
41 * Execute a batch of SQL statements atomically.
42 *
43 * The batch is executed in its own logical database connection and the statements
44 * are wrapped in a transaction. This ensures that the batch is applied atomically:
45 * either all or no changes are applied.
46 *
47 * If any of the statements in the batch fails with an error, the batch is aborted,
48 * the transaction is rolled back and the effect fails.
49 *
50 * @param statements - Array of SQL statements with their parameters
51 */
52 batch(
53 statements: Array<{ sql: string; params?: unknown[] }>,
54 ): Effect.Effect<void, SQLiteErrorType>;
55}