Fastify
Mount Silgi as a Fastify plugin — run RPC and REST routes on the same server.
Silgi has a built-in serve() function that creates its own HTTP server. But if you already have a Fastify application with REST routes, middleware, and plugins, you can add Silgi alongside everything else using the Fastify adapter.
When to use this
| Approach | When |
|---|---|
s.serve(router) | New project, Silgi-only server |
silgiFastify(router) | Adding RPC to an existing Fastify app |
Setup
Install Fastify
npm install fastifyCreate your Silgi router
If you haven't defined a router yet, see the Getting Started guide. You need a router object — the same one you'd pass to s.serve().
Register the plugin
import from 'fastify'
import { } from 'silgi/fastify'
import { } from './router'
const = ()
// Your existing REST routes
.('/api/health', async () => ({ : 'rest' }))
// Silgi RPC under /rpc prefix
.(
(, {
: () => ({
: .user,
: .ip,
}),
}),
{ : '/rpc' },
)
.({ : 3000 })Each procedure becomes a POST route under the prefix:
POST /rpc/health
POST /rpc/users/list
POST /rpc/users/createContext from Fastify
The context option receives the Fastify request object. Use it to bridge Fastify's auth plugins, IP detection, and headers into Silgi's context:
silgiFastify(appRouter, {
: () => ({
: .user, // from @fastify/jwt or similar
: .ip, // client IP
: .headers, // raw headers
}),
})If you don't provide a context function, an empty object is used.
Content negotiation
Content negotiation works automatically. If the client sends Accept: application/x-msgpack, the Fastify adapter responds with MessagePack. Same for devalue. JSON is the default.
Fastify's built-in JSON parser handles request body parsing. The adapter only needs to encode the response.
Fastify's schema-based serialization is not used here — Silgi has its own compiled serializers. Request bodies are
parsed by Fastify, but response encoding is handled by Silgi for consistency with serve() and handler().
Error handling
Errors from guards, wraps, and resolvers are caught and returned as JSON responses with the appropriate status code. Validation errors return 400, SilgiError returns its defined status, and unexpected errors return 500.
The error format is the same as serve() and handler():
{
"code": "NOT_FOUND",
"status": 404,
"message": "Not Found"
}