camelon

Database

camelon does not ship a database. It injects the client you pass. The db arg is whatever you hand createHandler, and it arrives on the args bag in every get and post handler.

A tiny in-memory client, injected and read off db:

import type { GetFunction } from 'camelon';
import type { Fruit, FruitDb } from '../../db';

declare module 'camelon' {
  interface Register {
    db: FruitDb;
  }
}

export type GetOutput = { fruits: Fruit[] };

export const get: GetFunction = ({ db }) => {
  return { fruits: db.fruits() };
};

export default function Db({ fruits }: GetOutput) {
  return (
    <div class="d-card">
      <strong>Fruit store</strong>
      <ul class="d-list">
        {fruits.map((f) => (
          <li>
            {f.emoji} {f.name} — {f.price}¢
          </li>
        ))}
      </ul>
    </div>
  );
}
live

A real adapter (Prisma via the same db arg) looks identical from the route's side:

import type { GetFunction } from 'camelon';
import type { PrismaClient, User } from '@prisma/client';

declare module 'camelon' {
  interface Register {
    db: PrismaClient;
  }
}

export type GetOutput = { users: User[] };

export const get: GetFunction = async ({ db }) => {
  return { users: await db.user.findMany() };
};
import { createHandler } from 'camelon';
import { PrismaClient } from '@prisma/client';
import { manifest } from './gen/manifest.generated';

await createHandler({ routes: manifest, db: new PrismaClient() });

Type db by declaring it on Register, the one augmentable interface where an app types itself. db then carries your client's type everywhere — no cast:

declare module 'camelon' {
  interface Register {
    db: PrismaClient;
  }
}

export type GetOutput = { users: User[] };

export const get: GetFunction = async ({ db }) => {
  return { users: await db.user.findMany() }; // db is PrismaClient
};

Until you declare Register['db'], touching db is a type error that tells you to declare it — never unknown or any. At runtime, using db without configuring one throws a clear error. Apps that never touch db pay nothing.