Adding API endpoints takes a lot more time than writing functions, which in turn makes programming modern apps slow and frustrating. This project includes a server and client libraries that make it dramatically easier to do client-server communication.
On the server:
import * as t from 'io-ts';
const square = rpc(t.number, (n): number => {
return n * n;
});
On the client:
const m = await client.call("square", 5);
assert(m == 5);
Everything is typechecked. When you type await client.call("sq...
on the client, you get autocompletion with all available rpc calls, and the client knows the expected argument type and the return type. Attempting to make a non-existing rpc call, passing an argument of the wrong type, or expecting the wrong return type will not type check.
This makes programming client-server communication on typescript feel as easy and solid as a functional call. It's a delightful way to program.
I deliberately avoided setup details in the TLDR
section to give you a sense of how easy it is to program with ts-alias
once you're set up. Let's look at these details here.
First, install the ts-alias-server
library in your backend project:
npm i ts-alias-server io-ts
Then, add the following snippet to your utilities file somewhere in your project. (Typescript doesn't yet support partial type argument inference, and I haven't figured out how to avoid this step without this feature. Fortunately, you do this once per project and forget about it.)
import { _rpc } from 'ts-alias-server';
export type Context = void;
export const rpc = _rpc<Context>();
You can now use the rpc
function you defined above to create rpc calls:
import * as t from 'io-ts';
// Square a number
const square = rpc(t.number, (n): number => {
return n * n;
});
// Divide one number by another
const DivArgs = t.type({
num: t.number,
den: t.number,
});
const div = rpc(DivArgs, (args, _): number => {
return args.num / args.den;
});
Finally, let's pull these together and start the server:
import { AliasServer } from 'ts-alias-server';
const channels = { square, div };
export type channels = typeof channels;
const server = new AliasServer<Context, channels>({
channels,
port: 443,
onContext: () => {},
});
server.start();
That's it! The server should be up and running, waiting to respond to client requests.
Now install the ts-alias-client
library in your frontend project:
npm i ts-alias-client
Create a client connection like this:
import { AliasClient } from 'ts-alias-client';
import type { channels } from './SERVER_PROJECT/TYPE_DEFINITIONS.ts';
const client = new AliasClient<channels>({
url: "ws://localhost:443",
onContext: () => {},
WebSocket,
});
That's it! You can start making rpc calls:
const k = await client.call("div", { num: 30, den: 6 });