Skip to content

Handler.compose

Composes multiple handlers into a single handler. This is useful when you want to run multiple services (like fee payer and key manager) from a single endpoint.

Usage

server.ts
import { Handler, Kv } from 'tempo.ts/server'
import { tempo } from 'tempo.ts/chains'
import { http } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
 
const handler = Handler.compose([
  // Create a fee payer handler
  Handler.feePayer({
    account: privateKeyToAccount('0x...'),
    chain: tempo({ feeToken: '0x20c0...0001' }),
    transport: http(),
    path: '/fee-payer',
  })
  
  // Create a key manager handler
  Handler.keyManager({
    kv: Kv.memory(),
    path: '/keys',
    rp: 'example.com',
  })
])

Then plug handler into your server framework of choice. For example:

createServer(handler.listener) // Node.js
Bun.serve(handler) // Bun
Deno.serve(handler) // Deno
app.all('*', c => handler.fetch(c.request)) // Elysia
app.use(handler.listener) // Express
app.use(c => handler.fetch(c.req.raw)) // Hono
export const GET = handler.fetch // Next.js
export const POST = handler.fetch // Next.js

Base Path

You can configure the base path for the composed handler.

const handler = Handler.compose([
  Handler.feePayer({ path: '/fee-payer', ... }),
  Handler.keyManager({ path: '/keys', ... }),
], { path: '/api' })

Requests are routed as follows:

  • POST /api/fee-payer → Fee payer handler
  • GET /api/keys/challenge → Key manager handler
  • GET /api/keys/:credentialId → Key manager handler
  • POST /api/keys/:credentialId → Key manager handler

Parameters

handlers

  • Type: Handler[]

An array of handlers to compose. Handlers are tried in order, and the first one that doesn't return a 404 wins.

import { Handler } from 'tempo.ts/server'
 
const handler = Handler.compose([
  Handler.feePayer({ /* ... */ }),
  Handler.keyManager({ /* ... */ }),
  // Add more handlers as needed
])

options.path

  • Type: string
  • Default: '/'

The base path where all composed handlers will be mounted. This path is stripped from incoming requests before forwarding to individual handlers.

import { Handler } from 'tempo.ts/server'
 
const handler = Handler.compose(
  [
    Handler.feePayer({ path: '/fee-payer', /* ... */ }),
    Handler.keyManager({ path: '/keys', /* ... */ }),
  ],
  { path: '/api' }, 
)
 
// Endpoints will be:
// POST /api/fee-payer
// GET  /api/keys/challenge
// GET  /api/keys/:credentialId
// POST /api/keys/:credentialId