0.8.1 • Published 12 months ago
@badaimweeb/js-dtsocket v0.8.1
DTSocket: Move fast and break nothing
What is this?
DTSocket is a application layer protocol (Layer 7 in OSI) that is built on top of ProtoV2/V2d (L4/5).
This package is inspired by tRPC, but rather than sending through HTTP, it sends through ProtoV2/V2d.
Compatible with js-protov2d@1
.
🐉 This library is in BETA stage. Expect bugs and changes, but it has been battle-tested in some low-volume services and we have catched some bugs this way.
Usage
Create server:
// Create ProtoV2d server
import { Server, type Session } from "@badaimweeb/js-protov2d";
import z from "zod";
import { InitProcedureGenerator, DTSocketServer, type ServerContext } from "@badaimweeb/js-dtsocket";
let v2dServer = new Server({
port: 0,
privateKey,
publicKey // see js-protov2d for more info
});
// .on and .emit events. csEvents are events that the client can emit, and scEvents are events that the server can emit.
type EventTable = {
csEvents: {
test: (a: number) => void
},
scEvents: {
test: (a: number) => void
}
};
// This will be the global object that all procedures will have access to.
const gState: {
stored?: number;
} = {};
type LState = {
// You can put data that is connection/session-specific here.
}
let pGen = InitProcedureGenerator<ServerContext<typeof gState, LState, EventTable, Session>>();
// The procedure table
const procedureTable = {
normal: pGen
.input(z.object({ a: z.number(), b: z.number() }))
.resolve((gState, lState, input, socket) => {
return input.a + input.b;
}),
streaming: pGen
.input(z.void())
.resolve(async function* (gState, lState, input) {
for (let i = 0; i < 10; i++) {
yield i;
}
})
}
// And create the DTSocket server...
const dtServer = new DTSocketServer<ServerContext<typeof gState, LState, EventTable, Session, typeof procedureTable>>(procedureTable, gState);
// ...and exporting definitions for client to use.
export type ServerDef = typeof dtServer;
// It's important to drop the connection when the client disconnects and timed out.
v2dServer.on("dropConnection", (socket) => {
dtServer.removeSession(socket);
});
// Handle client connection
v2dServer.on("connection", async (socket) => {
// Upgrade to DTSocket
let dtSocket = await dtServer.processSession(socket);
// Handle client events
dtSocket.on("test", (a) => {
console.log(a);
// Emit server event
dtSocket.emit("test", a);
});
// Handle client connection timeout.
// When this event is fired, DTServer will disregard this connection and remove it from the session list.
// You may use this event to clean up resources. You cannot send messages to client.
dtSocket.on("internal:drop", () => {
// lState can be accessed at dtSocket.lState if you want to get state to clean up.
console.log("Client timed out");
});
});
// ...or you can handle it this way
dtServer.on("internal:new-session", dtSocket => {
// do stuff
});
// Handling client disconnection is also possible outside of the connection event.
dtServer.on("internal:remove-session", dtSocket => {
// do stuff like clean up.
});
Client to server:
import { connect, Session } from "@badaimweeb/js-protov2d";
import { DTSocketClient } from "@badaimweeb/js-dtsocket";
import type { ServerDef } from "server_somewhere";
// Connect to remote server using ProtoV2d...
let client = await connect({
url: `ws://address.here`,
publicKeys: [{
type: "key" | "hash",
value: "something"
}]
});
// ...and then upgrading to DTSocket...
let dtClient = new DTSocketClient<ServerDef>(client);
// Client can now use the procedures defined in the server.
let result = await dtClient.p.normal({ a: 1, b: 2 });
// or...
let result = await dtClient.procedure("normal")({ a: 1, b: 2 });
// Streaming/server events? No problem!
let stream = dtClient.sp.streaming();
// or...
let stream = dtClient.streamingProcedure("streaming")();
for await (let i of stream) {
console.log(i);
}
// Transmitting events? Also no problem!
dtClient.emit("test", 1);
// and listening to server events...
dtClient.on("test", (a) => {
console.log(a);
});
0.8.1
12 months ago
0.7.2
1 year ago
0.8.0
12 months ago
0.7.1
1 year ago
0.5.4
2 years ago
0.5.3
2 years ago
0.7.0
2 years ago
0.6.1
2 years ago
0.6.0
2 years ago
0.5.0
2 years ago
0.4.0
2 years ago
0.5.2
2 years ago
0.5.1
2 years ago
0.3.0
2 years ago
0.2.0
2 years ago
0.1.4
2 years ago
0.1.3
2 years ago
0.1.2
2 years ago
0.1.1
2 years ago
0.1.0
2 years ago