Telefunc Documentation

website·Indexed 33 days ago

https://telefunc.com

A 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.

Tokens
28K
Snippets
141
Records
177
Agent score
66%

What's inside Telefunc

  1. Overview of Telefunc Remote Functions

    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.
  2. 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.

  3. 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.
  4. 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.
  5. 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 key are 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.
  6. 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 use new Telefunc() instead, as serve() does not support WebSockets or Cloudflare Channels (Durable Objects).
  7. 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
    }
  8. Implement permissions and access control with throw Abort()

    Because telefunctions are public and can be called by anyone, you must explicitly protect them. Use throw 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 (unlike throw 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)
    }
  9. Authorize streaming telefunctions

    Authorization for streaming telefunctions must occur at "open time"—before the function returns or begins streaming data. Use getContext() to check permissions and throw Abort() to deny access. Because the context.user is 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)
    }
  10. Use throw Abort() for validation errors

    Alternatively, you can use throw 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 over throw 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.'
          }
        })
      }
      /* ... */
    }
  11. Install Telefunc for Vike

    To use Telefunc in a Vike project, install the telefunc package using your preferred package manager.
    npm install telefunc
    # or
    pnpm add telefunc
    # or
    bun add telefunc
    # or
    yarn add telefunc
  12. Unit 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')
    })