Skip to content
Source
Sign inSign up
Open History to see the last commit

MigrationConnection.ts

57 lines1.9 KB

1import { withMySqlExecutor, withPgExecutor } from "@alchemy.run/sql/Migrations/Executors";
2import type { MigrationError, SqlExecutor } from "@alchemy.run/sql/Migrations/Format";
3import type * as Effect from "effect/Effect";
4​
5/**
6 * Where and as whom a migration connects. Plain JSON: the Lambda transport
7 * sends it to the migration runner in the invocation payload.
8 */
9export interface MigrationConnectionTarget {
10 dialect: "postgres" | "mysql";
11 host: string;
12 port: number;
13 database: string | undefined;
14 username: string;
15 password: string;
17​
18// Fail fast on an unreachable endpoint instead of hanging the deploy.
19const CONNECT_TIMEOUT_MILLIS = 15_000;
20​
21/**
22 * Open one `pg` client or `mysql2` connection to an RDS endpoint for the
23 * scope of `use`, closing it afterwards. Shared by the direct transport
24 * (on the deploying machine) and the migration runner Lambda (in the VPC).
25 *
26 * TLS is always on. RDS certificates chain to a private AWS CA that Node's
27 * trust store doesn't carry, so the certificate is not verified.
28 */
29export const withMigrationConnection = <A, E, R>(
30 target: MigrationConnectionTarget,
31 use: (executor: SqlExecutor) => Effect.Effect<A, E, R>,
32): Effect.Effect<A, MigrationError | E, R> =>
33 target.dialect === "postgres"
34 ? withPgExecutor(
35 {
36 host: target.host,
37 port: target.port,
38 database: target.database,
39 user: target.username,
40 password: target.password,
41 ssl: { rejectUnauthorized: false },
42 connectionTimeoutMillis: CONNECT_TIMEOUT_MILLIS,
43 },
44 use,
45 )
46 : withMySqlExecutor(
47 {
48 host: target.host,
49 port: target.port,
50 database: target.database,
51 user: target.username,
52 password: target.password,
53 ssl: { rejectUnauthorized: false },
54 connectTimeout: CONNECT_TIMEOUT_MILLIS,
55 },
56 use,
57 );