Adapters
Bring-your-own-database and the framework bridge.
Adapters bridge orvacon to your infrastructure. There are two kinds — a database adapter (where orvacon persists payments, events, and the ledger) and a framework adapter (the HTTP glue).
Database — bring your own
orvacon imposes no database. You pass a DatabaseAdapter; the core does every read and write through
it, inside the transactions it asks for, so a state transition and its ledger row commit together —
there is never a half-applied state.
Supabase / Postgres
@orvacon/adapter-supabase connects directly to Postgres (transactions, advisory locks) and pairs
with a generated schema carrying default-deny row-level security.
import { supabaseAdapter } from "@orvacon/adapter-supabase";
import postgres from "postgres";
// `prepare: false` is load-bearing behind a serverless pooler (Supabase, PgBouncer).
const sql = postgres(process.env.SUPABASE_DB_URL!, { prepare: false });
const database = supabaseAdapter({ sql });Generate the schema + RLS migration with the CLI:
npx orvacon generate --write # → supabase/migrations/<timestamp>_orvacon.sqlThe RLS keys off each payment's userId (e.g. a Supabase auth.uid()). A guest payment has no
owner and is visible only to the server (the service role / direct connection) — auth.uid() = null
never matches a row, a deliberate posture. Any Postgres works underneath: Supabase, Neon, RDS, or
your own; a Drizzle ORM adapter is on the roadmap.
Framework — Next.js
@orvacon/adapter-nextjs turns orvacon into App Router route handlers — the gateway-callback route,
with signed-webhook delivery drained through after().
import { toNextJsHandler } from "@orvacon/adapter-nextjs";
import { orva } from "@/lib/orva";
export const { POST } = toNextJsHandler(orva, {
returnUrl: { success: "/checkout/done", failure: "/checkout/failed" },
});The finalize and state writes settle before the browser is redirected, so the user lands on the real outcome; the signed outbound webhook is drained in the background.
Make the callback route public
The gateway redirects the browser to this route with no session — exclude /api/orva/callback from
your middleware, or an auth check silently strands payments.
The core itself is framework-agnostic — it speaks Web-standard Request/Response via
toWebHandler, so other framework adapters are a thin wrapper; v1 ships the Next.js one.