Prisma ORM with Postgres
Contracts · Query API · Runnable example
Install the dependencies
Section titled “Install the dependencies”pnpm add https://pkg.alchemy.run/alchemy/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/cloudflare/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/neon/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/prisma/pr:2930:a10573e effect @prisma/orm-postgres arktypepnpm add -D prismabun add https://pkg.alchemy.run/alchemy/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/cloudflare/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/neon/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/prisma/pr:2930:a10573e effect @prisma/orm-postgres arktypebun add -d prismanpm install https://pkg.alchemy.run/alchemy/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/cloudflare/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/neon/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/prisma/pr:2930:a10573e effect @prisma/orm-postgres arktypenpm install -D prismayarn add https://pkg.alchemy.run/alchemy/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/cloudflare/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/neon/pr:2930:a10573e https://pkg.alchemy.run/@alchemy.run/prisma/pr:2930:a10573e effect @prisma/orm-postgres arktypeyarn add -D prismaCloudflare setup · Neon setup · Define a contract
Configure validation for Workers
Section titled “Configure validation for Workers”import { configure } from "arktype/config";
configure({ jitless: true });Import the bootstrap before the contract builder:
import "./validation.ts";import { defineContract } from "@alchemy.run/prisma/ORM";If your package uses "sideEffects": false, preserve this module:
{ "sideEffects": ["./src/prisma/validation.ts"] }PSL-first projects skip this step.
Provision the database and migrations
Section titled “Provision the database and migrations”import * as Neon from "@alchemy.run/neon";import * as Prisma from "@alchemy.run/prisma";import * as Effect from "effect/Effect";
export const Db = Effect.gen(function* () { const contract = yield* Prisma.Contract("contract"); const project = yield* Neon.Project("app-db"); const branch = yield* Neon.Branch("app-branch", { project });
yield* Prisma.Migrate("migrate", { url: branch.connectionUri, contract, });
return branch;});Add Hyperdrive
Section titled “Add Hyperdrive”import * as Cloudflare from "@alchemy.run/cloudflare";
export const Hyperdrive = Effect.gen(function* () { const branch = yield* Db; return yield* Cloudflare.Hyperdrive.Connection("app-hyperdrive", { origin: branch.origin, caching: { disabled: true }, });});Caching is disabled so reads immediately reflect writes. Hyperdrive guide.
Connect in a Worker
Section titled “Connect in a Worker”import * as Cloudflare from "@alchemy.run/cloudflare";import * as PrismaPostgres from "@alchemy.run/prisma/ORM/Postgres";import * as Effect from "effect/Effect";import * as HttpServerResponse from "effect/http/HttpServerResponse";import { contract } from "./prisma/contract.ts";import { Hyperdrive } from "./db.ts";
export default class Api extends Cloudflare.Worker<Api>()( "Api", { main: import.meta.url }, Effect.gen(function* () { const conn = yield* Cloudflare.Hyperdrive.Connect(Hyperdrive); const db = yield* PrismaPostgres.Postgres(conn.connectionString, { contract });
return { fetch: Effect.gen(function* () { const users = yield* db.orm.public.User.all(); return yield* HttpServerResponse.json({ users }); }), }; }).pipe(Effect.provide(Cloudflare.Hyperdrive.ConnectBinding)),) {}Use a PSL contract
Section titled “Use a PSL contract”import { makeDatabase } from "./prisma/generated/client.ts";
const conn = yield* Cloudflare.Hyperdrive.Connect(Hyperdrive);const db = yield* makeDatabase(conn.connectionString);Generate the PSL client before compiling. The handler and binding layer stay the same.
Wire the stack
Section titled “Wire the stack”import * as Alchemy from "alchemy";import * as Cloudflare from "@alchemy.run/cloudflare";import * as Neon from "@alchemy.run/neon";import * as Prisma from "@alchemy.run/prisma";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import Api from "./src/api.ts";
export default Alchemy.Stack( "PrismaWorker", { providers: Layer.mergeAll( Cloudflare.providers(), Neon.providers(), Prisma.providers(), ), state: Alchemy.localState(), }, Effect.gen(function* () { const api = yield* Api; return { url: api.url }; }),);Deploy and query
Section titled “Deploy and query”pnpm alchemy deploycurl https://<your-worker>.workers.devbun alchemy deploycurl https://<your-worker>.workers.devnpx alchemy deploycurl https://<your-worker>.workers.devyarn alchemy deploycurl https://<your-worker>.workers.devThis demo route is public. Add authentication before exposing private data.
Clean up
Section titled “Clean up”pnpm alchemy destroybun alchemy destroynpx alchemy destroyyarn alchemy destroyDestroy removes the example’s Worker, Hyperdrive configuration, and Neon resources, including the database data.