SSR framework for Svelte 5 + Bun with islands-based selective hydration
API routes
Mochi.api() creates JSON API endpoints. The handler receives a MochiApiEvent with method, request, url, and locals:
import { error } from "./mochi-framework/utils";
"/health": Mochi.api(({ method }) =>
Response.json({ status: "ok", method }),
),
"/add": Mochi.api(async ({ method, request }) => {
if (method !== "POST") error(405, "Method Not Allowed");
const { a, b } = await request.json();
return Response.json({ result: a + b });
}),Error responses
API routes return a standard JSON envelope for all errors — they never render the HTML error page, and handleError is not called for them. Use apiError(status, message) to build the envelope response:
import { apiError } from 'mochi-framework';
Mochi.api(async ({ request }) => {
const body = await request.json().catch(() => null);
if (!body) return apiError(400, 'Invalid JSON');
return Response.json({ ok: true });
});
// bad body → 400 { "error": { "message": "Invalid JSON", "status": 400 } }apiError returns a Response with Content-Type: application/json and the HTTP status set to match. Prefer it over throwing when the error is part of the route’s normal control flow.
Thrown MochiHttpError — same envelope. Use error(status, message) from mochi-framework to throw one from deep inside helper code where returning is awkward:
import { error } from 'mochi-framework';
error(404, 'Not found');
// → 404 { "error": { "message": "Not found", "status": 404 } }Any other uncaught throw — returned as 500 Internal Server Error with a generic message. The original error (including stack) is logged server-side via log.error with the method and path; it is not leaked to the client. Throw MochiHttpError (or return apiError(…)) explicitly when you want a specific status or message to reach the caller.
Mochi.api(async () => {
await db.query('SELECT …'); // throws ConnectionError
return Response.json({ ok: true });
});
// → 500 { "error": { "message": "Internal Server Error", "status": 500 } }
// (real error + stack logged to stderr)