mirror of
https://github.com/nvms/prsm.git
synced 2025-12-16 16:10:54 +00:00
registerCommand -> exposeCommand
This commit is contained in:
parent
978fd71d85
commit
6e153b1b44
@ -58,7 +58,7 @@ const server = new MeshServer({
|
|||||||
redisOptions: { host: "localhost", port: 6379 },
|
redisOptions: { host: "localhost", port: 6379 },
|
||||||
});
|
});
|
||||||
|
|
||||||
server.registerCommand("echo", async (ctx) => {
|
server.exposeCommand("echo", async (ctx) => {
|
||||||
return `echo: ${ctx.payload}`;
|
return `echo: ${ctx.payload}`;
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -296,7 +296,7 @@ These can be used to implement custom commands or manage room state manually if
|
|||||||
You can guard room joins using command middleware, just like any other command. The built-in room join command is "mesh/join-room", and the payload contains a `roomName` string:
|
You can guard room joins using command middleware, just like any other command. The built-in room join command is "mesh/join-room", and the payload contains a `roomName` string:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
server.addMiddleware(async (ctx) => {
|
server.useMiddleware(async (ctx) => {
|
||||||
if (ctx.command === "mesh/join-room") {
|
if (ctx.command === "mesh/join-room") {
|
||||||
const { roomName } = ctx.payload;
|
const { roomName } = ctx.payload;
|
||||||
const meta = await server.connectionManager.getMetadata(ctx.connection);
|
const meta = await server.connectionManager.getMetadata(ctx.connection);
|
||||||
@ -444,7 +444,7 @@ You can associate data like user IDs, tokens, or custom attributes with a connec
|
|||||||
Metadata can be any JSON-serializable object, including nested structures. Updates fully replace the previous value—partial updates (patches) are not supported. While there is no hard size limit, large metadata objects may impact Redis performance.
|
Metadata can be any JSON-serializable object, including nested structures. Updates fully replace the previous value—partial updates (patches) are not supported. While there is no hard size limit, large metadata objects may impact Redis performance.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
server.registerCommand("authenticate", async (ctx) => {
|
server.exposeCommand("authenticate", async (ctx) => {
|
||||||
// maybe do some actual authentication here
|
// maybe do some actual authentication here
|
||||||
const { userId } = ctx.payload;
|
const { userId } = ctx.payload;
|
||||||
const token = encode({
|
const token = encode({
|
||||||
@ -711,11 +711,11 @@ Middleware can be applied globally to all commands or specifically to individual
|
|||||||
Applied to every command received by the server.
|
Applied to every command received by the server.
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
server.addMiddleware(async (ctx) => {
|
server.useMiddleware(async (ctx) => {
|
||||||
console.log(`Received command: ${ctx.command} from ${ctx.connection.id}`);
|
console.log(`Received command: ${ctx.command} from ${ctx.connection.id}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
server.addMiddleware(async (ctx) => {
|
server.useMiddleware(async (ctx) => {
|
||||||
const metadata = await server.connectionManager.getMetadata(ctx.connection);
|
const metadata = await server.connectionManager.getMetadata(ctx.connection);
|
||||||
if (!metadata?.userId) {
|
if (!metadata?.userId) {
|
||||||
throw new Error("Unauthorized");
|
throw new Error("Unauthorized");
|
||||||
@ -741,7 +741,7 @@ const validateProfileUpdate = async (ctx) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
server.registerCommand(
|
server.exposeCommand(
|
||||||
"update-profile",
|
"update-profile",
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
// ..
|
// ..
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export class CommandManager {
|
|||||||
* @param {SocketMiddleware[]} [middlewares=[]] - An optional array of middleware functions to apply to the command. Defaults to an empty array.
|
* @param {SocketMiddleware[]} [middlewares=[]] - An optional array of middleware functions to apply to the command. Defaults to an empty array.
|
||||||
* @throws {Error} May throw an error if the command registration or middleware addition fails.
|
* @throws {Error} May throw an error if the command registration or middleware addition fails.
|
||||||
*/
|
*/
|
||||||
registerCommand<T = any, U = any>(
|
exposeCommand<T = any, U = any>(
|
||||||
command: string,
|
command: string,
|
||||||
callback: (context: MeshContext<T>) => Promise<U> | U,
|
callback: (context: MeshContext<T>) => Promise<U> | U,
|
||||||
middlewares: SocketMiddleware[] = []
|
middlewares: SocketMiddleware[] = []
|
||||||
@ -33,7 +33,7 @@ export class CommandManager {
|
|||||||
this.commands[command] = callback;
|
this.commands[command] = callback;
|
||||||
|
|
||||||
if (middlewares.length > 0) {
|
if (middlewares.length > 0) {
|
||||||
this.addMiddlewareToCommand(command, middlewares);
|
this.useMiddlewareWithCommand(command, middlewares);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ export class CommandManager {
|
|||||||
* @returns {void}
|
* @returns {void}
|
||||||
* @throws {Error} If the provided middlewares are not valid or fail validation (if applicable).
|
* @throws {Error} If the provided middlewares are not valid or fail validation (if applicable).
|
||||||
*/
|
*/
|
||||||
addMiddleware(...middlewares: SocketMiddleware[]): void {
|
useMiddleware(...middlewares: SocketMiddleware[]): void {
|
||||||
this.globalMiddlewares.push(...middlewares);
|
this.globalMiddlewares.push(...middlewares);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ export class CommandManager {
|
|||||||
* @param {SocketMiddleware[]} middlewares - An array of middleware functions to be added to the command.
|
* @param {SocketMiddleware[]} middlewares - An array of middleware functions to be added to the command.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
addMiddlewareToCommand(
|
useMiddlewareWithCommand(
|
||||||
command: string,
|
command: string,
|
||||||
middlewares: SocketMiddleware[]
|
middlewares: SocketMiddleware[]
|
||||||
): void {
|
): void {
|
||||||
|
|||||||
@ -216,12 +216,12 @@ export class MeshServer extends WebSocketServer {
|
|||||||
* @param {SocketMiddleware[]} [middlewares=[]] - An optional array of middleware functions to apply to the command. Defaults to an empty array.
|
* @param {SocketMiddleware[]} [middlewares=[]] - An optional array of middleware functions to apply to the command. Defaults to an empty array.
|
||||||
* @throws {Error} May throw an error if the command registration or middleware addition fails.
|
* @throws {Error} May throw an error if the command registration or middleware addition fails.
|
||||||
*/
|
*/
|
||||||
registerCommand<T = any, U = any>(
|
exposeCommand<T = any, U = any>(
|
||||||
command: string,
|
command: string,
|
||||||
callback: (context: MeshContext<T>) => Promise<U> | U,
|
callback: (context: MeshContext<T>) => Promise<U> | U,
|
||||||
middlewares: SocketMiddleware[] = []
|
middlewares: SocketMiddleware[] = []
|
||||||
) {
|
) {
|
||||||
this.commandManager.registerCommand(command, callback, middlewares);
|
this.commandManager.exposeCommand(command, callback, middlewares);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -232,8 +232,8 @@ export class MeshServer extends WebSocketServer {
|
|||||||
* @returns {void}
|
* @returns {void}
|
||||||
* @throws {Error} If the provided middlewares are not valid or fail validation (if applicable).
|
* @throws {Error} If the provided middlewares are not valid or fail validation (if applicable).
|
||||||
*/
|
*/
|
||||||
addMiddleware(...middlewares: SocketMiddleware[]): void {
|
useMiddleware(...middlewares: SocketMiddleware[]): void {
|
||||||
this.commandManager.addMiddleware(...middlewares);
|
this.commandManager.useMiddleware(...middlewares);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,11 +243,11 @@ export class MeshServer extends WebSocketServer {
|
|||||||
* @param {SocketMiddleware[]} middlewares - An array of middleware functions to be added to the command.
|
* @param {SocketMiddleware[]} middlewares - An array of middleware functions to be added to the command.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
addMiddlewareToCommand(
|
useMiddlewareWithCommand(
|
||||||
command: string,
|
command: string,
|
||||||
middlewares: SocketMiddleware[]
|
middlewares: SocketMiddleware[]
|
||||||
): void {
|
): void {
|
||||||
this.commandManager.addMiddlewareToCommand(command, middlewares);
|
this.commandManager.useMiddlewareWithCommand(command, middlewares);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
@ -492,7 +492,7 @@ export class MeshServer extends WebSocketServer {
|
|||||||
// #region Command Registration
|
// #region Command Registration
|
||||||
|
|
||||||
private registerBuiltinCommands() {
|
private registerBuiltinCommands() {
|
||||||
this.registerCommand<
|
this.exposeCommand<
|
||||||
{ channel: string; historyLimit?: number },
|
{ channel: string; historyLimit?: number },
|
||||||
{ success: boolean; history?: string[] }
|
{ success: boolean; history?: string[] }
|
||||||
>("mesh/subscribe-channel", async (ctx) => {
|
>("mesh/subscribe-channel", async (ctx) => {
|
||||||
@ -527,7 +527,7 @@ export class MeshServer extends WebSocketServer {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand<{ channel: string }, boolean>(
|
this.exposeCommand<{ channel: string }, boolean>(
|
||||||
"mesh/unsubscribe-channel",
|
"mesh/unsubscribe-channel",
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { channel } = ctx.payload;
|
const { channel } = ctx.payload;
|
||||||
@ -544,7 +544,7 @@ export class MeshServer extends WebSocketServer {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.registerCommand<
|
this.exposeCommand<
|
||||||
{ roomName: string },
|
{ roomName: string },
|
||||||
{ success: boolean; present: string[] }
|
{ success: boolean; present: string[] }
|
||||||
>("mesh/join-room", async (ctx) => {
|
>("mesh/join-room", async (ctx) => {
|
||||||
@ -556,7 +556,7 @@ export class MeshServer extends WebSocketServer {
|
|||||||
return { success: true, present };
|
return { success: true, present };
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand<{ roomName: string }, { success: boolean }>(
|
this.exposeCommand<{ roomName: string }, { success: boolean }>(
|
||||||
"mesh/leave-room",
|
"mesh/leave-room",
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { roomName } = ctx.payload;
|
const { roomName } = ctx.payload;
|
||||||
@ -567,7 +567,7 @@ export class MeshServer extends WebSocketServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private registerRecordCommands() {
|
private registerRecordCommands() {
|
||||||
this.registerCommand<
|
this.exposeCommand<
|
||||||
{ recordId: string; mode?: "patch" | "full" },
|
{ recordId: string; mode?: "patch" | "full" },
|
||||||
{ success: boolean; record?: any; version?: number }
|
{ success: boolean; record?: any; version?: number }
|
||||||
>("mesh/subscribe-record", async (ctx) => {
|
>("mesh/subscribe-record", async (ctx) => {
|
||||||
@ -600,7 +600,7 @@ export class MeshServer extends WebSocketServer {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand<{ recordId: string }, boolean>(
|
this.exposeCommand<{ recordId: string }, boolean>(
|
||||||
"mesh/unsubscribe-record",
|
"mesh/unsubscribe-record",
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { recordId } = ctx.payload;
|
const { recordId } = ctx.payload;
|
||||||
@ -612,7 +612,7 @@ export class MeshServer extends WebSocketServer {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.registerCommand<
|
this.exposeCommand<
|
||||||
{ recordId: string; newValue: any },
|
{ recordId: string; newValue: any },
|
||||||
{ success: boolean }
|
{ success: boolean }
|
||||||
>("mesh/publish-record-update", async (ctx) => {
|
>("mesh/publish-record-update", async (ctx) => {
|
||||||
@ -639,7 +639,7 @@ export class MeshServer extends WebSocketServer {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand<
|
this.exposeCommand<
|
||||||
{ roomName: string },
|
{ roomName: string },
|
||||||
{ success: boolean; present: string[] }
|
{ success: boolean; present: string[] }
|
||||||
>("mesh/subscribe-presence", async (ctx) => {
|
>("mesh/subscribe-presence", async (ctx) => {
|
||||||
@ -672,7 +672,7 @@ export class MeshServer extends WebSocketServer {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand<{ roomName: string }, boolean>(
|
this.exposeCommand<{ roomName: string }, boolean>(
|
||||||
"mesh/unsubscribe-presence",
|
"mesh/unsubscribe-presence",
|
||||||
async (ctx) => {
|
async (ctx) => {
|
||||||
const { roomName } = ctx.payload;
|
const { roomName } = ctx.payload;
|
||||||
|
|||||||
@ -65,7 +65,7 @@ describe("MeshServer", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("clients can send a command and receive a response", async () => {
|
test("clients can send a command and receive a response", async () => {
|
||||||
server.registerCommand("echo", async (c) => `echo: ${c.payload}`);
|
server.exposeCommand("echo", async (c) => `echo: ${c.payload}`);
|
||||||
await clientA.connect();
|
await clientA.connect();
|
||||||
const response = await clientA.command("echo", "Hello, World!");
|
const response = await clientA.command("echo", "Hello, World!");
|
||||||
expect(response).toBe("echo: Hello, World!");
|
expect(response).toBe("echo: Hello, World!");
|
||||||
|
|||||||
@ -43,7 +43,7 @@ describe("MeshClient", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("command times out when server doesn't respond", async () => {
|
test("command times out when server doesn't respond", async () => {
|
||||||
server.registerCommand("never-responds", async () => new Promise(() => {}));
|
server.exposeCommand("never-responds", async () => new Promise(() => {}));
|
||||||
|
|
||||||
await client.connect();
|
await client.connect();
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ describe("MeshClient", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("thrown servers errors are serialized to the client", async () => {
|
test("thrown servers errors are serialized to the client", async () => {
|
||||||
server.registerCommand("throws-error", async () => {
|
server.exposeCommand("throws-error", async () => {
|
||||||
throw new Error("This is a test error");
|
throw new Error("This is a test error");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ describe("MeshClient", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("handles large payloads without issue", async () => {
|
test("handles large payloads without issue", async () => {
|
||||||
server.registerCommand("echo", async (ctx) => ctx.payload);
|
server.exposeCommand("echo", async (ctx) => ctx.payload);
|
||||||
await client.connect();
|
await client.connect();
|
||||||
|
|
||||||
const largeData = {
|
const largeData = {
|
||||||
|
|||||||
@ -56,7 +56,7 @@ describe.sequential("Multiple instances", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("broadcast should work across instances", async () => {
|
test("broadcast should work across instances", async () => {
|
||||||
serverA.registerCommand("broadcast", async (ctx) => {
|
serverA.exposeCommand("broadcast", async (ctx) => {
|
||||||
await serverA.broadcast("hello", "Hello!");
|
await serverA.broadcast("hello", "Hello!");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -97,13 +97,13 @@ describe.sequential("Multiple instances", () => {
|
|||||||
|
|
||||||
test("broadcastRoom should work across instances", async () => {
|
test("broadcastRoom should work across instances", async () => {
|
||||||
[serverA, serverB].forEach((server) =>
|
[serverA, serverB].forEach((server) =>
|
||||||
server.registerCommand("join-room", async (ctx) => {
|
server.exposeCommand("join-room", async (ctx) => {
|
||||||
await server.addToRoom(ctx.payload.room, ctx.connection);
|
await server.addToRoom(ctx.payload.room, ctx.connection);
|
||||||
return { joined: true };
|
return { joined: true };
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
serverA.registerCommand("broadcast-room", async (ctx) => {
|
serverA.exposeCommand("broadcast-room", async (ctx) => {
|
||||||
await serverA.broadcastRoom(
|
await serverA.broadcastRoom(
|
||||||
ctx.payload.room,
|
ctx.payload.room,
|
||||||
"room-message",
|
"room-message",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user