@element-ts/lithium
v0.1.4
Published
A type-safe remote function invocation library using websockets and TypeScript.
Downloads
27
Maintainers
Readme
Welcome to the lithium wiki! This is a work in progress and will be constantly updated. Below you will find pages to this wiki but also feel free to view some nice features and information about the package.
Wiki
To view the rest of the wiki, please visit here.
Summary
Lithium is a Typescript package available on NPM as a part of the @elemen-ts organization. It provides a simple yet very in depth medium of sending requests between clients and a server. It is all type safe only allowing invocation of implemented methods and requiring the parameters and return types are correct. Lithium also allows for peer-to-peer function invocation creating a network that is routed through a central server.
Example
Shared
You can make a shared package that contains the type definitions for what commands your websockets will implement.
commands.ts
import {LiCommandRegistryStructure} from "@element-ts/lithium";
export interface MyServerCommands extends LiCommandRegistryStructure {
changeFavoriteNumber: {
param: number;
return: void;
};
getFavoriteColor: {
param: void;
return: number;
};
}
export interface MyClientCommands extends LiCommandRegistryStructure {
favoriteNumberChanged: {
param: number;
return: void;
};
}
Server
server.ts
import {LiServer} from "@element-ts/lithium";
import {MyClientCommands, MyServerCommands} from "./playground-types";
const server: LiServer<MyServerCommands, MyClientCommands> = new LiServer({
port: 8080,
debug: true
});
let favoriteNumber: number = 42;
server.implement("getFavoriteColor", async(): Promise<number> => {
return favoriteNumber;
});
server.implement("changeFavoriteNumber", async(num: number): Promise<void> => {
favoriteNumber = num;
await server.broadcast("favoriteNumberChanged", favoriteNumber);
});
Client
client.ts
import {LiSocket} from "@element-ts/lithium";
import {MyServerCommands, MyClientCommands} from "./playground-types";
const socket: LiSocket<MyClientCommands, MyServerCommands> = await LiSocket.init({
address: "ws://localhost:8080",
debug: true
});
socket.implement("favoriteNumberChanged", async(num: number): Promise<void> => {
console.log(`Favorite number is now: ${num}!`);
await socket.invoke("changeFavoriteNumber", num + 1);
});
await socket.invoke("changeFavoriteNumber", 0);
Features
Implement/Invoke
Once you have a LiCommandRegistryStructure
(view docs on 'Command Registry') set up you can
simply implement()
and invoke()
the commands on both the clients and central server. These are type
checked off of your command registry and will make sure you not only are talking about a command that exists, but you
are providing the correct parameters and expecting the correct return type.
Async
Everything is written with promises so that you don't have to worry about the messy stuff underneath the scenes. If you are interested you can view the page on the underlying protocol that messages are sent via.
Typesafe
If you try to implement/invoke a method with the incorrect command name, parameter, or return value TypeScript will throw a compile time error. Whenever you are using lithium you will always know you are using the right types!
If you are interested in looking at the types that make Lithium work you can view the source code for them in the
LiCommandRegistry.ts
file found here.
Broadcast
The server can broadcast the invoking of a command to all clients and coalesce the returned messages together in a
mapping in parallel where you get an object that follows the type {[socketId: string]: T | undefined }
where T
is
the type the command returns. There is a possibility of undefined
because instead of using Promise.all()
, it uses
a custom promise handler that will not reject if a client throws an error, it will just make the resulting return
undefined for that singular client in the map. I think this makes most sense for the use of broadcasting.
You can read more about broadcasts on the broadcast page.
Peer-To-Peer
Another cool feature built into lithium is peer-to-peer command invocation. A LiSocket
actually takes three type
parameters. The third is SC
which stands for 'Sibling Commands' and follows the same LiCommandRegistryStructure
.
Once SC
is provided to a LiSocket
, you can access the implementSibling()
and invokeSibling()
methods. These
allow a client to talk to another client. To allow for peer-to-peer, when initializing a LiSocket
you must set the
allowPeerToPeer
property to true
in the config object. If you provide an sibling command but do not set the socket
to allow peer-to-peer the socket will respond as if the command does not exist.
You can read more about peer-to-peer command invoking on the peer-to-peer page.
About
Language
All of Lithium is written in TypeScript. If you do not know how to use TypeScript don't worry. It is completely compatible with JavaScript.
Why?
I wanted a really easy way to handle web-sockets in my projects and had some free time due to Covid-19.
Author/Maintainer
My name is Elijah Cobb. I am a computer science student at Michigan Technological University.