Skip to content

Repository files navigation

alien-rpc

A type-safe RPC library for TypeScript that bridges the gap between your server and client with minimal boilerplate and maximum performance.

Key Features

  • Type-safe by default: Share types between server and client without manual effort.
  • Automatic Code Generation: CLI scans your routes and generates client-side calling code and server-side manifests.
  • Validation: Integrated with TypeBox for robust runtime validation using TypeScript types.
  • Middleware Support: Powered by alien-middleware for powerful, type-safe request context propagation.
  • Websocket Support: First-class support for websockets via crossws.
  • Flexible Formats: Supports JSON, JSON-Seq (for pagination/streaming), and raw Responses.

Installation

npm install alien-rpc @sinclair/typebox@0.34

Use TypeBox v0.34.x with alien-rpc.

Quick Start

1. Define a route

Create a file for your routes (e.g., server/api/hello.ts):

import{route}from'alien-rpc/service'// One path parameterexportconsthello=route('/hello/:name').get(async(name,{},ctx)=>{return{message: `Hello, ${name}!`}})// Multiple path parametersexportconstmultiple=route('/user/:id/post/:postId').get(async([id,postId],{},ctx)=>{return{ id, postId }})// No path parametersexportconstnoParams=route('/status').get(async({},ctx)=>{return{ok: true}})

2. Generate client & server manifests

Run the alien-rpc CLI to scan your routes and generate the necessary manifests:

npx alien-rpc './server/api/**/*.ts' --clientOutFile ./client/api.ts --serverOutFile ./server/api.ts

Tip

See CLI and Configuration for more details.

3. Use the client

In your client-side code:

import{defineClient}from'alien-rpc/client'importroutesfrom'./api.ts'constclient=defineClient(routes,{prefixUrl: '/api',})// Parameters can be passed directly if there's only one path paramconstresult=awaitclient.hello('World')console.log(result.message)// "Hello, World!"

4. Setup the server

Use the generated server manifest with any Hattip-compatible adapter. For example, using @hattip/adapter-node:

import{createServer}from'@hattip/adapter-node'import{compileRoutes}from'alien-rpc/service'import{chain}from'alien-rpc/middleware'importroutesfrom'./server/api.ts'consthandler=chain(compileRoutes(routes,{prefix: '/api/',}))createServer(handler).listen(3000)

Core Concepts

Middlewares and Context

Use route.use() to create factories with shared middlewares. Middlewares can provide context (like a database or user session) to your handlers.

import{chain}from'alien-rpc/middleware'import{route}from'alien-rpc/service'constwithUser=chain(asyncctx=>{constuser=awaitgetUser(ctx.request)return{ user }})constuserRoute=route.use(withUser)exportconstgetProfile=userRoute('/me').get(async(_,ctx)=>{returnctx.user// Type-safe access to user!})

Tip

See Middlewares and Context for more details.

Validation Constraints

Use TypeScript types to define validation rules. The generator automatically converts these to TypeBox schemas.

importtype{t}from'alien-rpc/service'exportconstupdateBio=route('/bio').post(async({ bio }: {bio: string&t.MaxLength<140>})=>{// bio is guaranteed to be <= 140 chars})

Path Parameter Coercion

Path parameters are automatically coerced based on the types defined in your handler's signature. Supported types include string and number.

exportconstgetById=route('/item/:id').get(async(id: number)=>{// id is guaranteed to be a number!})

Tip

See Validation and Coercion for more details.

Websockets

Define websocket routes that share the same connection:

exportconstchat=route.ws(ctx=>{ctx.on('message',msg=>{ctx.send({echo: msg})})})

Tip

See Websockets for more details.

Pagination and Streaming

Support efficient data transfer for lists and large datasets.

exportconstlistItems=route('/items').get(asyncfunction*({ offset =0}){constitems=awaitdb.items.findMany({skip: offset,take: 10})for(constitemofitems)yielditemreturnpaginate(this,{next: {offset: offset+10},})})

Tip

See Pagination and Streaming for more details.

Examples

Check out the examples directory for minimal, ready-to-run projects using different stacks:

  • Astro: Integration with Astro's server-side routes and client-side components.
  • Vite + Node.js: A full-stack setup with a Node.js backend proxied through Vite.
  • Vite + Cloudflare Workers: Deploying to Cloudflare Workers using Vite and @cloudflare/vite-plugin.

For a package-local example of the umbrella subpath imports, see examples/full-stack.ts.

Configuration

For larger projects, use an alien-rpc.config.ts file:

import{defineConfig}from'alien-rpc/config'exportdefaultdefineConfig({include: ['./server/api/**/*.ts'],outDir: './src/generated',clientOutFile: 'client.ts',serverOutFile: 'server.ts',})

Tip

See CLI and Configuration for more details.

License

MIT

About

Type-safe RPC with generated runtime validation, REST semantics, websockets, and json-seq streams

Topics

Resources

Stars

26 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages