| 1 | import * as Alchemy from "alchemy"; |
| 2 | import * as Cloudflare from "alchemy/Cloudflare"; |
| 3 | import * as Neon from "alchemy/Neon"; |
| 4 | import * as Prisma from "alchemy/Prisma"; |
| 5 | import * as Effect from "effect/Effect"; |
| 6 | |
| 7 | /** |
| 8 | * A Prisma contract + Neon project + branch. Passing the contract's |
| 9 | * output to `Prisma.Migrate` orders the deploy: |
| 10 | * |
| 11 | * 1. `Prisma.Contract` re-emits the contract and plans a migration |
| 12 | * package when the contract drifted from the migration graph. |
| 13 | * 2. `Prisma.Migrate` applies pending packages to the branch |
| 14 | * (graph-ordered, tracked by the database's contract marker). |
| 15 | */ |
| 16 | export const NeonDb = Effect.gen(function* () { |
| 17 | const { stage } = yield* Alchemy.Stack; |
| 18 | |
| 19 | const contract = yield* Prisma.Contract("app-contract"); |
| 20 | |
| 21 | const project = stage.startsWith("pr-") |
| 22 | ? yield* Neon.Project.ref("app-db", { stage: `staging-${stage}` }) |
| 23 | : yield* Neon.Project("app-db", { |
| 24 | region: "aws-us-east-1", |
| 25 | }); |
| 26 | |
| 27 | const branch = yield* Neon.Branch("app-branch", { project }); |
| 28 | |
| 29 | const migrate = yield* Prisma.Migrate("app-migrate", { |
| 30 | url: branch.connectionUri, |
| 31 | contract, |
| 32 | }); |
| 33 | |
| 34 | return { project, branch, contract, migrate }; |
| 35 | }); |
| 36 | |
| 37 | export const Hyperdrive = Effect.gen(function* () { |
| 38 | const { branch } = yield* NeonDb; |
| 39 | return yield* Cloudflare.Hyperdrive.Connection("app-hyperdrive", { |
| 40 | origin: branch.origin, |
| 41 | caching: { disabled: true }, |
| 42 | }); |
| 43 | }); |