
SpeedAPI wire protocol implementation
This library provides a SpeedAPI implementation for JS and TS in all major environments (browser, node, etc.). Install it with:
npm i @speedapi/driver
Also install a transport level library according to your environment:
npm i @speedapi/node
for Node.JS- don't see an appropriate transport here? implement your own
You don't need additional libraries if you just use the Serializer
class.
If you're using a BigInt polyfill, add this as close to entry as possible:
import * as speedapi from "@speedapi/driver";
speedapi.repr.BigInteger.polyfillMode = "radix";
speedapi.repr.BigInteger.polyfillMode = "0x";
speedapi.repr.BigInteger.polyfillMode = "none";
What is SpeedAPI?
It's a platform-agnostic API and serialization tool specifically geared towards high-throughput realtime applications. You can read more about its features here
How do I use it?
There's a complete tutorial over here.
Implementing a transport layer
You just have to write glue code between an implementation of your desired transport protocol and SpeedAPI. The requirements for the underlying protocol are as follows:
- for datagram/packet/frame-based protocols like UDP: reliable and unordered - packets must not get lost, but their order may be mixed up (note that UDP doesn't fit this description as it's unreliable)
- for stream-based protocols like TCP: reliable and ordered - bytes must not get lost and their order must not get mixed up
You will need to write 3 or 4 classes depending on the protocol nature:
- A
Link
, Client
and Server
if the protocol is two-partied in nature, meaning there are only two active devices on the bus/network (e.g. UART) - A
Link
, Client
, Server
and Listener
if one server can serve multiple clients (the overwhelming majority of Internet protocols)
Note that for every client-to-server link there's a Client
object on the client and a Server
object on the server. There's only one Listener
on the server.
Link
This class acts as the reader/writer for SpeedAPI and should extend Duplex
. Its only job is to read and write Uint8Array
s. This class will be instantiated by you, therefore you can make the constructor of an arbitrary signature. Here's the skeleton for such a class:
import { Duplex } from "@speedapi/driver";
class MyLink extends Duplex {
constructor() { }
async write(data: Uint8Array): Promise<void> { }
async read(cnt: number): Promise<Uint8Array> { }
async close(): Promise<void> { }
}
Alternatively, you can extend from BufferedLink
if the underlying protocol implementation is event-driven, meaning it provides a "data has arrived" callback, but not a "read me N bytes" function.
import { BufferedLink } from "@speedapi/driver/transport/universal";
class MyLink extends BufferedLink {
constructor() {
someProtocol.on("bytesArrived", (data: Uint8Array) => {
this.dataArrived(data);
});
}
protected async dataWrite(data: Uint8Array): Promise<void> { }
override async close(): Promise<void> { }
}
Server
and Client
Very thin wrappers that tell SpeedAPI about your Link
while preserving type information.
Important: if you omit type information (e.g. if you're using plain JS to implement these two classes), your IDE will not be able to provide suggestions.
import { SpecSpaceGen, Session } from "@speedapi/driver";
class MyClient<Gen extends SpecSpaceGen> extends Session<Gen> {
constructor(specSpace: Gen ) {
super(specSpace, new MyLink(), "client");
}
}
class MyServer<Gen extends SpecSpaceGen> extends Session<Gen> {
constructor(specSpace: Gen ) {
super(specSpace, new MyLink(), "server");
}
}
Listener
(optional)
The notice from before applies here as well.
class MyListener<Gen extends SpecSpaceGen> {
constructor(specSpace: Gen, , callback: (server: MyServer<Gen>) => void ) {
someProtocol.on("clientConnected", (socket) => {
const session = new MyServer(specSpace, socket );
callback(session);
});
}
async close() { }
}
Testing
Warning: this repository uses a pnpm
lock file, hence you can't substitute it for npm
below.
git clone https://github.com/speedapi/driver-ts
cd driver-ts
pnpm i
pip3 install susc
pnpm test
TypeScript notice
This project relies heavily on typing. As such, the language server gets misled into thinking that an expression type is any
even though it's not just because the type is deeply nested. If you see a type error in your IDE that you think shouldn't be there or you're missing some autocomplete entries, try restarting your IDE and/or language server.