Skip to content

Bun + Elysia + SQLite

Thin Elysia fetch adapter over the private checkout kernel with in-memory Bun SQLite.

Updated View as Markdown

@paykernel/example-bun-elysia-sqlite is a private workspace host (private: true). It is not published and is not @paykernel/integration-elysia. The checkout kernel owns checkout, inbox, and reconciliation.

Source: examples/bun-elysia-sqlite (README).

Mapping

createElysiaCheckoutApp returns an Elysia instance. JSON routes use parse: "none" and readRequestJson(request). Imports and Stripe route as in source:

import { Elysia } from "elysia";
import { elysiaWebhook } from "@paykernel/integration-elysia";
import {
  checkoutJsonResponse,
  createCheckoutHandlers,
  createPaymentInputFromUnknown,
  gatewayPaymentIdFromUnknown,
  readRequestJson,
  type CheckoutHttpOptions,
  type CheckoutKernel,
} from "@paykernel/example-checkout-kernel";

const noParse = { parse: "none" as const };

app.use(
  elysiaWebhook("/webhooks/stripe", {
    gateway: kernel.webhook.gateway,
    client: kernel.webhook.client,
    engine: kernel.webhook.engine,
    handler: kernel.webhook.handler,
  }),
);

elysiaWebhook posts with parse: "none", then await request.text(), then processWebhookHttp. Do not put a JSON body parser on that path. Stripe HMAC needs the original bytes.

HTTP status lives in the checkout kernel (mapInboxOutcome), not in @paykernel/webhooks. Fulfillment runs only after an inbox claim, and only when the rematched event is payment.succeeded / capture.completed with payment.status === "paid". Never fulfill in onWebhookVerified. Never createPayment again after an indeterminate create — lookup + decideReconciliationPolicy only.

This package does not reimplement mapInboxOutcome or HMAC signing. Stripe fixtures live in the kernel.

:memory: is process-local

Default createCheckoutKernel() uses in-memory Bun SQLite after an explicit migrateSqliteAdapter. One process, one memory DB — not multi-host or multi-region. See SQLite store.

Routes

createElysiaCheckoutApp(kernel) wires:

Method Path Notes
POST /payments parse: "none" + readRequestJson. Invalid JSON → 400 { "error": "invalid_json" }.
POST /webhooks/stripe elysiaWebhook / request.text().
GET /orders/:orderId Order book.
POST /internal/reconcile Test hook. Unauthenticated. Do not deploy (enableTestHooks).
POST /internal/provider-paid Test hook. Unauthenticated. Do not deploy.
GET /internal/create-count Test hook. Unauthenticated. Do not deploy (enableTestHooks).

Shared failure paths: Checkout kernel (runCheckoutHttpScenarios("elysia", …)).

Run

bun install
bun test
# optional listen (PORT, default 3000)
bun run start

bun run startbun src/index.tsapp.listen(port). Tests drive app.handle(req) and do not use that listener.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close