diff --git a/src/base-command.ts b/src/base-command.ts index 27ac76a7..52bacace 100644 --- a/src/base-command.ts +++ b/src/base-command.ts @@ -338,6 +338,7 @@ export abstract class AblyBaseCommand extends InteractiveBaseCommand { flags: BaseFlags, options?: { skipAuthInfo?: boolean; + autoConnect?: boolean; }, ): Promise { // Return cached client if it exists @@ -348,6 +349,7 @@ export abstract class AblyBaseCommand extends InteractiveBaseCommand { const client = await this.createAblyClientInternal(flags, { type: "realtime", skipAuthInfo: options?.skipAuthInfo, + autoConnect: options?.autoConnect, }); // Cache the client for reuse @@ -367,6 +369,7 @@ export abstract class AblyBaseCommand extends InteractiveBaseCommand { options?: { type?: "rest" | "realtime"; skipAuthInfo?: boolean; + autoConnect?: boolean; }, ): Promise { const clientType = options?.type || "realtime"; @@ -438,7 +441,16 @@ export abstract class AblyBaseCommand extends InteractiveBaseCommand { } // Create Realtime client - const client = new Ably.Realtime(clientOptions); + const autoConnect = options?.autoConnect !== false; + const client = new Ably.Realtime({ + ...clientOptions, + autoConnect, + }); + + // If autoConnect is disabled, return the client immediately without waiting for connection + if (!autoConnect) { + return client; + } // Wait for the connection to be established or fail return await new Promise((resolve, reject) => { diff --git a/src/chat-base-command.ts b/src/chat-base-command.ts index b422dd05..0fb13404 100644 --- a/src/chat-base-command.ts +++ b/src/chat-base-command.ts @@ -69,6 +69,7 @@ export abstract class ChatBaseCommand extends AblyBaseCommand { */ protected async createChatClient( flags: BaseFlags, + options?: { restOnly?: boolean }, ): Promise { // We already have a client, return it if (this._chatClient) { @@ -76,7 +77,11 @@ export abstract class ChatBaseCommand extends AblyBaseCommand { } // Create Ably Realtime client first - const realtimeClient = await this.createAblyRealtimeClient(flags); + // When restOnly is true, skip auto-connect to avoid opening a WebSocket + // for commands that only use REST API methods (send, delete, update, history, etc.) + const realtimeClient = await this.createAblyRealtimeClient(flags, { + autoConnect: options?.restOnly ? false : undefined, + }); // Mark auth info as shown after creating the client // to prevent duplicate "Using..." output on subsequent calls diff --git a/src/commands/rooms/messages/delete.ts b/src/commands/rooms/messages/delete.ts index 9dda89ef..48c6636b 100644 --- a/src/commands/rooms/messages/delete.ts +++ b/src/commands/rooms/messages/delete.ts @@ -41,7 +41,7 @@ export default class MessagesDelete extends ChatBaseCommand { const { args, flags } = await this.parse(MessagesDelete); try { - const chatClient = await this.createChatClient(flags); + const chatClient = await this.createChatClient(flags, { restOnly: true }); if (!chatClient) { return this.fail( @@ -51,8 +51,6 @@ export default class MessagesDelete extends ChatBaseCommand { ); } - this.setupConnectionStateLogging(chatClient.realtime, flags); - const room = await chatClient.rooms.get(args.room); if (!this.shouldOutputJson(flags)) { diff --git a/src/commands/rooms/messages/history.ts b/src/commands/rooms/messages/history.ts index e6ad8d57..fc807856 100644 --- a/src/commands/rooms/messages/history.ts +++ b/src/commands/rooms/messages/history.ts @@ -73,7 +73,7 @@ export default class MessagesHistory extends ChatBaseCommand { try { // Create Chat client - const chatClient = await this.createChatClient(flags); + const chatClient = await this.createChatClient(flags, { restOnly: true }); if (!chatClient) { return this.fail( diff --git a/src/commands/rooms/messages/reactions/remove.ts b/src/commands/rooms/messages/reactions/remove.ts index 8b119ad0..53a8eb70 100644 --- a/src/commands/rooms/messages/reactions/remove.ts +++ b/src/commands/rooms/messages/reactions/remove.ts @@ -47,7 +47,7 @@ export default class MessagesReactionsRemove extends ChatBaseCommand { try { // Create Chat client - const chatClient = await this.createChatClient(flags); + const chatClient = await this.createChatClient(flags, { restOnly: true }); if (!chatClient) { return this.fail( @@ -58,9 +58,6 @@ export default class MessagesReactionsRemove extends ChatBaseCommand { ); } - // Set up connection state logging - this.setupConnectionStateLogging(chatClient.realtime, flags); - // Get the room this.logCliEvent( flags, @@ -71,19 +68,6 @@ export default class MessagesReactionsRemove extends ChatBaseCommand { const chatRoom = await chatClient.rooms.get(room); this.logCliEvent(flags, "room", "gotRoom", `Got room handle for ${room}`); - // Subscribe to room status changes - this.setupRoomStatusHandler(chatRoom, flags, { roomName: room }); - - // Attach to the room - this.logCliEvent(flags, "room", "attaching", `Attaching to room ${room}`); - await chatRoom.attach(); - this.logCliEvent( - flags, - "room", - "attached", - `Successfully attached to room ${room}`, - ); - // Remove the reaction this.logCliEvent( flags, diff --git a/src/commands/rooms/messages/reactions/send.ts b/src/commands/rooms/messages/reactions/send.ts index 73cb05d1..962500b2 100644 --- a/src/commands/rooms/messages/reactions/send.ts +++ b/src/commands/rooms/messages/reactions/send.ts @@ -68,7 +68,7 @@ export default class MessagesReactionsSend extends ChatBaseCommand { } // Create Chat client - this.chatClient = await this.createChatClient(flags); + this.chatClient = await this.createChatClient(flags, { restOnly: true }); if (!this.chatClient) { return this.fail( @@ -79,9 +79,6 @@ export default class MessagesReactionsSend extends ChatBaseCommand { ); } - // Set up connection state logging - this.setupConnectionStateLogging(this.chatClient.realtime, flags); - // Get the room this.logCliEvent( flags, @@ -92,19 +89,6 @@ export default class MessagesReactionsSend extends ChatBaseCommand { const chatRoom = await this.chatClient.rooms.get(room); this.logCliEvent(flags, "room", "gotRoom", `Got room handle for ${room}`); - // Subscribe to room status changes - this.setupRoomStatusHandler(chatRoom, flags, { roomName: room }); - - // Attach to the room - this.logCliEvent(flags, "room", "attaching", `Attaching to room ${room}`); - await chatRoom.attach(); - this.logCliEvent( - flags, - "room", - "attached", - `Successfully attached to room ${room}`, - ); - // Prepare the reaction parameters const reactionParams: { name: string; diff --git a/src/commands/rooms/messages/send.ts b/src/commands/rooms/messages/send.ts index 829a3afc..7c4e63cb 100644 --- a/src/commands/rooms/messages/send.ts +++ b/src/commands/rooms/messages/send.ts @@ -98,7 +98,7 @@ export default class MessagesSend extends ChatBaseCommand { try { // Create Chat client - this.chatClient = await this.createChatClient(flags); + this.chatClient = await this.createChatClient(flags, { restOnly: true }); if (!this.chatClient) { return this.fail( @@ -108,9 +108,6 @@ export default class MessagesSend extends ChatBaseCommand { ); } - // Set up connection state logging - this.setupConnectionStateLogging(this.chatClient.realtime, flags); - // Parse metadata if provided let metadata: JsonObject | undefined; if (flags.metadata) { diff --git a/src/commands/rooms/messages/update.ts b/src/commands/rooms/messages/update.ts index b5882daf..dcd71e66 100644 --- a/src/commands/rooms/messages/update.ts +++ b/src/commands/rooms/messages/update.ts @@ -120,7 +120,7 @@ export default class MessagesUpdate extends ChatBaseCommand { ); } - const chatClient = await this.createChatClient(flags); + const chatClient = await this.createChatClient(flags, { restOnly: true }); if (!chatClient) { return this.fail( @@ -130,8 +130,6 @@ export default class MessagesUpdate extends ChatBaseCommand { ); } - this.setupConnectionStateLogging(chatClient.realtime, flags); - const room = await chatClient.rooms.get(args.room); if (!this.shouldOutputJson(flags)) { diff --git a/src/commands/rooms/occupancy/get.ts b/src/commands/rooms/occupancy/get.ts index 3f39a8ec..31e9c28a 100644 --- a/src/commands/rooms/occupancy/get.ts +++ b/src/commands/rooms/occupancy/get.ts @@ -34,7 +34,7 @@ export default class RoomsOccupancyGet extends ChatBaseCommand { try { // Create Chat client - this.chatClient = await this.createChatClient(flags); + this.chatClient = await this.createChatClient(flags, { restOnly: true }); if (!this.chatClient) { return this.fail( diff --git a/src/commands/rooms/reactions/send.ts b/src/commands/rooms/reactions/send.ts index 6878b756..e2910d7f 100644 --- a/src/commands/rooms/reactions/send.ts +++ b/src/commands/rooms/reactions/send.ts @@ -80,9 +80,6 @@ export default class RoomsReactionsSend extends ChatBaseCommand { ); } - // Set up connection state logging - this.setupConnectionStateLogging(this.chatClient.realtime, flags); - // Get the room this.logCliEvent( flags, diff --git a/test/unit/commands/rooms/messages/reactions/remove.test.ts b/test/unit/commands/rooms/messages/reactions/remove.test.ts index 0332eae0..92b41f5c 100644 --- a/test/unit/commands/rooms/messages/reactions/remove.test.ts +++ b/test/unit/commands/rooms/messages/reactions/remove.test.ts @@ -41,7 +41,7 @@ describe("rooms:messages:reactions:remove command", () => { import.meta.url, ); - expect(room.attach).toHaveBeenCalled(); + expect(room.attach).not.toHaveBeenCalled(); expect(room.messages.reactions.delete).toHaveBeenCalledWith( "msg-serial-123", { diff --git a/test/unit/commands/rooms/messages/reactions/send.test.ts b/test/unit/commands/rooms/messages/reactions/send.test.ts index 06a09b52..767d776b 100644 --- a/test/unit/commands/rooms/messages/reactions/send.test.ts +++ b/test/unit/commands/rooms/messages/reactions/send.test.ts @@ -34,7 +34,7 @@ describe("rooms:messages:reactions:send command", () => { import.meta.url, ); - expect(room.attach).toHaveBeenCalled(); + expect(room.attach).not.toHaveBeenCalled(); expect(room.messages.reactions.send).toHaveBeenCalledWith( "msg-serial-123", {