Skip to content

chore: refactor apps converters to TypeScript with Zod codecs (1/2)#41400

Merged
ggazzo merged 5 commits into
developfrom
chore/apps-converters-zod-1
Jul 17, 2026
Merged

chore: refactor apps converters to TypeScript with Zod codecs (1/2)#41400
ggazzo merged 5 commits into
developfrom
chore/apps-converters-zod-1

Conversation

@d-gubert

@d-gubert d-gubert commented Jul 15, 2026

Copy link
Copy Markdown
Member

Proposed changes (including videos or screenshots)

Proposed changes

This PR adds the proposal document and the foundation to support migration of the apps converters from JavaScript to TypeScript and introduces Zod-based codec infrastructure for enum mappings. The changes are behavior-preserving, with the exception of a small set of latent bugs that typing the converters made visible — those are fixed deliberately and each is pinned by a test (see Incidental bug fixes).

Key changes:

  1. TypeScript migration: Converted the following converters from .js to .ts:

    • AppUsersConverter
    • AppMessagesConverter
    • AppRoomsConverter
    • AppSettingsConverter
    • AppDepartmentsConverter
    • AppVisitorsConverter
    • AppUploadsConverter
  2. New Zod codec infrastructure (app/apps/server/converters/codecs/enums.ts):

    • UserTypeCodec: Maps Rocket.Chat user type strings to Apps-Engine UserType enum
    • UserStatusConnectionCodec: Maps status connection strings to UserStatusConnection enum
    • RoomTypeCodec: Maps room type characters to RoomType enum
    • SettingTypeCodec: Maps setting type strings to SettingType enum
    • All codecs preserve legacy fallback semantics exactly (including pass-through behavior for unknown values)
  3. Comprehensive golden snapshot tests (tests/unit/app/apps/server/converters.golden.spec.ts):

    • Tests for all converters capturing pre-codec behavior
    • Validates field mapping, date normalization, and _unmappedProperties_ bucketing
    • Tests bidirectional conversion (RC ↔ Apps-Engine)
    • Covers edge cases like cross-converter lookups and nested field mapping
  4. Enum codec tests (tests/unit/app/apps/server/codecs/enums.spec.ts):

    • Validates each codec's decode and encode operations
    • Compares against legacy helper implementations to ensure behavior preservation
    • Tests all known enum values and edge cases

Incidental bug fixes

Typing the converters surfaced three pre-existing latent bugs. Rather than carry them forward as "behavior to preserve", they are fixed here — these are the only intentional behavior changes in the PR, and each is covered by a golden or focused test:

  1. usersutfOffset typo (from-app). convertToRocketChat read the misspelled appUser.utfOffset, so a round-tripped user always dropped its utcOffset. It now reads utcOffset first and keeps utfOffset only as a compatibility fallback for any app still emitting the old key. The golden round-trip fixture now uses utcOffset; a focused test pins the legacy fallback.
  2. messages — dead visitor-sender fallback (to-app). The sender resolver deleted message.u before the "old system message without token" fallback re-read it, so the fallback always received undefined. It now captures the sender before deletion; a focused test drives a missing primary lookup and asserts the fallback resolves the original sender.
  3. messages — null editor deref (from-app). convertAppMessage dereferenced Users.findOneById(editor.id) through a non-null assertion, throwing when the editor no longer exists. It now falls back to the editor data carried on the app payload, mirroring the adjacent sender handling.

Alongside these, a few defensive guards were added where a destructuring or lookup could hit an optional value the types claimed was always present (uploads rid/room, users convertByUsername, rooms visitorChannelInfo). These only turn a latent TypeError into the already-intended empty result and match the guards their sibling fields already had, so they change no covered output.

Migration approach:

  • Added proper TypeScript types and interface implementations
  • Preserved all existing transformation logic and field mappings
  • Maintained _unmappedProperties_ bucketing for forward compatibility
  • Codecs are behavior-preserving replacements for private _convert*ToApp/_convert*ToEnum helpers
  • Golden snapshots lock the RC ↔ Apps-Engine field mapping to enable safe incremental codec migration

Issue(s)

https://rocketchat.atlassian.net/browse/ARCH-2265

#41205

Steps to test or reproduce

Further comments

<img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg">

Summary by CodeRabbit

  • New Features

    • Improved Apps integration support for users, rooms, messages, departments, settings, uploads, and livechat visitors.
    • Added more consistent handling of enum values and legacy data formats.
    • Preserved unmapped fields and partial records during data conversion.
  • Bug Fixes

    • Improved handling of missing or optional data during synchronization.
    • Corrected a utcOffset round-trip typo, a dead visitor-sender fallback, and a null-editor dereference in the message/user converters.
    • Added support for upload and visitor lookups by their respective identifiers.
  • Tests

    • Added comprehensive compatibility and conversion coverage, including enum behavior and data snapshots.
  • Documentation

    • Added a proposal outlining the future data-conversion approach.

Summary by CodeRabbit

  • New Features
    • Added codec-based enum conversions with legacy-compatible behavior.
    • Reintroduced/implemented uploads and visitors server-side converters.
  • Bug Fixes
    • Improved handling of missing/empty/unknown enum inputs and legacy fallbacks (including status, user type, utcOffset/utfOffset, and message sender/editor edge cases).
  • Tests
    • Added unit tests for enum codecs.
    • Added golden snapshot tests to lock deterministic converter output.
  • Documentation
    • Added a proposal for migrating converters to a unified codec-based approach.

@changeset-bot

changeset-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 407662b

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@CLAassistant

CLAassistant commented Jul 15, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds bidirectional enum codecs, strengthens TypeScript typing across Apps converters, replaces upload and visitor implementations with TypeScript versions, and adds enum parity tests, converter golden snapshots, and a Zod migration proposal.

Changes

Apps converter migration

Layer / File(s) Summary
Enum codec contracts and parity tests
apps/meteor/app/apps/server/converters/codecs/enums.ts, apps/meteor/app/apps/server/converters/codecs/index.ts, apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts
Adds four exported Zod codecs with legacy-compatible decoding, identity encoding, barrel exports, and unit tests against legacy conversion oracles.
Typed synchronous converter boundaries
apps/meteor/app/apps/server/converters/departments.ts, apps/meteor/app/apps/server/converters/settings.ts, apps/meteor/app/apps/server/converters/users.ts
Adds explicit interfaces, constructors, overloads, return types, enum signatures, and typed handling of optional and unmapped fields.
Upload and visitor converter implementations
apps/meteor/app/apps/server/converters/uploads.ts, apps/meteor/app/apps/server/converters/visitors.ts
Adds TypeScript converters for upload and livechat visitor records, including orchestrator lookups and reverse mappings.
Typed room and message conversion paths
apps/meteor/app/apps/server/converters/rooms.ts, apps/meteor/app/apps/server/converters/messages.ts
Adds typed overloads and dynamic-data aliases for room and message conversion, preserving cross-converter lookups, memoization, attachment handling, and unmapped fields.
Converter golden coverage and migration proposal
apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts, docs/proposals/apps-converters-zod/README.md
Adds golden coverage for converter mappings and documents the phased Zod codec migration, compatibility rules, and testing strategy.

Estimated code review effort: 4 (Complex) | ~60 minutes

Suggested labels: type: chore

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: migrating apps converters to TypeScript with Zod codecs, and the 1/2 suffix matches the staged rollout.

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • ZOD-1: Request failed with status code 401

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.

@dionisio-bot

dionisio-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 74.17219% with 39 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.44%. Comparing base (abab8a0) to head (407662b).
⚠️ Report is 4 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #41400      +/-   ##
===========================================
- Coverage    68.47%   68.44%   -0.03%     
===========================================
  Files         4092     4102      +10     
  Lines       158285   158627     +342     
  Branches     28622    28829     +207     
===========================================
+ Hits        108379   108566     +187     
- Misses       44874    44969      +95     
- Partials      5032     5092      +60     
Flag Coverage Δ
e2e 59.19% <ø> (-0.14%) ⬇️
e2e-api 45.51% <ø> (+0.01%) ⬆️
unit 70.31% <74.17%> (-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.

@d-gubert d-gubert changed the title chore: refactor apps converters to TypeScript with Zod codecs chore: refactor apps converters to TypeScript with Zod codecs (1/2) Jul 15, 2026
@d-gubert
d-gubert marked this pull request as ready for review July 15, 2026 19:14
@d-gubert
d-gubert requested review from a team as code owners July 15, 2026 19:14

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (3)
apps/meteor/app/apps/server/converters/messages.ts (2)

207-213: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Handle a missing editor instead of asserting it exists.

Users.findOneById may return undefined; the non-null assertions then crash message conversion. Fall back to message.editor, or reject with a deliberate validation error.

Possible fix
 			const editor = await Users.findOneById(message.editor.id);
+			const editorId = editor?._id ?? message.editor.id;
+			const editorUsername = editor?.username ?? message.editor.username;
+
+			if (!editorUsername) {
+				throw new Error('Invalid editor provided on the message.');
+			}
+
 			editedBy = {
-				_id: editor!._id,
-				username: editor!.username,
+				_id: editorId,
+				username: editorUsername,
 			};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/app/apps/server/converters/messages.ts` around lines 207 - 213,
Update the editor lookup in the message conversion flow to handle
Users.findOneById returning undefined instead of relying on non-null assertions.
In the message.editor branch, use the found user when present and fall back to
message.editor, or explicitly reject with a deliberate validation error;
preserve the existing editedBy shape.

143-160: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve message.u for the legacy sender fallback.

Line 153 deletes message.u, so Line 160 always calls convertToApp(undefined) when the primary lookup fails.

Proposed fix
 			sender: async (message: MessageData) => {
-				if (!message.u?._id) {
+				const sender = message.u;
+				if (!sender?._id) {
 					return undefined;
 				}

 				const user = await (isMessageFromVisitor(msgObj)
-					? cache.get('user.convertToApp')(message.u)
-					: cache.get('user.convertById')(message.u._id));
+					? cache.get('user.convertToApp')(sender)
+					: cache.get('user.convertById')(sender._id));

 				delete message.u;

-				return user || cache.get('user.convertToApp')(message.u);
+				return user || cache.get('user.convertToApp')(sender);
 			},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/app/apps/server/converters/messages.ts` around lines 143 - 160,
Update the sender resolver in the async sender function to preserve the original
message.u value before deleting it, then use that saved value for the legacy
fallback when the primary user lookup returns no user. Keep the existing primary
lookup and cleanup behavior unchanged, but ensure convertToApp receives the
original sender data rather than undefined.
apps/meteor/app/apps/server/converters/rooms.ts (1)

154-164: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Default visitorChannelInfo before destructuring visitorChannelInfo is optional and can be undefined here, so destructuring it directly can throw. Default it to {} or guard before reading lastMessageTs and phone.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/app/apps/server/converters/rooms.ts` around lines 154 - 164,
Update __getVisitor to safely handle an undefined visitorChannelInfo before
destructuring lastMessageTs and phone, using an empty-object default or an
equivalent guard while preserving the existing visitor validation flow.
🧹 Nitpick comments (1)
apps/meteor/app/apps/server/converters/visitors.ts (1)

7-7: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove resolved TODO comment.

The convertVisitor function is already correctly handling async behavior by returning the Promise from transformMappedData, while convertAppVisitor operates synchronously. Additionally, as per coding guidelines, avoid code comments in the implementation.

♻️ Proposed fix
-// TODO: check if functions from this converter can be async
 export class AppVisitorsConverter implements IAppVisitorsConverter {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/meteor/app/apps/server/converters/visitors.ts` at line 7, Remove the
resolved TODO comment above convertVisitor; retain the existing async behavior
through transformMappedData and the synchronous convertAppVisitor implementation
unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/meteor/app/apps/server/converters/messages.ts`:
- Around line 12-15: Remove the explanatory migration-rationale comment above
MessageData in apps/meteor/app/apps/server/converters/messages.ts (lines 12-15)
and the corresponding comment above RoomData in
apps/meteor/app/apps/server/converters/rooms.ts (lines 9-11); leave the
converter implementations unchanged.

In `@apps/meteor/app/apps/server/converters/uploads.ts`:
- Around line 89-91: Update the destructuring in the upload conversion flow to
safely handle missing optional references: use optional chaining when extracting
rid from upload.room, consistent with the existing userId and visitorToken
extraction, while preserving the resulting undefined value when the room is
absent.
- Around line 46-53: Update the room converter callback around the room
conversion logic to check whether upload.rid exists before calling convertById.
Return the appropriate empty result when rid is absent, while preserving the
current conversion and rid cleanup behavior when it is present; follow the
existing userId and visitorToken guards as the pattern.

In `@apps/meteor/app/apps/server/converters/users.ts`:
- Line 89: Update the user converter’s utcOffset mapping in
apps/meteor/app/apps/server/converters/users.ts:89 to read user.utcOffset first
and retain user.utfOffset only as a compatibility fallback. Update the primary
round-trip fixture in
apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts:133-166 to use
utcOffset, and add a focused fallback test if needed to preserve legacy
utfOffset behavior.

---

Outside diff comments:
In `@apps/meteor/app/apps/server/converters/messages.ts`:
- Around line 207-213: Update the editor lookup in the message conversion flow
to handle Users.findOneById returning undefined instead of relying on non-null
assertions. In the message.editor branch, use the found user when present and
fall back to message.editor, or explicitly reject with a deliberate validation
error; preserve the existing editedBy shape.
- Around line 143-160: Update the sender resolver in the async sender function
to preserve the original message.u value before deleting it, then use that saved
value for the legacy fallback when the primary user lookup returns no user. Keep
the existing primary lookup and cleanup behavior unchanged, but ensure
convertToApp receives the original sender data rather than undefined.

In `@apps/meteor/app/apps/server/converters/rooms.ts`:
- Around line 154-164: Update __getVisitor to safely handle an undefined
visitorChannelInfo before destructuring lastMessageTs and phone, using an
empty-object default or an equivalent guard while preserving the existing
visitor validation flow.

---

Nitpick comments:
In `@apps/meteor/app/apps/server/converters/visitors.ts`:
- Line 7: Remove the resolved TODO comment above convertVisitor; retain the
existing async behavior through transformMappedData and the synchronous
convertAppVisitor implementation unchanged.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a4ebe66e-2f67-45c9-a422-484f03b0b8fd

📥 Commits

Reviewing files that changed from the base of the PR and between 012dd32 and 2093b92.

📒 Files selected for processing (14)
  • apps/meteor/app/apps/server/converters/codecs/enums.ts
  • apps/meteor/app/apps/server/converters/codecs/index.ts
  • apps/meteor/app/apps/server/converters/departments.ts
  • apps/meteor/app/apps/server/converters/messages.ts
  • apps/meteor/app/apps/server/converters/rooms.ts
  • apps/meteor/app/apps/server/converters/settings.ts
  • apps/meteor/app/apps/server/converters/uploads.js
  • apps/meteor/app/apps/server/converters/uploads.ts
  • apps/meteor/app/apps/server/converters/users.ts
  • apps/meteor/app/apps/server/converters/visitors.js
  • apps/meteor/app/apps/server/converters/visitors.ts
  • apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts
  • apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts
  • docs/proposals/apps-converters-zod/README.md
💤 Files with no reviewable changes (2)
  • apps/meteor/app/apps/server/converters/uploads.js
  • apps/meteor/app/apps/server/converters/visitors.js
📜 Review details
⏰ Context from checks skipped due to timeout. (10)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Hacktron Security Check
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 8.0 coverage (1/5)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 8.0 coverage (4/5)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 8.0 coverage (2/5)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 8.0 coverage (5/5)
  • GitHub Check: 🔨 Test UI (EE) / MongoDB 8.0 coverage (3/5)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 8.0 (2/4)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 8.0 (1/4)
  • GitHub Check: 🔨 Test UI (CE) / MongoDB 8.0 (4/4)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts
  • apps/meteor/app/apps/server/converters/codecs/index.ts
  • apps/meteor/app/apps/server/converters/codecs/enums.ts
  • apps/meteor/app/apps/server/converters/uploads.ts
  • apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts
  • apps/meteor/app/apps/server/converters/visitors.ts
  • apps/meteor/app/apps/server/converters/users.ts
  • apps/meteor/app/apps/server/converters/settings.ts
  • apps/meteor/app/apps/server/converters/rooms.ts
  • apps/meteor/app/apps/server/converters/messages.ts
  • apps/meteor/app/apps/server/converters/departments.ts
**/*.spec.ts

📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)

**/*.spec.ts: Use descriptive test names that clearly communicate expected behavior in Playwright tests
Use .spec.ts extension for test files (e.g., login.spec.ts)

Files:

  • apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts
  • apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts
🧠 Learnings (5)
📚 Learning: 2026-02-24T19:22:48.358Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/omnichannel/omnichannel-send-pdf-transcript.spec.ts:66-67
Timestamp: 2026-02-24T19:22:48.358Z
Learning: In Playwright end-to-end tests (e.g., under apps/meteor/tests/e2e/...), prefer locating elements by translated text (getByText) and ARIA roles (getByRole) over data-qa attributes. If translation values change, update the corresponding test locators accordingly. Never use data-qa locators. This guideline applies to all Playwright e2e test specs in the repository and helps keep tests robust to UI text changes and accessible semantics.

Applied to files:

  • apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts
  • apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts
  • apps/meteor/app/apps/server/converters/codecs/index.ts
  • apps/meteor/app/apps/server/converters/codecs/enums.ts
  • apps/meteor/app/apps/server/converters/uploads.ts
  • apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts
  • apps/meteor/app/apps/server/converters/visitors.ts
  • apps/meteor/app/apps/server/converters/users.ts
  • apps/meteor/app/apps/server/converters/settings.ts
  • apps/meteor/app/apps/server/converters/rooms.ts
  • apps/meteor/app/apps/server/converters/messages.ts
  • apps/meteor/app/apps/server/converters/departments.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts
  • apps/meteor/app/apps/server/converters/codecs/index.ts
  • apps/meteor/app/apps/server/converters/codecs/enums.ts
  • apps/meteor/app/apps/server/converters/uploads.ts
  • apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts
  • apps/meteor/app/apps/server/converters/visitors.ts
  • apps/meteor/app/apps/server/converters/users.ts
  • apps/meteor/app/apps/server/converters/settings.ts
  • apps/meteor/app/apps/server/converters/rooms.ts
  • apps/meteor/app/apps/server/converters/messages.ts
  • apps/meteor/app/apps/server/converters/departments.ts
📚 Learning: 2026-03-06T18:10:15.268Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 39397
File: packages/gazzodown/src/code/CodeBlock.spec.tsx:47-68
Timestamp: 2026-03-06T18:10:15.268Z
Learning: In tests (especially those using testing-library/dom/jsdom) for Rocket.Chat components, the HTML <code> element has an implicit ARIA role of 'code'. Therefore, screen.getByRole('code') or screen.findByRole('code') will locate <code> elements even without a role attribute. Do not flag findByRole('code') as invalid in reviews; prefer using the implicit role instead of adding role="code" unless necessary for accessibility.

Applied to files:

  • apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts
  • apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.

Applied to files:

  • apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts
  • apps/meteor/app/apps/server/converters/codecs/index.ts
  • apps/meteor/app/apps/server/converters/codecs/enums.ts
  • apps/meteor/app/apps/server/converters/uploads.ts
  • apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts
  • apps/meteor/app/apps/server/converters/visitors.ts
  • apps/meteor/app/apps/server/converters/users.ts
  • apps/meteor/app/apps/server/converters/settings.ts
  • apps/meteor/app/apps/server/converters/rooms.ts
  • apps/meteor/app/apps/server/converters/messages.ts
  • apps/meteor/app/apps/server/converters/departments.ts
🔇 Additional comments (10)
apps/meteor/app/apps/server/converters/codecs/index.ts (1)

1-2: LGTM!

apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts (1)

93-103: LGTM!

apps/meteor/app/apps/server/converters/departments.ts (1)

1-27: LGTM!

docs/proposals/apps-converters-zod/README.md (1)

1-5: LGTM!

apps/meteor/app/apps/server/converters/codecs/enums.ts (1)

26-26: 📐 Maintainability & Code Quality

Check the Zod module augmentation for z.codec. z.codec, z.decode, and z.encode are not standard Zod APIs, so this file should only rely on them if the project adds the corresponding zod module augmentation.

apps/meteor/app/apps/server/converters/settings.ts (1)

1-17: LGTM!

Also applies to: 31-34, 51-51

apps/meteor/app/apps/server/converters/users.ts (1)

1-73: LGTM!

Also applies to: 90-121, 138-138

apps/meteor/app/apps/server/converters/messages.ts (1)

1-3: LGTM!

Also applies to: 16-41, 67-128, 162-173, 231-231, 263-266, 306-306, 333-333, 342-342, 351-364

apps/meteor/app/apps/server/converters/rooms.ts (1)

1-8: LGTM!

Also applies to: 12-40, 75-75, 90-137, 177-177, 193-193, 219-219, 228-244, 301-312, 338-348, 358-363, 374-382, 383-391, 398-398, 412-412, 423-437, 448-458, 459-459, 470-470, 486-491

apps/meteor/tests/unit/app/apps/server/converters.golden.spec.ts (1)

1-132: LGTM!

Also applies to: 167-867

Comment thread apps/meteor/app/apps/server/converters/messages.ts
Comment thread apps/meteor/app/apps/server/converters/uploads.ts
Comment thread apps/meteor/app/apps/server/converters/uploads.ts Outdated
Comment thread apps/meteor/app/apps/server/converters/users.ts Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 14 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread apps/meteor/app/apps/server/converters/uploads.ts Outdated
Comment thread apps/meteor/tests/unit/app/apps/server/codecs/enums.spec.ts Outdated
Comment thread apps/meteor/app/apps/server/converters/users.ts Outdated

@hacktron-app hacktron-app Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 1 file

Severity Count
HIGH 1

View full scan results

Comment thread apps/meteor/app/apps/server/converters/uploads.ts
claude added 5 commits July 16, 2026 12:53
Detailed plan behind PR #41205: problem, codec design decisions, the
phased rollout (Phase 0 done), testing strategy via golden snapshots,
and risks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185hwJYnx3nzP4pcrYM2XXj

move document
Groundwork for migrating the apps-engine converters to Zod codecs. No
runtime behaviour changes — this only converts files to TypeScript and
adds scaffolding + a behavioural safety net for the later phases.

- Convert the 7 remaining .js converters (settings, users, visitors,
  departments, uploads, rooms, messages) to .ts, preserving behaviour
  verbatim (including the legacy `utfOffset` read and throw-on-null
  paths). Transform maps in rooms/messages keep loose typing for now;
  they are tightened when each is codec-ified.
- Add converters/codecs/ with the first shared primitives: bidirectional
  enum codecs (UserType, UserStatusConnection, RoomType, SettingType)
  that reproduce the current _convert* switch logic exactly.
- Add unit tests asserting the enum codecs match the legacy helpers, and
  golden-snapshot tests locking the current RC <-> Apps-Engine field
  mapping (incl. the _unmappedProperties_ bucket) for settings, users,
  visitors, departments, roles, videoConferences, contacts and uploads.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185hwJYnx3nzP4pcrYM2XXj

test(apps): add decode golden snapshots for rooms, messages and threads

The golden equivalence oracle previously covered only the simpler
converters; the async, cross-converter, memoized ones (rooms, messages,
threads) — where mapping drift is hardest to reason about — had no golden
coverage, and threads had no test at all.

Add decode-direction golden snapshots (via the stub orchestrator, so they
run without a database) locking the RC -> Apps-Engine mapping for:
- AppRoomsConverter.convertRoom (channel + livechat: renames, boolean/type
  function fields, cross-converter lookups, secure fields, bucket) and
  convertRoomRaw;
- AppMessagesConverter.convertMessage (room/editor/sender lookups,
  attachment sub-map, bucket) and convertMessageRaw;
- AppThreadsConverter.convertMessage (injected room, passed-in user lookups,
  attachment sub-map, bucket) — previously untested.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0185hwJYnx3nzP4pcrYM2XXj
…tatus case

Address PR 41400 review feedback:

- uploads: guard `upload.rid` in the `room` mapper before calling
  `convertById`, matching the `user`/`visitor` handlers. `IUpload['rid']`
  is optional, so the previous `as string` cast masked a possible
  `undefined` reaching the rooms lookup.
- users: guard `convertByUsername` against an empty/undefined username
  instead of casting with `as string`, making the contract explicit and
  avoiding a `{ username: undefined }` query.
- tests: add the empty-string input to the UserStatusConnectionCodec
  decode test so the falsy `!status -> OFFLINE` branch is covered.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158L8oVaauRgodsw6bVvZii
Address additional PR 41400 review feedback (crash-prevention only):

- uploads: default `upload.room` to `{}` when destructuring `rid` in
  convertToRocketChat, matching the sibling `upload.user`/`upload.visitor`
  guards. `IUpload['room']` can be absent at runtime (uploads without a
  room), which previously threw a TypeError.
- rooms: default `visitorChannelInfo` to `{}` in `__getVisitor` before
  destructuring `lastMessageTs`/`phone`, consistent with the method's
  existing `roomVisitor`/`visitor` guards.

These preserve the intended result on all non-crashing paths (verified by
the golden snapshot tests) and only turn a latent TypeError into the
already-intended empty result.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158L8oVaauRgodsw6bVvZii
These were previously carried forward as "behaviour to preserve"; typing
the converters made them visible, so fix them with focused coverage:

- users: convertToRocketChat read the misspelled `utfOffset`, so a
  round-tripped user always lost `utcOffset`. Read `utcOffset` first and
  keep `utfOffset` only as a compatibility fallback.
- messages: the visitor-sender fallback re-read `message.u` after it had
  been deleted, so it always received `undefined`. Capture the sender
  before deletion.
- messages: convertAppMessage dereferenced Users.findOneById through a
  non-null assertion, throwing when the editor no longer exists. Fall back
  to the editor data on the app payload, mirroring the sender handling.

Update the golden user round-trip fixture to `utcOffset`, add focused
tests for the `utfOffset` fallback and the sender fallback, and document
the fixes in the migration proposal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0158L8oVaauRgodsw6bVvZii
@d-gubert
d-gubert force-pushed the chore/apps-converters-zod-1 branch from 64fd256 to 407662b Compare July 16, 2026 15:54
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
putComment timed out

@ggazzo ggazzo added this to the 8.7.0 milestone Jul 16, 2026
@d-gubert d-gubert added the stat: QA assured Means it has been tested and approved by a company insider label Jul 16, 2026
@dionisio-bot dionisio-bot Bot added the stat: ready to merge PR tested and approved waiting for merge label Jul 16, 2026
@dionisio-bot
dionisio-bot Bot added this pull request to the merge queue Jul 16, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 16, 2026
@ggazzo
ggazzo merged commit 14d0718 into develop Jul 17, 2026
83 of 85 checks passed
@ggazzo
ggazzo deleted the chore/apps-converters-zod-1 branch July 17, 2026 02:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider stat: ready to merge PR tested and approved waiting for merge type: chore

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants