route()
Wrap a +server.c handler with body parsing, validation, container resolution and JSON (or TRON) serialization.
import { messages } from '$lib/norns/messages/server/public'
import { sendMessageSchema } from '$lib/norns/messages/shared/schema'
export GET := route
handler: ({ container }) =>
data: messages(container).list()
export POST := route
input: sendMessageSchema
handler: ({ input, container }) =>
messages(container).create input
{ ok: true }route is auto-imported in server files.
#What the wrapper does, in order
- Body parsing, only when
inputis set.application/jsonis parsed as JSON;application/x-www-form-urlencodedandmultipart/form-dataare read withformData()and flattened. An app-wide or per-route serializer can claim other content types first through itsparseBodyhook (this is how TRON request bodies work). Empty or unsupported bodies becomenull, and the schema decides whethernullis acceptable. - Body validation against
input. Failure throwserror(400, { message, issues }). - Query validation against
query, overObject.fromEntries(url.searchParams). Same 400 on failure. - Handler call with
{ input, query, container, event, user }. - Serialization. A
Responsereturned by the handler passes through untouched. Otherwise the serializer (per-route, else app-wide) may turn the value into aResponse; if it declines, the value is sent as JSON withjson().undefinedbecomesnull.
#Options
| Option | Notes |
|---|---|
input |
body schema: a valibot schema, any Standard Schema, or a function |
query |
query-string schema, same forms |
serializer |
per-route serializer; null forces plain JSON even when an app-wide one is set |
handler |
required |
For non-success outcomes throw error(...) or redirect(...) inside the handler; SvelteKit surfaces them.
#Returning something that is not JSON
Return a Response yourself:
export GET := route
handler: ({ container }) =>
new Response(docs(container).sitemap(), { headers: { 'content-type': 'application/xml' } })#Calling it from the browser
Plain fetch works. With norns-tron installed, api.get('/api/messages') sends Accept: application/tron and decodes either format transparently.