Skip to content

[DX-790] Add support for Chat message updates and deletes#168

Open
umair-ably wants to merge 1 commit intomainfrom
DX-790-chat-update-delete
Open

[DX-790] Add support for Chat message updates and deletes#168
umair-ably wants to merge 1 commit intomainfrom
DX-790-chat-update-delete

Conversation

@umair-ably
Copy link
Contributor

@umair-ably umair-ably commented Mar 12, 2026

Summary

  • Add ably rooms messages update and ably rooms messages delete commands for Chat message lifecycle management
  • Both commands support --json output, --description for operation details, and --client-id
  • The update command additionally supports --metadata and --headers flags for rich message updates
  • Fix return before this.fail() calls across 9 existing Chat commands to satisfy TypeScript control flow (since fail() returns never, the return makes it explicit to the type checker that execution stops)

Changes

File Change
src/commands/rooms/messages/update.ts New command: update a Chat message by serial
src/commands/rooms/messages/delete.ts New command: delete a Chat message by serial
src/commands/rooms/messages/index.ts Add update/delete examples to topic help
test/unit/commands/rooms/messages/update.test.ts Unit tests (349 lines): functionality, JSON output, metadata/headers validation, error handling
test/unit/commands/rooms/messages/delete.test.ts Unit tests (172 lines): functionality, JSON output, description passthrough, error handling
test/helpers/mock-ably-chat.ts Add update and delete mocks to MockRoomMessages
9 existing Chat commands Add return before this.fail() for correct control flow
README.md Auto-generated command docs

Review strategy

Step What to check Files
1. SDK API alignment Verify room.messages.update(serial, params, details) and room.messages.delete(serial, details) match the @ably/chat SDK signatures src/commands/rooms/messages/update.ts, delete.ts
2. Update command flags Confirm --metadata and --headers are properly parsed, validated (must be JSON objects, not arrays/primitives), and passed through update.ts lines 78-130
3. Delete command simplicity Delete is intentionally simpler (no metadata/headers) — verify it only accepts --description delete.ts
4. OperationDetails handling Both commands pass { description } when --description is set, undefined otherwise — verify no empty object leaks through update.ts, delete.ts
5. JSON output envelope Verify logJsonResult payloads include room, serial, versionSerial (and updatedText for update) Both commands, JSON tests
6. Human output format Check progress/success messages use formatResource(), formatProgress(), formatSuccess() correctly Both commands
7. return this.fail() fix Existing commands now have return before this.fail() — verify no behavior change, just type safety All 9 modified existing files
8. Mock completeness mock-ably-chat.ts update/delete mocks return shapes that match the SDK's Message type test/helpers/mock-ably-chat.ts
9. Test coverage All 5 required describe blocks present; edge cases for invalid JSON, non-object metadata/headers, API errors Both test files
10. Consistency with send Compare patterns (room get/attach flow, error handling, verbose logging) with existing messages/send.ts update.ts, delete.ts vs send.ts

Test plan

  • pnpm test:unit passes (including new update/delete tests)
  • pnpm exec eslint . shows 0 errors
  • ably rooms messages update <room> <serial> "new text" works against a real Chat room
  • ably rooms messages delete <room> <serial> works against a real Chat room
  • --json output produces valid NDJSON envelopes for both commands
  • --description is passed through correctly in both commands
  • Invalid --metadata/--headers (non-JSON, arrays, primitives) produce clear error messages

Summary by CodeRabbit

  • New Features

    • Added delete command to remove messages from Ably Chat rooms.
    • Added update command to modify existing messages in Ably Chat rooms.
  • Bug Fixes

    • Improved error handling across multiple commands to prevent further execution when initialization fails.
  • Documentation

    • Updated README with usage examples and descriptions for the new delete and update commands.
  • Tests

    • Added comprehensive test coverage for the new message management commands.

@umair-ably umair-ably requested a review from Copilot March 12, 2026 21:28
@vercel
Copy link

vercel bot commented Mar 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cli-web-cli Ready Ready Preview, Comment Mar 13, 2026 0:55am

Request Review

@umair-ably
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c5707be1-6f14-4bfe-8799-c877a33df4fe

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The PR adds two new CLI commands for Ably Chat room message operations (delete and update), refactors multiple existing commands to properly return early when chat client initialization fails, updates mock test helpers to support the new operations, and provides comprehensive test coverage for both new commands.

Changes

Cohort / File(s) Summary
Documentation
README.md
Added documentation for two new room messages commands with usage, arguments, examples, and descriptions.
Delete Message Command
src/commands/rooms/messages/delete.ts, test/unit/commands/rooms/messages/delete.test.ts
Introduced new CLI command to delete messages from chat rooms with OperationDetails support, lifecycle logging, and comprehensive unit tests covering deletion flow, description handling, JSON output, and error cases.
Update Message Command
src/commands/rooms/messages/update.ts, test/unit/commands/rooms/messages/update.test.ts
Introduced new CLI command to update message text with optional metadata and headers, including structured event logging, JSON envelope support, and extensive test coverage for argument validation, metadata/headers parsing, descriptions, and error handling.
Control Flow Fixes
src/commands/rooms/messages/history.ts, src/commands/rooms/messages/reactions/..., src/commands/rooms/messages/send.ts, src/commands/rooms/occupancy/..., src/commands/rooms/reactions/..., src/commands/rooms/typing/...
Refactored chat client initialization failures across 11 files to return the result of this.fail() instead of only calling it, ensuring proper early exit and preventing subsequent command execution after errors.
Test Infrastructure
test/helpers/mock-ably-chat.ts
Extended MockRoomMessages interface and createMockRoomMessages implementation to expose update and delete mock methods returning resolved objects with message metadata.
Index Updates
src/commands/rooms/messages/index.ts
Added example usage for the new update and delete commands to the rooms messages CLI index.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as Delete Command
    participant ChatClient
    participant Room
    participant MessageAPI as Messages API

    User->>CLI: Execute: rooms messages delete ROOM SERIAL
    CLI->>ChatClient: Initialize chat client
    ChatClient-->>CLI: Client ready
    CLI->>Room: Get and attach room
    Room-->>CLI: Room attached
    CLI->>MessageAPI: room.messages.delete(serial, OperationDetails?)
    MessageAPI-->>CLI: Deletion confirmed (versionSerial)
    CLI->>User: Output success message + versionSerial
Loading
sequenceDiagram
    participant User
    participant CLI as Update Command
    participant ChatClient
    participant Room
    participant MessageAPI as Messages API

    User->>CLI: Execute: rooms messages update ROOM SERIAL TEXT
    Note over CLI: Parse --metadata, --headers, --description flags
    CLI->>ChatClient: Initialize chat client
    ChatClient-->>CLI: Client ready
    CLI->>Room: Get and attach room
    Room-->>CLI: Room attached
    CLI->>MessageAPI: room.messages.update(serial, text, {metadata?, headers?, OperationDetails?})
    MessageAPI-->>CLI: Update confirmed (versionSerial)
    CLI->>User: Output success message + versionSerial
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Two new commands hop into place—delete and update with grace!
Error returns now flow just right, no lingering fallthrough in sight.
Tests stand guard with comprehensive cheer,
Mock helpers ready, the road is clear! 🎯

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding support for Chat message updates and deletes, which is the primary focus across the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch DX-790-chat-update-delete
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds new CLI commands for updating and deleting Ably Chat room messages, including unit tests and README command documentation, plus a small consistency tweak to ensure execution stops after fail() in several existing room commands.

Changes:

  • Add rooms messages update command with --metadata, --headers, and --description support and JSON/human output.
  • Add rooms messages delete command with optional --description and JSON/human output.
  • Update mocks, docs, and several existing commands to return this.fail(...) for consistent early-exit flow.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/unit/commands/rooms/messages/update.test.ts Unit tests covering update behavior, flag handling, JSON output, and error cases.
test/unit/commands/rooms/messages/delete.test.ts Unit tests covering delete behavior, description handling, JSON output, and API error propagation.
test/helpers/mock-ably-chat.ts Extends the room messages mock to include update and delete.
src/commands/rooms/messages/update.ts Implements the new message update command, including JSON parsing/validation for metadata and headers.
src/commands/rooms/messages/delete.ts Implements the new message delete command, including optional operation details.
src/commands/rooms/messages/index.ts Adds topic examples for the new update and delete subcommands.
README.md Adds generated documentation sections and TOC entries for the new commands.
src/commands/rooms/typing/subscribe.ts Returns after fail() when chat client init fails.
src/commands/rooms/typing/keystroke.ts Returns after fail() when chat client init fails.
src/commands/rooms/reactions/subscribe.ts Returns after fail() when chat client init fails.
src/commands/rooms/reactions/send.ts Returns after fail() when chat client init fails.
src/commands/rooms/occupancy/subscribe.ts Returns after fail() when chat client init fails.
src/commands/rooms/occupancy/get.ts Returns after fail() when chat client init fails.
src/commands/rooms/messages/send.ts Returns after fail() when chat client init fails.
src/commands/rooms/messages/reactions/subscribe.ts Returns after fail() when chat client init fails.
src/commands/rooms/messages/reactions/send.ts Returns after fail() when chat client init fails.
src/commands/rooms/messages/reactions/remove.ts Returns after fail() when chat client init fails.
src/commands/rooms/messages/history.ts Returns after fail() when chat client init fails.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/commands/rooms/messages/reactions/send.ts (1)

62-67: ⚠️ Potential issue | 🟠 Major

Return after invalid --count validation too.

Line 62 still calls this.fail(...) without exiting. That leaves --type multiple --count <= 0 able to continue into room attach and messages.reactions.send(...) after the command has already rejected the input.

Suggested fix
       if (
         flags.type === "multiple" &&
         flags.count !== undefined &&
         flags.count <= 0
       ) {
-        this.fail(
+        return this.fail(
           "Count must be a positive integer for Multiple type reactions",
           flags,
           "roomMessageReactionSend",
           { room, count: flags.count },
         );
       }

Also applies to: 74-79

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/rooms/messages/reactions/send.ts` around lines 62 - 67,
Validation branches call this.fail(...) when count is invalid but do not stop
execution, allowing the flow to continue into room attach and
messages.reactions.send(...); after each validation this.fail(...) (specifically
the Multiple-type count checks) add an immediate return to exit the handler
early so the method does not proceed after rejecting the input.
🧹 Nitpick comments (1)
test/unit/commands/rooms/messages/delete.test.ts (1)

12-14: Optional cleanup: local beforeEach seems redundant.

getMockAblyChat() here doesn’t add isolation beyond the global unit-test setup/reset and can likely be removed to reduce noise.

Based on learnings: In the ably/ably-cli repository, unit test mocks are centralized in test/unit/setup.ts with global initialization/reset before each test, and per-file lifecycle setup should avoid duplication.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/unit/commands/rooms/messages/delete.test.ts` around lines 12 - 14,
Remove the redundant per-file setup by deleting the local beforeEach that calls
getMockAblyChat() in this test file; rely on the global test setup/reset
(test/unit/setup.ts) instead, and if any test in this file actually depends on
per-file mock state, replace the beforeEach with only the minimal calls required
(referencing getMockAblyChat and any specific mocks) and run the unit tests to
confirm no regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@README.md`:
- Around line 2889-2914: Add the missing fenced-code language marker "text" to
the two usage/example blocks for the commands so markdownlint MD040 is
satisfied: update the opening triple-backtick fence for the "ably rooms messages
delete ROOM SERIAL ..." block and the "ably rooms messages update ROOM SERIAL
TEXT ..." block to use ```text (leave the closing ``` unchanged); search for
those exact command-usage lines to locate the blocks and change their opening
fences to include the language identifier.

In `@src/commands/rooms/messages/history.ts`:
- Around line 69-73: The time-range validation in
src/commands/rooms/messages/history.ts currently calls this.fail(...) without
returning, allowing execution to continue into room.messages.history(...) after
reporting invalid --start/--end; update the validation branch so it returns the
result of this.fail(...) (matching the early exit used when client creation
fails) to stop further execution—specifically change the bare this.fail(...)
used for start/end validation to return this.fail(..., flags,
"roomMessageHistory") so the command exits immediately on invalid time-range.

In `@src/commands/rooms/messages/update.ts`:
- Around line 56-133: Move the JSON parsing and validation of flags.metadata and
flags.headers to before calling createChatClient() and
setupConnectionStateLogging(); specifically, in the command handler parse the
flags when flags.metadata !== undefined and flags.headers !== undefined (so
empty string is treated as provided), JSON.parse them inside try/catch, validate
the result is a non-null object and not an array, call this.fail(...) on
parse/shape errors using errorMessage, and only call this.logCliEvent(...) after
the object validation succeeds; keep createChatClient() and
setupConnectionStateLogging(chatClient.realtime, flags) after successful flag
validation.

---

Outside diff comments:
In `@src/commands/rooms/messages/reactions/send.ts`:
- Around line 62-67: Validation branches call this.fail(...) when count is
invalid but do not stop execution, allowing the flow to continue into room
attach and messages.reactions.send(...); after each validation this.fail(...)
(specifically the Multiple-type count checks) add an immediate return to exit
the handler early so the method does not proceed after rejecting the input.

---

Nitpick comments:
In `@test/unit/commands/rooms/messages/delete.test.ts`:
- Around line 12-14: Remove the redundant per-file setup by deleting the local
beforeEach that calls getMockAblyChat() in this test file; rely on the global
test setup/reset (test/unit/setup.ts) instead, and if any test in this file
actually depends on per-file mock state, replace the beforeEach with only the
minimal calls required (referencing getMockAblyChat and any specific mocks) and
run the unit tests to confirm no regressions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 16a0e997-c1b6-4010-a65a-31160c04a097

📥 Commits

Reviewing files that changed from the base of the PR and between fc7c4c6 and 592961f.

📒 Files selected for processing (18)
  • README.md
  • src/commands/rooms/messages/delete.ts
  • src/commands/rooms/messages/history.ts
  • src/commands/rooms/messages/index.ts
  • src/commands/rooms/messages/reactions/remove.ts
  • src/commands/rooms/messages/reactions/send.ts
  • src/commands/rooms/messages/reactions/subscribe.ts
  • src/commands/rooms/messages/send.ts
  • src/commands/rooms/messages/update.ts
  • src/commands/rooms/occupancy/get.ts
  • src/commands/rooms/occupancy/subscribe.ts
  • src/commands/rooms/reactions/send.ts
  • src/commands/rooms/reactions/subscribe.ts
  • src/commands/rooms/typing/keystroke.ts
  • src/commands/rooms/typing/subscribe.ts
  • test/helpers/mock-ably-chat.ts
  • test/unit/commands/rooms/messages/delete.test.ts
  • test/unit/commands/rooms/messages/update.test.ts

@umair-ably umair-ably force-pushed the DX-790-chat-update-delete branch from 592961f to 2c735b9 Compare March 12, 2026 23:43
@umair-ably umair-ably marked this pull request as ready for review March 12, 2026 23:50
@umair-ably umair-ably requested a review from sacOO7 March 12, 2026 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants