| 1 | import * as Effect from "effect/Effect"; |
| 2 | import * as Redacted from "effect/Redacted"; |
| 3 | import type * as Scope from "effect/Scope"; |
| 4 | import type { Pool, PoolOptions } from "mysql2/promise"; |
| 5 | |
| 6 | /** |
| 7 | * Lazily load the `mysql2/promise` driver (an optional peer dependency of |
| 8 | * alchemy) with a descriptive failure when it isn't installed. The |
| 9 | * promise flavor is the canonical surface — its `.pool` property exposes |
| 10 | * the callback pool for consumers (like Kysely) that drive that API. |
| 11 | */ |
| 12 | export const importMySql = (): Promise<typeof import("mysql2/promise")> => |
| 13 | import("mysql2/promise") |
| 14 | .then((mod) => |
| 15 | (mod as { default?: { createPool?: unknown } }).default?.createPool !== |
| 16 | undefined |
| 17 | ? (mod as unknown as { default: typeof import("mysql2/promise") }) |
| 18 | .default |
| 19 | : mod, |
| 20 | ) |
| 21 | .catch((cause) => { |
| 22 | throw new Error( |
| 23 | "Failed to load the 'mysql2' driver. Install the optional peer dependency 'mysql2' to connect to MySQL.", |
| 24 | { cause }, |
| 25 | ); |
| 26 | }); |
| 27 | |
| 28 | /** |
| 29 | * Open a raw `mysql2/promise` pool on the current `Scope` — `pool.end()` |
| 30 | * runs when the scope closes. Pair with `makeExecutionMemo` for the |
| 31 | * one-pool-per-event shape workerd and Lambda require. |
| 32 | * |
| 33 | * `connectionLimit` defaults to 1: per-execution pools never need more |
| 34 | * than one connection. |
| 35 | */ |
| 36 | export const openMySQLPool = ( |
| 37 | url: Effect.Effect<Redacted.Redacted<string>>, |
| 38 | config?: Omit<PoolOptions, "uri">, |
| 39 | ): Effect.Effect<Pool, never, Scope.Scope> => |
| 40 | Effect.gen(function* () { |
| 41 | const mysql = yield* Effect.promise(importMySql); |
| 42 | const uri = Redacted.value(yield* url); |
| 43 | return yield* Effect.acquireRelease( |
| 44 | Effect.sync(() => |
| 45 | mysql.createPool({ uri, connectionLimit: 1, ...config }), |
| 46 | ), |
| 47 | (pool) => Effect.promise(() => pool.end()), |
| 48 | ); |
| 49 | }); |