diff --git a/packages/mesh/README.md b/packages/mesh/README.md index 40128a3..7f87cfc 100644 --- a/packages/mesh/README.md +++ b/packages/mesh/README.md @@ -58,7 +58,7 @@ const server = new MeshServer({ redisOptions: { host: "localhost", port: 6379 }, }); -server.registerCommand("echo", async (ctx) => { +server.exposeCommand("echo", async (ctx) => { 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: ```ts -server.addMiddleware(async (ctx) => { +server.useMiddleware(async (ctx) => { if (ctx.command === "mesh/join-room") { const { roomName } = ctx.payload; 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. ```ts -server.registerCommand("authenticate", async (ctx) => { +server.exposeCommand("authenticate", async (ctx) => { // maybe do some actual authentication here const { userId } = ctx.payload; 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. ```ts -server.addMiddleware(async (ctx) => { +server.useMiddleware(async (ctx) => { 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); if (!metadata?.userId) { throw new Error("Unauthorized"); @@ -741,7 +741,7 @@ const validateProfileUpdate = async (ctx) => { } }; -server.registerCommand( +server.exposeCommand( "update-profile", async (ctx) => { // .. diff --git a/packages/mesh/src/server/managers/command.ts b/packages/mesh/src/server/managers/command.ts index 5a715ae..b58e226 100644 --- a/packages/mesh/src/server/managers/command.ts +++ b/packages/mesh/src/server/managers/command.ts @@ -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. * @throws {Error} May throw an error if the command registration or middleware addition fails. */ - registerCommand( + exposeCommand( command: string, callback: (context: MeshContext) => Promise | U, middlewares: SocketMiddleware[] = [] @@ -33,7 +33,7 @@ export class CommandManager { this.commands[command] = callback; if (middlewares.length > 0) { - this.addMiddlewareToCommand(command, middlewares); + this.useMiddlewareWithCommand(command, middlewares); } } @@ -45,7 +45,7 @@ export class CommandManager { * @returns {void} * @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); } @@ -56,7 +56,7 @@ export class CommandManager { * @param {SocketMiddleware[]} middlewares - An array of middleware functions to be added to the command. * @returns {void} */ - addMiddlewareToCommand( + useMiddlewareWithCommand( command: string, middlewares: SocketMiddleware[] ): void { diff --git a/packages/mesh/src/server/mesh-server.ts b/packages/mesh/src/server/mesh-server.ts index 5c6b32c..87dfc03 100644 --- a/packages/mesh/src/server/mesh-server.ts +++ b/packages/mesh/src/server/mesh-server.ts @@ -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. * @throws {Error} May throw an error if the command registration or middleware addition fails. */ - registerCommand( + exposeCommand( command: string, callback: (context: MeshContext) => Promise | U, 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} * @throws {Error} If the provided middlewares are not valid or fail validation (if applicable). */ - addMiddleware(...middlewares: SocketMiddleware[]): void { - this.commandManager.addMiddleware(...middlewares); + useMiddleware(...middlewares: SocketMiddleware[]): void { + 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. * @returns {void} */ - addMiddlewareToCommand( + useMiddlewareWithCommand( command: string, middlewares: SocketMiddleware[] ): void { - this.commandManager.addMiddlewareToCommand(command, middlewares); + this.commandManager.useMiddlewareWithCommand(command, middlewares); } // #endregion @@ -492,7 +492,7 @@ export class MeshServer extends WebSocketServer { // #region Command Registration private registerBuiltinCommands() { - this.registerCommand< + this.exposeCommand< { channel: string; historyLimit?: number }, { success: boolean; history?: string[] } >("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", async (ctx) => { const { channel } = ctx.payload; @@ -544,7 +544,7 @@ export class MeshServer extends WebSocketServer { } ); - this.registerCommand< + this.exposeCommand< { roomName: string }, { success: boolean; present: string[] } >("mesh/join-room", async (ctx) => { @@ -556,7 +556,7 @@ export class MeshServer extends WebSocketServer { return { success: true, present }; }); - this.registerCommand<{ roomName: string }, { success: boolean }>( + this.exposeCommand<{ roomName: string }, { success: boolean }>( "mesh/leave-room", async (ctx) => { const { roomName } = ctx.payload; @@ -567,7 +567,7 @@ export class MeshServer extends WebSocketServer { } private registerRecordCommands() { - this.registerCommand< + this.exposeCommand< { recordId: string; mode?: "patch" | "full" }, { success: boolean; record?: any; version?: number } >("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", async (ctx) => { const { recordId } = ctx.payload; @@ -612,7 +612,7 @@ export class MeshServer extends WebSocketServer { } ); - this.registerCommand< + this.exposeCommand< { recordId: string; newValue: any }, { success: boolean } >("mesh/publish-record-update", async (ctx) => { @@ -639,7 +639,7 @@ export class MeshServer extends WebSocketServer { } }); - this.registerCommand< + this.exposeCommand< { roomName: string }, { success: boolean; present: string[] } >("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", async (ctx) => { const { roomName } = ctx.payload; diff --git a/packages/mesh/src/tests/basic.test.ts b/packages/mesh/src/tests/basic.test.ts index 2a9b7a2..c0d17bd 100644 --- a/packages/mesh/src/tests/basic.test.ts +++ b/packages/mesh/src/tests/basic.test.ts @@ -65,7 +65,7 @@ describe("MeshServer", () => { }); 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(); const response = await clientA.command("echo", "Hello, World!"); expect(response).toBe("echo: Hello, World!"); diff --git a/packages/mesh/src/tests/client.test.ts b/packages/mesh/src/tests/client.test.ts index 6af336b..d4c7cbb 100644 --- a/packages/mesh/src/tests/client.test.ts +++ b/packages/mesh/src/tests/client.test.ts @@ -43,7 +43,7 @@ describe("MeshClient", () => { }); 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(); @@ -64,7 +64,7 @@ describe("MeshClient", () => { }); 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"); }); @@ -79,7 +79,7 @@ describe("MeshClient", () => { }); test("handles large payloads without issue", async () => { - server.registerCommand("echo", async (ctx) => ctx.payload); + server.exposeCommand("echo", async (ctx) => ctx.payload); await client.connect(); const largeData = { diff --git a/packages/mesh/src/tests/multiple-instance.test.ts b/packages/mesh/src/tests/multiple-instance.test.ts index 66a2787..a2e3c31 100644 --- a/packages/mesh/src/tests/multiple-instance.test.ts +++ b/packages/mesh/src/tests/multiple-instance.test.ts @@ -56,7 +56,7 @@ describe.sequential("Multiple instances", () => { }); test("broadcast should work across instances", async () => { - serverA.registerCommand("broadcast", async (ctx) => { + serverA.exposeCommand("broadcast", async (ctx) => { await serverA.broadcast("hello", "Hello!"); }); @@ -97,13 +97,13 @@ describe.sequential("Multiple instances", () => { test("broadcastRoom should work across instances", async () => { [serverA, serverB].forEach((server) => - server.registerCommand("join-room", async (ctx) => { + server.exposeCommand("join-room", async (ctx) => { await server.addToRoom(ctx.payload.room, ctx.connection); return { joined: true }; }) ); - serverA.registerCommand("broadcast-room", async (ctx) => { + serverA.exposeCommand("broadcast-room", async (ctx) => { await serverA.broadcastRoom( ctx.payload.room, "room-message",