Edit

new Telefunc()

Environment: server.

Use new Telefunc() to embed Telefunc into your server (Hono, Cloudflare, Express, Fastify, ...).

Lower-level alternative: API > serve()

Setup

With the web standard Request object and Response object (Hono, Fastify, ...):

// server.js
// Environment: server
 
import { Hono } from 'hono'
import { serve } from '@hono/node-server'
import { Telefunc } from 'telefunc/node'
 
const app = new Hono()
const telefunc = new Telefunc()
 
app.all('/_telefunc', async (c) => {
  const response = await telefunc.serve({
    request: c.req.raw,
    // Provide context, accessed via getContext()
    context: {
      user: await c.get('user')
    }
  })
  return response ?? c.notFound()
})
 
const server = serve({ fetch: app.fetch, port: 3000 })
 
// Enable WebSocket support for streams
telefunc.installWebSocket(server)
// server.ts
// Environment: server
 
import { Hono } from 'hono'
import { serve } from '@hono/node-server'
import { Telefunc } from 'telefunc/node'
 
const app = new Hono()
const telefunc = new Telefunc()
 
app.all('/_telefunc', async (c) => {
  const response = await telefunc.serve({
    request: c.req.raw,
    // Provide context, accessed via getContext()
    context: {
      user: await c.get('user')
    }
  })
  return response ?? c.notFound()
})
 
const server = serve({ fetch: app.fetch, port: 3000 })
 
// Enable WebSocket support for streams
telefunc.installWebSocket(server)

With the Node.js req object and res object (e.g. Express):

// server.js
// Environment: server
 
import express from 'express'
import { Telefunc } from 'telefunc/node'
 
const app = express()
const telefunc = new Telefunc()
 
app.all('/_telefunc', async (req, res, next) => {
  const handled = await telefunc.serve({
    req,
    res,
    // Provide context, accessed via getContext()
    context: {
      user: await getUser(req)
    }
  })
  if (!handled) next()
})
 
const server = app.listen(3000)
 
// Enable WebSocket support for streams
telefunc.installWebSocket(server)
// server.ts
// Environment: server
 
import express from 'express'
import { Telefunc } from 'telefunc/node'
 
const app = express()
const telefunc = new Telefunc()
 
app.all('/_telefunc', async (req, res, next) => {
  const handled = await telefunc.serve({
    req,
    res,
    // Provide context, accessed via getContext()
    context: {
      user: await getUser(req)
    }
  })
  if (!handled) next()
})
 
const server = app.listen(3000)
 
// Enable WebSocket support for streams
telefunc.installWebSocket(server)

Performance tip: prefer { req, res } over { request } when you have access to the raw Node.js objects (Express, raw http, Connect-style middleware). The req/res path reads the request body directly from the Node Readable and writes the response straight to the Node Writable, skipping the Web Streams conversion layer. Node's Web Streams implementation is slower than its internal streams; see nodejs/performance#134.

// server.js
// Environment: server
 
import { Telefunc } from 'telefunc/bun'
 
const telefunc = new Telefunc()
 
Bun.serve({
  port: 3000,
  // Enable WebSocket support for streams
  websocket: telefunc.websocket,
  async fetch(request, server) {
    const response = await telefunc.serve({
      request,
      server,
      // Provide context, accessed via getContext()
      context: {
        user: await getUser(request)
      }
    })
    if (response) return response
 
    return new Response('Not found', { status: 404 })
  }
})
// server.ts
// Environment: server
 
import { Telefunc } from 'telefunc/bun'
 
const telefunc = new Telefunc()
 
Bun.serve({
  port: 3000,
  // Enable WebSocket support for streams
  websocket: telefunc.websocket,
  async fetch(request, server) {
    const response = await telefunc.serve({
      request,
      server,
      // Provide context, accessed via getContext()
      context: {
        user: await getUser(request)
      }
    })
    if (response) return response
 
    return new Response('Not found', { status: 404 })
  },
})
// server.js
// Environment: server
 
import { Telefunc } from 'telefunc/deno'
 
const telefunc = new Telefunc()
 
Deno.serve({ port: 3000 }, async (request, info) => {
  const response = await telefunc.serve({
    request,
    info,
    // Provide context, accessed via getContext()
    context: {
      user: await getUser(request)
    }
  })
  if (response) return response
 
  return new Response('Not found', { status: 404 })
})
// server.ts
// Environment: server
 
import { Telefunc } from 'telefunc/deno'
 
const telefunc = new Telefunc()
 
Deno.serve({ port: 3000 }, async (request, info) => {
  const response = await telefunc.serve({
    request,
    info,
    // Provide context, accessed via getContext()
    context: {
      user: await getUser(request)
    }
  })
  if (response) return response
 
  return new Response('Not found', { status: 404 })
})
// worker.js
// Environment: server
 
import { Telefunc } from 'telefunc/cloudflare'
 
const telefunc = new Telefunc({
  // Provide context, accessed via getContext()
  context: async (request, env) => ({
    user: await getUser(request, env)
  })
})
 
// Enable streams
export const TelefuncDurableObject = telefunc.TelefuncDurableObject
 
export default {
  async fetch(request, env, ctx) {
    const response = await telefunc.serve({ request, env, ctx })
    if (response) return response
 
    return new Response('Not found', { status: 404 })
  }
}
// worker.ts
// Environment: server
 
import { Telefunc } from 'telefunc/cloudflare'
 
const telefunc = new Telefunc({
  // Provide context, accessed via getContext()
  context: async (request, env: Env) => ({
    user: await getUser(request, env)
  })
})
 
// Enable streams
export const TelefuncDurableObject = telefunc.TelefuncDurableObject
 
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext) {
    const response = await telefunc.serve({ request, env, ctx })
    if (response) return response
 
    return new Response('Not found', { status: 404 })
  },
}

On Cloudflare the context is set in a separate function from the request handler. (Because the context function runs in a Durable Object, whereas the request handler doesn't.)

On Cloudflare new Telefunc also takes bindingName, kvBindingName, scale, locationFallback, jurisdiction, and more — see Stream on Cloudflare > Configuration.

Add the Durable Object and KV bindings to your wrangler.jsonc:

{
  "durable_objects": {
    "bindings": [
      { "name": "TelefuncDurableObject", "class_name": "TelefuncDurableObject" }
    ]
  },
  "kv_namespaces": [
    { "binding": "TelefuncKV", "id": "your-kv-namespace-id" }
  ],
  "migrations": [
    { "tag": "v1", "new_classes": ["TelefuncDurableObject"] }
  ]
}

See Stream on Cloudflare for scaling, distributed broadcast, delivery guarantees, and Durable Object configuration.

See also:

Methods

MethodRuntimeDescription
serve(input)allProcess a request and return the response. The input shape ({ request }, { req, res }, { request, env, ctx }, …) and return type vary by runtime — see Return.
installWebSocket(server)NodeEnable WebSocket channels on your HTTP server. Idempotent (calling it multiple times is safe). (The Node.js adapter auto-detects your HTTP server from the request socket.)
websocketBunThe WebSocket handler — pass it to Bun.serve({ websocket }).
TelefuncDurableObjectCloudflareThe Durable Object class to export — see Stream on Cloudflare.

Return

telefunc.serve() returns:

RuntimeReturnsMeaning
Node.js ({ request })Response | undefinedundefined if not a Telefunc request
Node.js ({ req, res })booleanfalse if not a Telefunc request
BunResponse | undefinedundefined if not a Telefunc request
DenoResponse | undefinedundefined if not a Telefunc request
CloudflareResponse | undefinedundefined if not a Telefunc request

telefunc.serve() returns a falsy value (undefined or false) for non-Telefunc requests, so that you can chain it with other handlers.

See also