@dotdo/db-rpc-server
v0.1.6
Published
RPC server for Payload database adapters - exposes any adapter via HTTP/WebSocket using capnweb
Readme
@dotdo/db-rpc-server
RPC server for Payload database adapters. Exposes any Payload database adapter via HTTP/WebSocket using capnweb and Hono.
Installation
pnpm add @dotdo/db-rpc-server honoQuick Start
Cloudflare Workers
import { createRpcServer } from '@dotdo/db-rpc-server/hono'
import { getPayload } from 'payload'
import config from './payload.config'
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const payload = await getPayload({ config })
const app = createRpcServer({
adapter: payload.db,
payload,
})
return app.fetch(request, env, ctx)
},
}Bun
import { createRpcServer } from '@dotdo/db-rpc-server/hono'
import { getPayload } from 'payload'
import config from './payload.config'
const payload = await getPayload({ config })
const app = createRpcServer({
adapter: payload.db,
payload,
})
export default {
fetch: app.fetch,
port: 3001,
}Node.js with @hono/node-server
import { serve } from '@hono/node-server'
import { createRpcServer } from '@dotdo/db-rpc-server/hono'
import { getPayload } from 'payload'
import config from './payload.config'
const payload = await getPayload({ config })
const app = createRpcServer({
adapter: payload.db,
payload,
})
serve({
fetch: app.fetch,
port: 3001,
})Adding to Existing Hono App
import { Hono } from 'hono'
import { createRpcMiddleware } from '@dotdo/db-rpc-server/hono'
import { getPayload } from 'payload'
import config from './payload.config'
const payload = await getPayload({ config })
const app = new Hono()
// Your other routes
app.get('/', (c) => c.text('Hello'))
// Mount RPC at /rpc
app.route(
'/rpc',
createRpcMiddleware({
adapter: payload.db,
payload,
}),
)
export default appAuthentication
The server supports two authentication modes:
Option 1: Payload Auth (Default)
Uses Payload's built-in authentication system. Pass the payload instance:
createRpcServer({
adapter: payload.db,
payload, // Uses payload.auth() to validate tokens
})Supported token types:
- JWT Tokens - Obtained from
payload.login() - API Keys - If configured in your users collection
Getting a token:
const { token } = await payload.login({
collection: 'users',
data: {
email: '[email protected]',
password: 'password',
},
})Option 2: Custom Auth
Use validateToken for external auth systems (Cloudflare Access, custom JWT, etc.):
createRpcServer({
adapter: db,
validateToken: async (token) => {
// Validate with your auth system
const decoded = await verifyJwt(token, { secret: env.JWT_SECRET })
if (!decoded) return null
// Return a user object (must have at least 'id')
return {
id: decoded.sub,
email: decoded.email,
// ... other user properties
}
},
})Cloudflare Access example:
createRpcServer({
adapter: db,
validateToken: async (token) => {
// Validate Cloudflare Access JWT
const payload = await verifyCloudflareAccessJwt(token, {
teamDomain: env.CF_TEAM_DOMAIN,
audience: env.CF_ACCESS_AUD,
})
return payload ? { id: payload.sub, email: payload.email } : null
},
})Auth Flow
- Client connects to the public RPC endpoint
- Client calls
authenticate(bearerToken) - Server validates token (via Payload or custom validator)
- Server returns an authenticated API stub
- All subsequent calls on that stub include user context
API Reference
createRpcServer(options)
Creates a standalone Hono application with RPC endpoint.
interface RpcServerOptions {
adapter: BaseDatabaseAdapter
payload?: Payload // For Payload auth
validateToken?: ValidateTokenFn // For custom auth
basePath?: string // default: '/rpc'
}
// Either payload or validateToken must be provided
type ValidateTokenFn = (token: string) => Promise<TypedUser | null>Endpoints:
GET /- Server infoPOST /rpc- RPC endpoint (handles HTTP batch)GET /rpc- WebSocket upgradeGET /rpc/health- Health check
createRpcMiddleware(options)
Creates Hono middleware for mounting on existing apps.
interface RpcMiddlewareOptions {
adapter: BaseDatabaseAdapter
payload?: Payload // For Payload auth
validateToken?: ValidateTokenFn // For custom auth
}DatabaseRpcTarget
The public RPC target class. Use directly for custom setups.
import { DatabaseRpcTarget } from '@dotdo/db-rpc-server'
// With Payload auth
const target = new DatabaseRpcTarget(adapter, payload)
// With custom auth
const target = new DatabaseRpcTarget(adapter, undefined, validateTokenFn)AuthenticatedDatabaseTarget
The authenticated RPC target. Returned by authenticate().
Supported Operations
All Payload database adapter operations are supported over RPC:
Collections
find,findOne,create,updateOne,updateMany,deleteOne,deleteManycount,upsert,findDistinct,queryDrafts
Globals
findGlobal,createGlobal,updateGlobal
Versions
findVersions,createVersion,updateVersion,deleteVersions,countVersionsfindGlobalVersions,createGlobalVersion,updateGlobalVersion,countGlobalVersions
Transactions
beginTransaction,commitTransaction,rollbackTransaction
Jobs
updateJobs
Migrations
Migrations are not supported over RPC. Run migrations directly on the server where the database adapter is configured.
Security Considerations
- Always use HTTPS/WSS in production - Tokens are sent in RPC calls
- Token expiration - Use short-lived tokens and implement refresh
- Rate limiting - Consider adding rate limiting middleware
- Access control - The authenticated user's permissions apply to all operations
Related
- @dotdo/db-rpc - The client adapter
- capnweb - The underlying RPC library
- Hono - The web framework used for HTTP handling
- Payload Docs
