Template
1
0

feat: checkpoint

This commit is contained in:
2025-11-23 22:57:43 +01:00
parent 7df57522d2
commit 5d45e273ee
160 changed files with 10160 additions and 1476 deletions

View File

@@ -0,0 +1,81 @@
import type { Params } from "@valkyr/json-rpc";
import { SocketRegistry } from "./sockets.ts";
export class Channels {
readonly #channels = new Map<string, SocketRegistry>();
/**
* Add a new channel.
*
* @param channel
*/
add(channel: string): this {
this.#channels.set(channel, new SocketRegistry());
return this;
}
/**
* Deletes a channel.
*
* @param channel
*/
del(channel: string): this {
this.#channels.delete(channel);
return this;
}
/**
* Add socket to the given channel. If the channel does not exist it is
* automatically created.
*
* @param channel - Channel to add socket to.
* @param socket - Socket to add to the channel.
*/
join(channel: string, socket: WebSocket): this {
const sockets = this.#channels.get(channel);
if (sockets === undefined) {
this.#channels.set(channel, new SocketRegistry().add(socket));
} else {
sockets.add(socket);
}
return this;
}
/**
* Remove a socket from the given channel.
*
* @param channel - Channel to leave.
* @param socket - Socket to remove from the channel.
*/
leave(channel: string, socket: WebSocket): this {
this.#channels.get(channel)?.del(socket);
return this;
}
/**
* Sends a JSON-RPC notification to all sockets in given channel.
*
* @param channel - Channel to emit method to.
* @param method - Method to send the notification to.
* @param params - Message data to send to the clients.
*/
notify(channel: string, method: string, params: Params): this {
this.#channels.get(channel)?.notify(method, params);
return this;
}
/**
* Transmits data to all registered WebSocket connections in the given channel.
* Data can be a string, a Blob, an ArrayBuffer, or an ArrayBufferView.
*
* @param channel - Channel to emit message to.
* @param data - Data to send to each connected socket in the channel.
*/
send(channel: string, data: string | ArrayBufferLike | Blob | ArrayBufferView): this {
this.#channels.get(channel)?.send(data);
return this;
}
}
export const channels = new Channels();

View File

@@ -0,0 +1,14 @@
{
"name": "@platform/socket",
"version": "0.0.0",
"private": true,
"type": "module",
"types": "types.d.ts",
"dependencies": {
"@platform/auth": "workspace:*",
"@platform/logger": "workspace:*",
"@platform/relay": "workspace:*",
"@platform/storage": "workspace:*",
"@valkyr/json-rpc": "npm:@jsr/valkyr__json-rpc@1.1.0"
}
}

38
platform/socket/server.ts Normal file
View File

@@ -0,0 +1,38 @@
import "./types.d.ts";
import { context, InternalServerError } from "@platform/relay";
import { getStorageContext, storage } from "@platform/storage";
import { SocketRegistry } from "./sockets.ts";
export const sockets = new SocketRegistry();
export default {
/**
* TODO ...
*/
bootstrap: async (): Promise<void> => {
Object.defineProperties(context, {
/**
* TODO ...
*/
sockets: {
get() {
const sockets = storage.getStore()?.sockets;
if (sockets === undefined) {
throw new InternalServerError("Sockets not defined.");
}
return sockets;
},
},
});
},
/**
* TODO ...
*/
resolve: async (): Promise<void> => {
const context = getStorageContext();
context.sockets = sockets;
},
};

View File

@@ -0,0 +1,49 @@
import type { Params } from "@valkyr/json-rpc";
export class SocketRegistry {
readonly #sockets = new Set<WebSocket>();
/**
* Add a socket to the pool.
*
* @param socket - WebSocket to add.
*/
add(socket: WebSocket): this {
this.#sockets.add(socket);
return this;
}
/**
* Remove a socket from the pool.
*
* @param socket - WebSocket to remove.
*/
del(socket: WebSocket): this {
this.#sockets.delete(socket);
return this;
}
/**
* Sends a JSON-RPC notification to all connected sockets.
*
* @param method - Method to send the notification to.
* @param params - Message data to send to the clients.
*/
notify(method: string, params: Params): this {
this.send(JSON.stringify({ jsonrpc: "2.0", method, params }));
return this;
}
/**
* Transmits data to all registered WebSocket connections. Data can be a string,
* a Blob, an ArrayBuffer, or an ArrayBufferView.
*
* @param data - Data to send to each connected socket.
*/
send(data: string | ArrayBufferLike | Blob | ArrayBufferView): this {
this.#sockets.forEach((socket) => {
socket.send(data);
});
return this;
}
}

22
platform/socket/types.d.ts vendored Normal file
View File

@@ -0,0 +1,22 @@
import "@platform/relay";
import "@platform/storage";
import { SocketRegistry } from "./sockets.ts";
declare module "@platform/storage" {
interface StorageContext {
/**
* TODO ...
*/
sockets?: SocketRegistry;
}
}
declare module "@platform/relay" {
export interface ServerContext {
/**
* TODO ...
*/
sockets: SocketRegistry;
}
}