// define on server:
export const sayHello = (x, y) => `${x}, meet ${y}.`
sayHello.rpc = true
// call on client:
const hello = await sayHello("Backend", "Frontend")
console.log(hello)
meet Frontend.
RPC for the Rest of Us.
Prim+RPC bridges incompatible environments in JavaScript. Call functions defined on the server as if they exist on the client, without the setup, event mapping, or wrappers.
It's Just JavaScript
If you know JavaScript basics, you know how to use Prim+RPC.
No Type Guessing
Get full type definitions in your client using TypeScript or JSDoc.
Zero Client Generation
Calls are generated at runtime, skip the build step, if you want.
Bring Your Own Server
It's framework agnostic and includes lots of popular integrations.
Choose Your Client
Don't like the default method of sending requests? Swap it out.
Transport-Agnostic
Bridge client/server, web workers, proceses and more. It's not just HTTP.
Write a Function. Call It. Done.
Prim+RPC is designed to work with your existing tools. It's sole focus is to create and respond to RPC, not to dicate what tools that you use to send it.
Write your function
No magic involved: they're just plain JavaScript functions.
export function sayHello() {
return "Hello world!"
}
// This property signals to Prim+RPC that this function can be exposed
sayHello.rpc = true
Create the server
Prim+RPC supports your existing server framework.
import { createPrimServer } from "@doseofted/prim-rpc"
import { primFetch } from "@doseofted/prim-rpc-plugins/server-fetch"
import * as module from "./module"
// Server routes are automatically created for your functions
export default primFetch({
prim: createPrimServer({ module }),
})
export type Module = typeof module
Create the client
Prim+RPC handles the client/server dance.
import { createPrimClient } from "@doseofted/prim-rpc"
import { createMethodPlugin } from "@doseofted/prim-rpc-plugins/browser-fetch"
import type { Module } from "../server"
// The Prim client knows how to call functions on the server
export default createPrimClient<Module>({
endpoint: "http://localhost:3000/prim",
methodPlugin: createMethodPlugin(),
})
Call your function
No wrappers or client generation. Just call the function.
import client from "./prim"
// Function calls are automatically translated into RPC in the background
const message = await client.sayHello()
console.log(message) // Hello world!
It Works Everywhere. With Everything.
Prim+RPC works in all JavaScript envrionments: Node, Deno, Bun, browser, wherever. It supports many frameworks already and can be extended to work with any framework.
Oh, but that's not all.
Prim+RPC does the heavy lifting so you can use JavaScript features between server and client that would otherwise be difficult.
Handle Files
Files and Blobs are fully supported without all of the extra work.
Use Callbacks
Use callbacks between server and client: great for real-time events.
Advanced Types Supported
Use a custom JSON handler to support Dates, RegExps, Errors, and more.
Throw Errors
No error code mapping needed. Errors on the server are errors on the client.
Forms Supported
You don't need to process HTML forms. Supports all fields, including files.
Build a Public API
Build an API either for internal usage or to share with the world.
Batch RPCs
Multiple function calls are batched into single requests easily.
Share Only What's Allowed
Only the functions you explicitly export and mark as RPC are callable.
Generate Documentation
Build documentation of your functions directly from your existing TypeDoc.
Modular & Test Friendly
Function logic is separate from the transport, makes testing easy.
It's Available Now. Right Now.
Easy to setup, lots of features, and open source. Try it out!