Telefunc Documentation
website·Indexed 33 days ago
https://telefunc.comA framework for building RPC-based applications with features including streaming primitives, channel-based communication via Channel and BroadcastChannel APIs, and integrations for Next.js, SvelteKit, Vike, and TanStack Query. It provides tools for file uploads and downloads, error handling with Abort(), and specialized packages like @telefunc/redis and @telefunc/rxjs.
What's inside Telefunc
- Telefunc allows developers to define functions on the server and call them directly in the browser. It replaces the need for manual REST or GraphQL API definitions by transforming server-side TypeScript files into thin HTTP clients for the frontend. Key features include automatic runtime validation for end-to-end type safety, seamless TypeScript integration (auto-import, refactoring), and support for streaming values (AI tokens, progress) and real-time features via channels and broadcasts.
Decouple frontend and backend development using a Telefunc Server
While Telefunc is often installed as Node.js server middleware (creating tight coupling), you can decouple frontend and backend development by implementing a 'Telefunc Server'.
In this architecture, a dedicated Node.js server is created solely to serve telefunctions. The frontend and the Telefunc Server are developed and deployed together, while the core backend (e.g., Ruby on Rails, another Node.js server) remains independent and can be deployed separately.
Telefunc Stream features and DX
Telefunc Stream provides several built-in developer experience features:
- Runtime type validation: Automatically validates client-to-server values against TypeScript types without requiring Zod.
- Automatic Transport: Selects the most performant transport (HTTP, SSE, or WebSocket) based on the primitive used.
- Backpressure: Built-in automatic backpressure when the network is the bottleneck.
- Reconnection: Automatic recovery from network interruptions.
Scale Telefunc Stream on Cloudflare Workers
Telefunc provides a specialized adapter for Cloudflare Workers (telefunc/cloudflare) that uses Durable Objects to route channels. Because of this architecture, you do not need to configure a sticky load balancer or a separate broadcast transport; distributed broadcasting and channel routing are handled automatically.Understand Telefunc Distributed Broadcast architecture
Broadcasts in Telefunc are automatically fanned out across all regions. The process follows this flow: Publisher (Durable Object) → Authority DO (assigns sequence numbers) → Coordinators (one per active region) → Local Durable Objects (deliver to subscribers).
Key characteristics:
- Ordering: Messages for a specific
keyare processed by a single authority, ensuring subscribers receive messages in order with a monotonic sequence number. - Presence: Telefunc uses KV to track active subscribers with a 90-second TTL, refreshing every 30 seconds. If a Durable Object is evicted, the region is excluded from fan-out after the TTL expires.
- Ordering: Messages for a specific
Use serve() for low-level Telefunc HTTP handling
serve()is a stateless, side-effect-free function that converts a telefunction HTTP request into an HTTP response. It is designed to run in any runtime without an adapter. While useful for custom integrations, most applications should usenew Telefunc()instead, asserve()does not support WebSockets or Cloudflare Channels (Durable Objects).Optimize telefunction performance and data transfer
To maximize efficiency in Telefunc RPC, create tailored telefunctions instead of generic ones. Avoid returning superfluous data; if the client only needs to know the operation succeeded, return nothing (the HTTP 200 status code is sufficient). This is more efficient than REST or GraphQL as the required data is implicitly defined by the telefunction name.// TodoList.telefunc.js // Environment: server import { getContext } from 'telefunc' shield(onTodoComplete, [shield.type.number]) export async function onTodoComplete(id) { const { user } = getContext() await Task.update({ completed: true }).where({ id, author: user.id }) // No data returned: minimizes payload size }Implement permissions and access control with throw Abort()
Because telefunctions are public and can be called by anyone, you must explicitly protect them. Usethrow Abort()to interrupt a telefunction call when a user lacks the necessary permissions or is not logged in. This prevents unauthorized execution without treating the interruption as a system bug (unlikethrow new Error()).// run.telefunc.js // Environment: server import { Abort, getContext } from 'telefunc' export async function run(sql) { const { user } = getContext() // Only admins are allowed to run this telefunction if (user.isAdmin !== true) throw Abort() return await database.execute(sql) }Authorize streaming telefunctions
Authorization for streaming telefunctions must occur at "open time"—before the function returns or begins streaming data. UsegetContext()to check permissions andthrow Abort()to deny access. Because thecontext.useris captured via closure, it remains available for subsequent callback executions.// Environment: server import { getContext, Abort } from 'telefunc' export async function onTeamFeed(teamId: string, onMessage: (text: string) => void) { const context = getContext() if (!context.user?.teams.includes(teamId)) throw Abort() // Authorized — push messages to the client const unwatch = watchTeam(teamId, onMessage) context.onClose(unwatch) }Use throw Abort() for validation errors
Alternatively, you can usethrow Abort(someValue)to stop the execution of a telefunction and send a value back to the frontend. While functional, returning a value (e.g.,return { inputErrors }) is generally recommended overthrow Abort()because it makes the code's intent clearer and provides better TypeScript developer experience, as caught errors in TypeScript require casting.// SignUpForm.telefunc.ts // Environment: server import { Abort } from 'telefunc' export async function onFormSubmit(email: string, password: string) { if (!email) { throw Abort({ inputErrors: { email: 'Please enter your email.' } }) } /* ... */ }Install Telefunc for Vike
To use Telefunc in a Vike project, install thetelefuncpackage using your preferred package manager.npm install telefunc # or pnpm add telefunc # or bun add telefunc # or yarn add telefuncUnit test Telefunctions on the server
Telefunctions are plain functions and can be unit-tested by importing and calling them directly in a server environment. This eliminates the need for a running server, HTTP requests, or mocking.// hello.telefunc.test.ts // Environment: server import { onHello } from './hello.telefunc' test('onHello', async () => { expect(await onHello('Eve')).toBe('Welcome, Eve') })