Skip to content

Conversation

@ahmed-n-abdeltwab
Copy link
Contributor

@ahmed-n-abdeltwab ahmed-n-abdeltwab commented Jul 24, 2025

Description:
This PR integrates OpenAPI support into the Rocket.Chat API, migrate of Rocket.Chat API endpoints to the new OpenAPI pattern. The update includes improved API documentation, enhanced type safety, and response validation using AJV.

Key Changes:

  • Implemented the new pattern and added AJV-based JSON schema validation for API.
  • Uses the ExtractRoutesFromAPI utility from the TypeScript definitions to dynamically derive the routes from the endpoint specifications.
  • Enabled Swagger UI integration for this API.
  • This does not introduce any breaking changes to the endpoint logic.

Issue Reference:
Relates to #34983, part of the ongoing OpenAPI integration effort.

Testing:

  • Verified that the API response schemas are correctly documented in Swagger UI.
  • All tests passed without any breaking changes
$ yarn testapi -f '[EmojiCustom]'


  [EmojiCustom]
    [/emoji-custom.create]
(node:18800) [DEP0044] DeprecationWarning: The `util.isArray` API is deprecated. Please use `Array.isArray()` instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
      ✔ should create new custom emoji (91ms)
      ✔ should create new custom emoji without optional parameter "aliases" (97ms)
      ✔ should throw an error when the filename is wrong
    [/emoji-custom.update]
      successfully:
        ✔ should update the custom emoji without a file
        ✔ should update the custom emoji without optional parameter "aliases"
        ✔ should update the custom emoji with all parameters and with a file (93ms)
        ✔ should change the etag when the custom emoji image is updated (398ms)
      should throw error when:
        ✔ the fields does not include "_id"
        ✔ the custom emoji does not exists
        ✔ the emoji file field is wrong
    [/emoji-custom.list]
      ✔ should return emojis
      ✔ should return emojis when use "query" query parameter
      ✔ should return emojis when use "updateSince" query parameter
      ✔ should return emojis when use both, "updateSince" and "query" query parameter
      ✔ should return an error when the "updateSince" query parameter is a invalid date
    [/emoji-custom.all]
      ✔ should return emojis
      ✔ should return emojis even requested with count and offset params
    Accessing custom emojis
      ✔ should return forbidden if the there is no fileId on the url
      ✔ should return success if the file does not exists with some specific headers
      ✔ should return not modified if the file does not exists and if-modified-since is equal to the Thu, 01 Jan 2015 00:00:00 GMT
      ✔ should return success if the the requested exists
      ✔ should return not modified if the the requested file contains a valid-since equal to the upload date
      ✔ should return the emoji even when no etag is passed (for old emojis)
      ✔ should return success if the etag is invalid
    [/emoji-custom.delete]
      ✔ should throw an error when trying delete custom emoji without the required param "emojid"
      ✔ should throw an error when trying delete custom emoji that does not exists
      ✔ should delete the custom emoji created before successfully


  27 passing (1s)

Endpoints: (In progress)

Looking forward to your feedback! 🚀

Summary by CodeRabbit

  • New Features
    • Added OpenAPI-backed validation and structured responses for the emoji creation API, improving reliability and consistency.
  • Bug Fixes
    • Improved error handling for emoji creation, returning clearer, standardized error responses.
  • Documentation
    • Enhanced API documentation for emoji creation with explicit request/response schemas.
  • Chores
    • Aligned internal route definitions and shared schema usage to modern standards without impacting public endpoints.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Jul 24, 2025

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Jul 24, 2025

🦋 Changeset detected

Latest commit: 0492e84

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 42 packages
Name Type
@rocket.chat/meteor Patch
@rocket.chat/rest-typings Patch
@rocket.chat/api-client Patch
@rocket.chat/core-services Patch
@rocket.chat/ddp-client Patch
@rocket.chat/http-router Patch
@rocket.chat/models Patch
@rocket.chat/ui-contexts Patch
@rocket.chat/web-ui-registration Patch
@rocket.chat/account-service Patch
@rocket.chat/authorization-service Patch
@rocket.chat/ddp-streamer Patch
@rocket.chat/stream-hub-service Patch
@rocket.chat/federation-matrix Patch
@rocket.chat/omnichannel-services Patch
@rocket.chat/presence Patch
rocketchat-services Patch
@rocket.chat/federation-service Patch
@rocket.chat/omnichannel-transcript Patch
@rocket.chat/presence-service Patch
@rocket.chat/queue-worker Patch
@rocket.chat/network-broker Patch
@rocket.chat/omni-core-ee Patch
@rocket.chat/livechat Patch
@rocket.chat/mock-providers Patch
@rocket.chat/cron Patch
@rocket.chat/instance-status Patch
@rocket.chat/omni-core Patch
@rocket.chat/media-calls Patch
@rocket.chat/uikit-playground Patch
@rocket.chat/fuselage-ui-kit Patch
@rocket.chat/gazzodown Patch
@rocket.chat/ui-avatar Patch
@rocket.chat/ui-client Patch
@rocket.chat/ui-video-conf Patch
@rocket.chat/ui-voip Patch
@rocket.chat/core-typings Patch
@rocket.chat/apps Patch
@rocket.chat/freeswitch Patch
@rocket.chat/model-typings Patch
@rocket.chat/license Patch
@rocket.chat/pdf-worker Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ahmed-n-abdeltwab
Copy link
Contributor Author

hey @cardoso the POST method lacks support for handling multipart/form-data payloads

@codecov
Copy link

codecov bot commented Jul 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 65.61%. Comparing base (f00d157) to head (2775d8a).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #36523      +/-   ##
===========================================
- Coverage    66.40%   65.61%   -0.80%     
===========================================
  Files         3325     3222     -103     
  Lines       111301   110516     -785     
  Branches     21113    20723     -390     
===========================================
- Hits         73913    72517    -1396     
- Misses       34702    35389     +687     
+ Partials      2686     2610      -76     
Flag Coverage Δ
unit 71.63% <ø> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cardoso
Copy link
Member

cardoso commented Jul 24, 2025

@ahmed-n-abdeltwab can you fix that in this PR?

@ahmed-n-abdeltwab ahmed-n-abdeltwab force-pushed the feat/openapi-emoji-custom-create branch from 121790a to 9eb457f Compare July 25, 2025 14:47
@ahmed-n-abdeltwab ahmed-n-abdeltwab marked this pull request as ready for review July 28, 2025 15:46
@ahmed-n-abdeltwab ahmed-n-abdeltwab requested review from a team as code owners July 28, 2025 15:46
@ahmed-n-abdeltwab ahmed-n-abdeltwab marked this pull request as draft August 5, 2025 06:54
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 27, 2025

Walkthrough

Adds OpenAPI/AJV-backed route handling for emoji-custom.create, integrates explicit 200/400 response schemas and error handling, exposes request on handler this-context, and adjusts/restores public typings by relocating the create endpoint’s typings from rest-typings into server route definitions with module augmentation.

Changes

Cohort / File(s) Summary
Route context typing
apps/meteor/app/api/server/definition.ts
Adds request: Request to TypedThis<TOptions, TPath> so handlers receive the HTTP Request in their this context.
Emoji create route implementation + public typings exposure
apps/meteor/app/api/server/v1/emoji-custom.ts
Wraps emoji-custom.create in a POST handler with AJV schemas for 200/400, structured responses, and try/catch logging. Introduces ExtractRoutesFromAPI-based EmojiCustomCreateEndpoints, exports EmojiCustomEndpoints, and augments @rocket.chat/rest-typings Endpoints.
Public REST typings adjustment
packages/rest-typings/src/v1/emojiCustom.ts
Removes '/v1/emoji-custom.create' POST from EmojiCustomEndpoints, leaving delete/update; endpoint typing is now provided via server-side augmentation.
Changeset
.changeset/weak-terms-shave.md
Records migration to chained route syntax and shared AJV schemas for emoji-custom.create with OpenAPI support.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant API Router
  participant emoji-custom.create Handler
  participant Validator (AJV)
  participant Emoji Service
  participant Storage/DB

  Client->>API Router: POST /v1/emoji-custom.create (payload)
  API Router->>emoji-custom.create Handler: Invoke with this.request
  emoji-custom.create Handler->>Validator (AJV): Validate request + prepare response schemas
  alt Valid
    emoji-custom.create Handler->>Emoji Service: insertOrUpdateEmoji()
    Emoji Service->>Storage/DB: Upsert emoji metadata
    Storage/DB-->>Emoji Service: OK / Data
    emoji-custom.create Handler->>Emoji Service: uploadEmojiCustomWithBuffer()
    Emoji Service->>Storage/DB: Store asset
    Storage/DB-->>Emoji Service: OK
    Emoji Service-->>emoji-custom.create Handler: Result
    emoji-custom.create Handler-->>API Router: 200 { structured response }
    API Router-->>Client: 200
  else Invalid or Error
    note over emoji-custom.create Handler: try/catch logs error
    emoji-custom.create Handler-->>API Router: 400 { failure payload }
    API Router-->>Client: 400
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I twitched my whiskers at the new emoji gate,
Schemas in rows, responses validate.
A hop through routes with tidy prose,
AJV guards where data flows.
With types aligned, I thump in cheer—
New faces bloom, the path is clear! 🐇✨

Pre-merge checks and finishing touches

✅ 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 concisely summarizes the primary change by indicating the addition of OpenAPI support for the specific emoji-custom.create endpoint, matching the PR’s main objective and avoiding extraneous detail.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🧪 Early access (Sonnet 4.5): enabled

We are currently testing the Sonnet 4.5 model, which is expected to improve code review quality. However, this model may lead to increased noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • Public repositories are always opted into early access features.
  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

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

@ahmed-n-abdeltwab ahmed-n-abdeltwab marked this pull request as ready for review September 30, 2025 03:20
Copy link
Contributor

@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: 1

🧹 Nitpick comments (2)
apps/meteor/app/api/server/v1/emoji-custom.ts (2)

158-171: Consider including error details in the failure response.

The catch block logs the error but returns a generic API.v1.failure() without any error message. This makes debugging difficult for API consumers. Consider passing error details to the failure response.

Apply this diff to include error context:

 		} catch (e) {
 			SystemLogger.error(e);
-			return API.v1.failure();
+			return API.v1.failure(e instanceof Error ? e.message : 'Failed to create emoji');
 		}

252-254: Consider the purpose of the EmojiCustomEndpoints alias.

The EmojiCustomEndpoints type is an alias to EmojiCustomCreateEndpoints, which only includes the create endpoint. This naming might be misleading since it suggests it covers all emoji-custom endpoints when it only covers one.

If the intent is to eventually include all emoji-custom endpoints in this type, consider:

  • Using a more specific name like EmojiCustomCreateEndpoint (singular), or
  • Documenting the planned expansion, or
  • Directly exporting EmojiCustomCreateEndpoints if the alias doesn't add clarity.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between dca0b3a and 8e34d61.

📒 Files selected for processing (4)
  • .changeset/weak-terms-shave.md (1 hunks)
  • apps/meteor/app/api/server/definition.ts (1 hunks)
  • apps/meteor/app/api/server/v1/emoji-custom.ts (4 hunks)
  • packages/rest-typings/src/v1/emojiCustom.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • packages/rest-typings/src/v1/emojiCustom.ts
🧰 Additional context used
🧬 Code graph analysis (1)
apps/meteor/app/api/server/v1/emoji-custom.ts (5)
packages/rest-typings/src/v1/Ajv.ts (1)
  • ajv (23-23)
apps/meteor/app/api/server/lib/getUploadFormData.ts (1)
  • getUploadFormData (55-195)
apps/meteor/app/api/server/ApiClass.ts (1)
  • ExtractRoutesFromAPI (73-77)
packages/rest-typings/src/v1/emojiCustom.ts (1)
  • EmojiCustomEndpoints (53-73)
packages/rest-typings/src/index.ts (1)
  • Endpoints (51-98)
🔇 Additional comments (6)
.changeset/weak-terms-shave.md (1)

1-7: LGTM!

The changeset correctly documents the OpenAPI support addition as patch-level changes for both affected packages. The description accurately summarizes the enhancement.

apps/meteor/app/api/server/v1/emoji-custom.ts (4)

4-4: LGTM!

The import additions for ajv and isEmojiCustomList are appropriate for the OpenAPI schema validation implementation.


14-14: LGTM!

The ExtractRoutesFromAPI import is correctly used for deriving route types from the endpoint specification.


138-146: Verify multipart/form-data Content-Type handling.

Per the PR comments, there's a concern about POST method support for multipart/form-data payloads. While getUploadFormData handles multipart parsing, verify that the OpenAPI specification documents the expected Content-Type: multipart/form-data header and that no middleware blocks it.

Consider adding explicit Content-Type validation or documentation in the OpenAPI schema to address the maintainer's concern about multipart/form-data handling.


256-259: LGTM!

The module augmentation correctly extends the @rocket.chat/rest-typings Endpoints interface. The eslint-disable comments are appropriate for this declaration merging pattern.

apps/meteor/app/api/server/definition.ts (1)

304-304: LGTM!

Adding the request: Request field to TypedThis aligns it with the existing ActionThis interface and enables typed access to the HTTP request in OpenAPI-style handlers. This change directly supports the emoji-custom.create endpoint implementation.

Comment on lines +111 to +135
response: {
400: ajv.compile({
type: 'object',
properties: {
success: { type: 'boolean', enum: [false] },
stack: { type: 'string' },
error: { type: 'string' },
errorType: { type: 'string' },
details: { type: 'string' },
},
{ field: 'emoji', sizeLimit: settings.get('FileUpload_MaxFileSize') },
);
required: ['success'],
additionalProperties: false,
}),
200: ajv.compile<void>({
type: 'object',
properties: {
success: {
type: 'boolean',
enum: [true],
},
},
required: ['success'],
additionalProperties: false,
}),
},
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify 400 response schema matches API.v1.failure() output.

The 400 response schema defines optional fields (stack, error, errorType, details), but API.v1.failure() at line 170 is called without arguments. Ensure the schema accurately reflects all possible 400 responses from this endpoint.

Run this script to check the API.v1.failure() implementation:


🏁 Script executed:

#!/bin/bash
# Description: Check API.v1.failure() signature and return shape

# Search for the failure method definition
ast-grep --pattern $'failure($$$) {
  $$$
}'

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Locate API.v1.failure definition and its return shape

echo "Searching for .failure( occurrences across .ts files"
rg -nP '\.failure\(' -C3 -g '*.ts' || echo "No .failure calls found"

echo -e "\nSearching for class API definition"
rg -nP 'class\s+API\b' -C3 -g '*.ts' || echo "No class API found"

echo -e "\nSearching for exported failure helper"
rg -nP 'export\s+(const|function)\s+failure' -C3 -g '*.ts' || echo "No exported failure helper found"

Length of output: 201931


🏁 Script executed:

#!/bin/bash
# Locate ApiClass declaration and failure method definition

echo "ApiClass declaration:"
rg -nP 'class\s+ApiClass\b' -n apps/meteor/app/api/server/ApiClass.ts || echo "Class ApiClass not found"

echo -e "\nFailure method signature and context:"
rg -nP '^\s*(public|private|protected)\s+failure\s*\(' -n -C3 apps/meteor/app/api/server/ApiClass.ts || echo "failure method definition not found"

Length of output: 121


🏁 Script executed:

#!/bin/bash
# Locate the ApiClass.ts file
fd --extension ts ApiClass.ts

# Search for the ApiClass declaration
rg -nP 'class\s+ApiClass\b' -g 'apps/meteor/app/api/server/ApiClass.ts'

# Extract the failure method implementation from ApiClass.ts
sed -n '900,950p' apps/meteor/app/api/server/ApiClass.ts | rg -C3 'failure\('

Length of output: 472


🏁 Script executed:

# Print the first 200 lines of ApiClass.ts to locate the failure method definition
sed -n '1,200p' apps/meteor/app/api/server/ApiClass.ts

Length of output: 6409


🏁 Script executed:

#!/bin/bash
# Search for public success and failure method definitions
echo "-- public success occurrences --"
rg -nP 'public\s+success\(' -C3 apps/meteor/app/api/server/ApiClass.ts || echo "No public success found"

echo -e "\n-- public failure occurrences --"
rg -nP 'public\s+failure\(' -C3 apps/meteor/app/api/server/ApiClass.ts || echo "No public failure found"

echo -e "\n-- Context around where success and failure are called --"
sed -n '600,700p' apps/meteor/app/api/server/ApiClass.ts | rg -C3 '\.failure\(' || echo "No failure calls in this segment"
sed -n '600,700p' apps/meteor/app/api/server/ApiClass.ts | rg -C3 '\.success\(' || echo "No success calls in this segment"

Length of output: 343


🏁 Script executed:

#!/bin/bash
sed -n '1,200p' apps/meteor/app/api/server/definition.ts

Length of output: 6259


Add missing message field to 400 schema
The default FailureResult body may include an optional message?: string, but your AJV schema forbids any properties beyond success, stack, error, errorType, and details. In apps/meteor/app/api/server/v1/emoji-custom.ts (lines 111–135), under the 400 schema’s properties, add

message: { type: 'string' },

so the schema aligns with API.v1.failure()’s possible output.

🤖 Prompt for AI Agents
In apps/meteor/app/api/server/v1/emoji-custom.ts around lines 111 to 135 the 400
AJV response schema omits the optional message field present in the default
FailureResult, causing valid error responses to be rejected; add a message
property with type 'string' to the 400 schema's properties so the schema allows
the optional message (i.e., include message: { type: 'string' } alongside stack,
error, errorType, details) while keeping required/additionalProperties as-is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants