Skip to content

Conversation

@d-gubert
Copy link
Member

@d-gubert d-gubert commented Jan 5, 2026

Proposed changes (including videos or screenshots)

To transfer the file contents from the server to the runtime subprocess, the engine needs to package the buffer in a JSON RPC message, serialize it using msgpack and deno then unserializes the contents on its side.

This means the whole file buffer is duplicated THRICE in the host's memory: 1) jsonrpc-lite runs the Buffer through JSON.stringify to validate they can be serialized (a problem for the future), which creates a string on the Node process with the Buffer's contents encoded as base64 (larger than the original), and then immediately discards it; 2) msgpack copies the Buffer's contents to the encoder's own internal buffer while serializing the message; 3) msgpack decodes the message as an object as it arrives on the Deno process, allocating it all into memory.

So essentially, for each app that is subscribed to the IPreFileUpload event, the uploaded file's full contents are loaded into memory ~3.3 additional times (base64 encoding is estimated to take ~30% more bytes to represent the original binary content)

In this PR, we completely switch up the strategy. When Rocket.Chat triggers the upload event on the Apps-Engine, we stream the file's contents to a temporary file in the file system, and send over to Deno just the file path. Deno is then responsible for reading the file when needed. For the IPreFileUpload event, this means we stop base64 encoding the contents, and stop transfering large contents over stdio, reducing pressure on that stream.

Issue(s)

SUP-963

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • Bug Fixes

    • Fixed a memory-usage spike when apps process file upload events.
  • New Features

    • Improved file-upload handling so apps can properly intercept and block uploads when configured.
  • Tests

    • Added end-to-end and local test packages to validate file-upload behavior.
  • Documentation

    • Added guidance for using pre-built test app packages for upload scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Jan 5, 2026

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

@changeset-bot
Copy link

changeset-bot bot commented Jan 5, 2026

🦋 Changeset detected

Latest commit: 0f7416c

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

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Implements temporary file storage for Apps Engine upload handling: writes uploaded file contents to a temp directory at upload time, passes the temp path into app subprocesses (via AppManager/getTempFilePath and Deno runtime permissions), and routes executePreFileUpload through new upload handlers and assertions.

Changes

Cohort / File(s) Summary
Changeset & Docs
\.changeset/spotty-steaks-notice.md, apps/meteor/tests/data/apps/app-packages/README.md
Adds changeset entry and README describing pre-built test app packages and IPreFileUpload test app.
Startup temp dir
apps/meteor/ee/server/apps/orchestrator.js
Creates apps-engine-temp in system temp dir at startup and passes path into AppManager deps.
AppManager
packages/apps-engine/src/server/AppManager.ts
Adds tempFilePath to IAppManagerDeps, stores it, and exposes getTempFilePath(): string.
Type defs (uploads)
packages/apps-engine/src/definition/uploads/IFileUploadContext.ts
Adds IFileUploadInternalContext { file: IUploadDetails; path: string }.
Deno runtime — handlers & assertions
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts, packages/apps-engine/deno-runtime/handlers/lib/assertions.ts, packages/apps-engine/deno-runtime/deno.jsonc, packages/apps-engine/deno-runtime/handlers/app/handler.ts
New upload event handler reading temp files into buffer, assertion helpers, import mapping, and routing of upload events with centralized result formatting.
Deno runtime — permissions
packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts
Adds tempFilePath field and conditionally includes it in --allow-read when app implements IPreFileUpload.
Bridge — Meteor listener
apps/meteor/app/apps/server/bridges/listeners.ts
Adds uploadEvent path: writes content to temp file, builds upload details, invokes PreFileUpload with { file, path }, and ensures cleanup; changes payload typing.
App package/compiler typings
packages/apps-engine/src/server/compiler/AppImplements.ts, packages/apps-engine/src/server/compiler/AppPackageParser.ts
Stronger typing: implemented as Record<AppInterface, boolean>, rename/setters setImplements and doesImplement accessor, updated usage.
ProxiedApp logging
packages/apps-engine/src/server/ProxiedApp.ts
Improves error logging using inspect() for deeper inspection.
Tests & test helpers
apps/meteor/tests/data/apps/app-packages/index.ts, apps/meteor/tests/data/apps/helper.ts, packages/apps-engine/tests/test-data/utilities.ts, apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts, packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
Adds test package export, installLocalTestPackage() helper, mock getTempFilePath() in test infra, new EE E2E tests for IPreFileUpload, and updates to AppImplements tests.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Bridge as App Listener Bridge
    participant TempFS as Temp File System
    participant DenoRT as Deno Runtime
    participant App as App Subprocess

    Client->>Bridge: POST rooms.media/{roomId} (file)
    Bridge->>TempFS: Write file to temp dir (uuid)
    TempFS-->>Bridge: temp path
    Bridge->>DenoRT: Invoke executePreFileUpload with {file, content} / temp path
    DenoRT->>DenoRT: Check App implements IPreFileUpload
    DenoRT->>DenoRT: Grant read to temp dir for subprocess
    DenoRT->>App: Execute handler with context { file, content }
    App-->>DenoRT: Result (allow/reject)
    DenoRT-->>Bridge: Handler result
    Bridge->>TempFS: Delete temp file
    TempFS-->>Bridge: deleted
    Bridge-->>Client: 200 or 400 response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • ggazzo
  • sampaiodiego

Poem

🐰 A rabbit hops with glee so bright,
Files find a temp bed out of sight,
No pipes of bytes to make a fuss,
Apps read paths and memory breathes thus—
Hooray for tidy uploads tonight! ✨

🚥 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: reducing memory usage in the IPreFileUpload event handling by streaming files to temporary storage instead of transferring buffers over stdio.
Linked Issues check ✅ Passed All coding requirements from SUP-963 are met: the PR implements file streaming to temporary storage (reducing memory duplication), avoids base64 encoding and stdio transfer of large buffers, and preserves IPreFileUpload functional behavior while improving resource usage.
Out of Scope Changes check ✅ Passed All changes are directly related to SUP-963 objectives. The PR consistently refactors IPreFileUpload event handling to use temporary files, updates type definitions, adds test infrastructure, and creates end-to-end tests for the new implementation.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/apps-file-stream

🧹 Recent nitpick comments
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (1)

29-29: Type mismatch between params destructuring and assertion.

Line 29 types the destructured file as IUpload, but line 37 validates it against IUploadDetails via assertIsUpload. The assertion function checks for IUploadDetails properties (rid, userId/visitorToken), which is the correct runtime shape being passed. Consider aligning the type annotation on line 29 with the actual expected type.

♻️ Proposed fix
-	const [{ file, path }] = params as [{ file?: IUpload, path?: string }];
+	const [{ file, path }] = params as [{ file?: IUploadDetails, path?: string }];

📜 Recent review details

Configuration used: Organization 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 4a84a2a and 0f7416c.

⛔ Files ignored due to path filters (2)
  • apps/meteor/tests/data/apps/app-packages/file-upload-test_0.0.1.zip is excluded by !**/*.zip
  • packages/apps-engine/deno-runtime/deno.lock is excluded by !**/*.lock
📒 Files selected for processing (20)
  • .changeset/spotty-steaks-notice.md
  • apps/meteor/app/apps/server/bridges/listeners.ts
  • apps/meteor/ee/server/apps/orchestrator.js
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/deno-runtime/deno.jsonc
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
  • packages/apps-engine/src/definition/uploads/IFileUploadContext.ts
  • packages/apps-engine/src/server/AppManager.ts
  • packages/apps-engine/src/server/ProxiedApp.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • packages/apps-engine/src/server/compiler/AppPackageParser.ts
  • packages/apps-engine/src/server/managers/AppListenerManager.ts
  • packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • packages/apps-engine/tests/test-data/utilities.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/apps-engine/src/server/managers/AppListenerManager.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • packages/apps-engine/src/server/AppManager.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts
  • apps/meteor/tests/data/apps/app-packages/index.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{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:

  • packages/apps-engine/src/server/ProxiedApp.ts
  • packages/apps-engine/tests/test-data/utilities.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • packages/apps-engine/src/server/compiler/AppPackageParser.ts
  • apps/meteor/app/apps/server/bridges/listeners.ts
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/ee/server/apps/orchestrator.js
  • packages/apps-engine/src/definition/uploads/IFileUploadContext.ts
🧠 Learnings (23)
📚 Learning: 2026-01-08T15:07:57.458Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38068
File: packages/apps-engine/deno-runtime/handlers/lib/assertions.ts:8-12
Timestamp: 2026-01-08T15:07:57.458Z
Learning: In packages/apps-engine/deno-runtime, App objects are never serialized and are instantiated and kept in the runtime context, so duck-typing checks on App methods (including protected methods like extendConfiguration) are reliable for runtime assertions.

Applied to files:

  • packages/apps-engine/src/server/ProxiedApp.ts
📚 Learning: 2025-10-06T20:30:45.540Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/storage/storage.ts:101-122
Timestamp: 2025-10-06T20:30:45.540Z
Learning: In `packages/apps-engine/tests/test-data/storage/storage.ts`, the stub methods (updatePartialAndReturnDocument, updateStatus, updateSetting, updateAppInfo, updateMarketplaceInfo) intentionally throw "Method not implemented." Tests using these methods must stub them using `SpyOn` from the test library rather than relying on actual implementations.

Applied to files:

  • packages/apps-engine/tests/test-data/utilities.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • packages/apps-engine/tests/test-data/utilities.ts
  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
📚 Learning: 2026-01-08T15:03:59.621Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38068
File: apps/meteor/tests/data/apps/app-packages/README.md:14-16
Timestamp: 2026-01-08T15:03:59.621Z
Learning: For the RocketChat/Rocket.Chat repository, do not analyze or report formatting issues (such as hard tabs vs spaces, line breaks, etc.). The project relies on automated linting tools to enforce formatting standards.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/ee/server/apps/orchestrator.js
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-10-16T21:09:51.816Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/keychain.ts:148-156
Timestamp: 2025-10-16T21:09:51.816Z
Learning: In the RocketChat/Rocket.Chat repository, only platforms with native crypto.randomUUID() support are targeted, so fallback implementations for crypto.randomUUID() are not required in E2EE or cryptographic code.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/app/apps/server/bridges/listeners.ts
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2026-01-08T15:07:47.836Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38068
File: packages/apps-engine/deno-runtime/handlers/lib/assertions.ts:8-12
Timestamp: 2026-01-08T15:07:47.836Z
Learning: In packages/apps-engine/deno-runtime, App objects are never serialized; they are instantiated and kept in the runtime context. Therefore, runtime assertions can rely on duck-typing checks of App methods (including protected ones like extendConfiguration) as reliable. When reviewing code in this area, prefer duck-typing checks for App behavior in assertions and avoid assuming serialization/deserialization will preserve App state. This guideline applies to files under this directory.

Applied to files:

  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-19T18:20:07.720Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
🧬 Code graph analysis (2)
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (3)
packages/apps-engine/deno-runtime/handlers/lib/assertions.ts (3)
  • isRecord (4-12)
  • assertAppAvailable (22-26)
  • assertHandlerFunction (29-33)
packages/apps-engine/src/definition/uploads/IFileUploadContext.ts (1)
  • IFileUploadContext (8-11)
packages/apps-engine/deno-runtime/lib/accessors/mod.ts (1)
  • AppAccessorsInstance (322-322)
apps/meteor/tests/data/apps/helper.ts (1)
apps/meteor/tests/data/apps/apps-data.ts (1)
  • apps (10-12)
🪛 Biome (2.1.2)
apps/meteor/ee/server/apps/orchestrator.js

[error] 1-1: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 1-2: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 2-3: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)

🪛 markdownlint-cli2 (0.18.1)
apps/meteor/tests/data/apps/app-packages/README.md

14-14: Hard tabs
Column: 1

(MD010, no-hard-tabs)


15-15: Hard tabs
Column: 1

(MD010, no-hard-tabs)


16-16: Hard tabs
Column: 1

(MD010, no-hard-tabs)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (17)
packages/apps-engine/src/server/ProxiedApp.ts (2)

1-2: LGTM!

The inspect import from Node.js built-in util is appropriate for improved error logging.


78-84: LGTM — improved error visibility for debugging.

Using inspect(e, { depth: 10 }) provides richer output for nested error objects that would otherwise truncate to [Object]. This is a good improvement for diagnosing JSON-RPC issues.

Note: The condition on line 81 (e.code >= -32999 || e.code <= -32000) appears to always evaluate to true due to the || operator — likely should be && to properly check the JSON-RPC error code range. This is a pre-existing issue outside the scope of this change, but worth addressing separately if you agree.

packages/apps-engine/deno-runtime/deno.jsonc (1)

7-7: LGTM!

The @std/streams import is correctly added with a caret range (^1.0.16), consistent with the versioning style of other imports like @std/cli. This dependency supports the new file streaming functionality for the IPreFileUpload event optimization.

.changeset/spotty-steaks-notice.md (1)

1-6: LGTM!

The changeset correctly identifies both affected packages (@rocket.chat/apps-engine and @rocket.chat/meteor) as patch releases, and the description accurately summarizes the memory usage fix for the IPreFileUpload event.

packages/apps-engine/tests/test-data/utilities.ts (1)

133-133: LGTM!

The mock getTempFilePath method correctly mirrors the production AppManager API, enabling test infrastructure to access a consistent temp file path value.

packages/apps-engine/src/definition/uploads/IFileUploadContext.ts (1)

3-6: LGTM!

The new IFileUploadInternalContext interface cleanly separates internal file handling (using a file path) from the app-facing IFileUploadContext (which includes the buffer). This design directly supports the PR objective of reducing memory usage by passing file paths instead of buffer contents over stdio.

apps/meteor/ee/server/apps/orchestrator.js (2)

1-4: LGTM!

Standard Node.js module imports for file system operations required by the temp directory functionality.


75-92: LGTM!

The temp directory initialization is well-implemented:

  • Synchronous mkdirSync is appropriate at startup as noted in the comment.
  • EEXIST handling ensures idempotent initialization across restarts.
  • Other errors are properly wrapped with cause for debugging context.
  • The tempFilePath is correctly passed to AppManager configuration.
apps/meteor/tests/data/apps/helper.ts (2)

24-27: LGTM - Improved test cleanup.

The updated cleanupApps now removes all installed apps instead of just a single named app. This is better for test isolation and ensures a clean state between test runs.


42-54: LGTM - Well-implemented local package installer.

The new installLocalTestPackage function correctly uses supertest's .attach() for file uploads and includes proper error handling with reject/resolve paths, unlike the existing installTestApp which silently resolves even on errors.

apps/meteor/tests/data/apps/app-packages/README.md (1)

1-54: LGTM - Clear and helpful documentation.

The README provides good documentation for the test app packages, including usage examples and behavior descriptions for the IPreFileUpload handler app.

apps/meteor/app/apps/server/bridges/listeners.ts (2)

252-284: LGTM - Well-structured temp file handling.

The uploadEvent implementation correctly:

  • Uses crypto.randomUUID() for unique temp filenames
  • Employs a finally block to ensure temp file cleanup even on errors
  • Logs errors appropriately without crashing on cleanup failures
  • Wraps errors with cause for better debugging

269-269: The token property exists on the IUpload interface from @rocket.chat/core-typings—no changes needed.

The code accessing file.token is valid. The IUpload type includes token?: string, making this a correct property access for livechat visitor uploads.

packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (1)

40-40: Good use of using for resource management.

The using keyword with Deno.open ensures the file handle is automatically closed when leaving the scope, even if an error occurs. This is the idiomatic Deno pattern for resource cleanup.

packages/apps-engine/src/server/compiler/AppImplements.ts (2)

15-23: LGTM - Good API clarity improvement.

Renaming the setter from doesImplement to setImplements and adding a proper getter doesImplement that returns a boolean improves API semantics. The naming now clearly distinguishes between setting and querying implementation status.


5-5: LGTM - Improved type safety.

Changing from { [key: string]: boolean } to Record<AppInterface, boolean> provides better type safety and IDE support throughout the codebase.

Also applies to: 25-25, 29-29

packages/apps-engine/src/server/compiler/AppPackageParser.ts (1)

85-89: Semantic improvement is correct; type alignment is sound.

The rename from doesImplement to setImplements clarifies the setter semantics. Type alignment is verified: IAppInfo.implements is typed as Array<AppInterface>, matching the setImplements(int: AppInterface) parameter type. Runtime validation in setImplements (checking if (int in AppInterface)) provides defensive safeguards.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 5, 2026

📦 Docker Image Size Report

➡️ Changes

Service Current Baseline Change Percent
sum of all images 0B 0B 0B
account-service 0B 0B 0B
authorization-service 0B 0B 0B
ddp-streamer-service 0B 0B 0B
omnichannel-transcript-service 0B 0B 0B
presence-service 0B 0B 0B
queue-worker-service 0B 0B 0B
rocketchat 0B 0B 0B

📊 Historical Trend

---
config:
  theme: "dark"
  xyChart:
    width: 900
    height: 400
---
xychart
  title "Image Size Evolution by Service (Last 30 Days + This PR)"
  x-axis ["11/18 22:53", "11/19 23:02", "11/21 16:49", "11/24 17:34", "11/27 22:32", "11/28 19:05", "12/01 23:01", "12/02 21:57", "12/03 21:00", "12/04 18:17", "12/05 21:56", "12/08 20:15", "12/09 22:17", "12/10 23:26", "12/11 21:56", "12/12 22:45", "12/13 01:34", "12/15 22:31", "12/16 22:18", "12/17 21:04", "12/18 23:12", "12/19 23:27", "12/20 21:03", "12/22 18:54", "12/23 16:16", "12/24 19:38", "12/25 17:51", "12/26 13:18", "12/29 19:01", "12/30 20:52", "01/14 21:17 (PR)"]
  y-axis "Size (GB)" 0 --> 0.5
  line "account-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "authorization-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "ddp-streamer-service" [0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.12, 0.00]
  line "omnichannel-transcript-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "presence-service" [0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.11, 0.00]
  line "queue-worker-service" [0.14, 0.14, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.13, 0.00]
  line "rocketchat" [0.35, 0.35, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.34, 0.00]
Loading

Statistics (last 30 days):

  • 📊 Average: 1.5GiB
  • ⬇️ Minimum: 1.4GiB
  • ⬆️ Maximum: 1.6GiB
  • 🎯 Current PR: 0B
ℹ️ About this report

This report compares Docker image sizes from this build against the develop baseline.

  • Tag: pr-38068
  • Baseline: develop
  • Timestamp: 2026-01-14 21:17:45 UTC
  • Historical data points: 30

Updated: Wed, 14 Jan 2026 21:17:45 GMT

@codecov
Copy link

codecov bot commented Jan 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.66%. Comparing base (46383a6) to head (0f7416c).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #38068      +/-   ##
===========================================
- Coverage    70.70%   70.66%   -0.05%     
===========================================
  Files         3147     3147              
  Lines       108851   108851              
  Branches     19625    19588      -37     
===========================================
- Hits         76965    76921      -44     
- Misses       29886    29922      +36     
- Partials      2000     2008       +8     
Flag Coverage Δ
e2e 60.13% <ø> (-0.08%) ⬇️
e2e-api 47.34% <ø> (-1.06%) ⬇️
unit 71.82% <ø> (-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 feat(apps): new apps-engine upload event and stop handling buffers directly feat(apps): reduce memory usage on apps-engine IPreFileUpload event Jan 6, 2026
@d-gubert d-gubert force-pushed the feat/apps-file-stream branch 3 times, most recently from 1b12ada to d66b200 Compare January 7, 2026 23:13
@d-gubert d-gubert changed the title feat(apps): reduce memory usage on apps-engine IPreFileUpload event fix(apps): reduce memory usage on apps-engine IPreFileUpload event Jan 7, 2026
@d-gubert d-gubert force-pushed the feat/apps-file-stream branch from 44e518b to 69549c2 Compare January 8, 2026 13:56
@d-gubert d-gubert added this to the 8.1.0 milestone Jan 8, 2026
@d-gubert d-gubert marked this pull request as ready for review January 8, 2026 14:55
@d-gubert d-gubert requested review from a team as code owners January 8, 2026 14:55
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: 7

Caution

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

⚠️ Outside diff range comments (1)
packages/apps-engine/src/server/AppManager.ts (1)

119-149: Add validation for tempFilePath in constructor.

Unlike other dependencies (metadataStorage, logStorage, bridges, sourceStorage), the tempFilePath parameter lacks validation. Consider adding a check to ensure it's a non-empty string.

🛡️ Proposed validation
 	if (sourceStorage instanceof AppSourceStorage) {
 		this.appSourceStorage = sourceStorage;
 	} else {
 		throw new Error('Invalid instance of the AppSourceStorage');
 	}

+	if (typeof tempFilePath !== 'string' || !tempFilePath.trim()) {
+		throw new Error('Invalid tempFilePath: must be a non-empty string');
+	}
+
 	this.tempFilePath = tempFilePath;
🤖 Fix all issues with AI agents
In @apps/meteor/app/apps/server/bridges/listeners.js:
- Around line 89-109: The uploadEvent handler can throw after writing tmpfile
(during convertToApp or executeListener) and never delete tmpfile; wrap the
conversion and listener execution in a try/finally: perform const appFile =
await this.orch.getConverters().get('uploads').convertToApp(file) and await
this.orch.getManager().getListenerManager().executeListener(...) inside the try,
and in the finally always attempt fs.promises.unlink(tmpfile) with the existing
warning log on failure (but do not let unlink errors mask the original error).

In @apps/meteor/tests/data/apps/app-packages/README.md:
- Around line 14-16: Replace the hard tabs used to indent the test setup block
so that the lines containing before(async () => { await
installLocalTestPackage(appImplementsIPreFileUpload); }); use spaces for
indentation; update the indentation for that entire snippet (and any adjacent
lines using tabs) to match the repository's space-based style and re-run the
linter or formatter to ensure consistency.

In @apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts:
- Line 38: Replace the incorrect Chai assertion on the error property (the line
starting with expect(res.body).to.have.property('error')): remove the invalid
`.that.is.string(fileContents)` chain and instead assert the property contains
the file contents, e.g. use `.that.includes(fileContents)` or
`.that.is.a('string').and.includes(fileContents)` so the test verifies the error
message contains the expected fileContents.

In @packages/apps-engine/deno-runtime/deno.jsonc:
- Line 7: The "@std/streams" dependency is pinned to an exact version ("1.0.16")
whereas "@std/cli" uses a caret range; update the "@std/streams" entry to use a
caret range ("^1.0.16") to match versioning style and allow minor/patch updates
unless you intentionally need an exact pin, i.e., change the value for the
"@std/streams" key to "^1.0.16".

In @packages/apps-engine/deno-runtime/handlers/lib/assertions.ts:
- Around line 4-6: The isRecord type guard currently returns true for arrays
because arrays are typeof 'object'; update isRecord(v: unknown): v is
Record<string, unknown> to also ensure v is not null and not an array (e.g., add
a check like !Array.isArray(v) or use Object.prototype.toString) so only plain
objects qualify; keep the function name isRecord and its signature unchanged
while adding the array exclusion to the boolean expression.
- Around line 8-12: The current assertAppAvailable uses a fragile duck-type
check on the protected method extendConfiguration; replace that with a stronger
discriminator by checking a combination of public IApp methods (e.g., verify
typeof (v as App).getID === 'function' && typeof (v as App).getStatus ===
'function' && typeof (v as App).getVersion === 'function') inside
assertAppAvailable so only objects implementing those public methods pass; keep
the same JsonRpcError.internalError throw when the check fails and update the
type assertion to asserts v is App.

In @packages/apps-engine/src/server/compiler/AppImplements.ts:
- Around line 7-13: In the AppImplements constructor the Object.keys iteration
types keys as string which conflicts with the AppInterface type; fix by
iterating using Object.values(AppInterface).forEach((int: AppInterface) => {
this.implemented[int] = false; }) or cast the keys with
(Object.keys(AppInterface) as AppInterface[]).forEach to ensure the loop
variable is AppInterface; update the constructor in AppImplements to use one of
these approaches so implemented is correctly initialized without TypeScript
errors.
🧹 Nitpick comments (4)
packages/apps-engine/src/server/ProxiedApp.ts (1)

83-83: Improved error logging with detailed inspection.

The change from logging the raw error object to using inspect with depth: 10 provides more detailed visibility into nested error structures, which is valuable for debugging JSON-RPC errors.

💡 Optional: Consider adding output limits

For extremely large or complex error objects, you could add limits to prevent excessive log output:

-console.error('JSON-RPC error received: ', inspect(e, { depth: 10 }));
+console.error('JSON-RPC error received: ', inspect(e, { depth: 10, maxArrayLength: 100, maxStringLength: 1000 }));

This would cap array and string lengths in the output while still providing detailed debugging information.

apps/meteor/ee/server/apps/orchestrator.js (1)

75-85: Validate the temp directory path and consider cleanup strategy.

The temp directory creation is sound, but consider these improvements:

  1. The path from os.tmpdir() could theoretically be empty or invalid—add a guard
  2. The error message could specify which directory failed to create
  3. Consider documenting the cleanup strategy for temp files (e.g., does the OS handle it, or should there be a shutdown hook?)
🔒 Proposed validation enhancement
 const tempFilePath = path.join(os.tmpdir(), 'apps-engine-temp');
+
+if (!tempFilePath || typeof tempFilePath !== 'string') {
+	throw new Error('Failed to resolve temporary directory path');
+}

 try {
 	// We call this only once at server startup, so using the synchronous version is fine
 	fs.mkdirSync(tempFilePath);
 } catch (err) {
 	// If the temp directory already exists, we can continue
 	if (err.code !== 'EEXIST') {
-		throw new Error('Failed to initialize the Apps-Engine', { cause: err });
+		throw new Error(`Failed to initialize the Apps-Engine temp directory at ${tempFilePath}`, { cause: err });
 	}
 }
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (2)

16-20: Strengthen IUpload validation.

The current validation only checks that user and room are objects, which is quite minimal. Consider validating additional required fields to fail fast on malformed uploads.

🔍 More thorough validation
 function assertIsUpload(v: unknown): asserts v is IUpload {
-	if (isRecord(v) && isRecord(v.user) && isRecord(v.room)) return;
+	if (
+		isRecord(v) &&
+		isRecord(v.user) &&
+		isRecord(v.room) &&
+		typeof v.name === 'string' &&
+		typeof v.type === 'string'
+	) return;

 	throw JsonRpcError.invalidParams({ err: `Invalid 'file' parameter. Expected IUploadDetails, got`, value: v });
 }

Note: Adjust the fields based on the actual IUpload interface requirements.


28-38: Validate params structure before destructuring.

The destructuring at line 29 assumes params is an array with a specific structure. If params is malformed, this will fail silently or throw a cryptic error.

🛡️ Add params validation
 export default async function handleUploadEvents(method: typeof uploadEvents[number], params: unknown): Promise<Defined | JsonRpcError> {
+	if (!Array.isArray(params) || params.length === 0) {
+		return JsonRpcError.invalidParams({ err: 'Expected params to be a non-empty array' });
+	}
+
 	const [{ file, path }] = params as [{ file?: IUpload, path?: string }];

 	const app = AppObjectRegistry.get<App>('app');
 	const handlerFunction = app?.[method as keyof App] as unknown;

 	try {
 		assertAppAvailable(app);
 		assertHandlerFunction(handlerFunction);
 		assertIsUpload(file);
 		assertString(path);
📜 Review details

Configuration used: Organization 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 7d86bc9 and 69549c2.

⛔ Files ignored due to path filters (2)
  • apps/meteor/tests/data/apps/app-packages/file-upload-test_0.0.1.zip is excluded by !**/*.zip
  • packages/apps-engine/deno-runtime/deno.lock is excluded by !**/*.lock
📒 Files selected for processing (20)
  • .changeset/spotty-steaks-notice.md
  • apps/meteor/app/apps/server/bridges/listeners.js
  • apps/meteor/ee/server/apps/orchestrator.js
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/deno-runtime/deno.jsonc
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
  • packages/apps-engine/src/definition/uploads/IFileUploadContext.ts
  • packages/apps-engine/src/server/AppManager.ts
  • packages/apps-engine/src/server/ProxiedApp.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • packages/apps-engine/src/server/compiler/AppPackageParser.ts
  • packages/apps-engine/src/server/managers/AppListenerManager.ts
  • packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • packages/apps-engine/tests/test-data/utilities.ts
🧰 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:

  • packages/apps-engine/src/server/ProxiedApp.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/src/server/managers/AppListenerManager.ts
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • packages/apps-engine/src/server/AppManager.ts
  • apps/meteor/ee/server/apps/orchestrator.js
  • packages/apps-engine/src/server/compiler/AppPackageParser.ts
  • packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
  • packages/apps-engine/tests/test-data/utilities.ts
  • apps/meteor/app/apps/server/bridges/listeners.js
  • packages/apps-engine/src/definition/uploads/IFileUploadContext.ts
  • apps/meteor/tests/data/apps/helper.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/src/server/compiler/AppImplements.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:

  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
🧠 Learnings (16)
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • packages/apps-engine/tests/test-data/utilities.ts
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • packages/apps-engine/tests/test-data/utilities.ts
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • packages/apps-engine/tests/test-data/utilities.ts
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/tests/test-data/utilities.ts
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/index.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
📚 Learning: 2025-10-06T20:30:45.540Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/storage/storage.ts:101-122
Timestamp: 2025-10-06T20:30:45.540Z
Learning: In `packages/apps-engine/tests/test-data/storage/storage.ts`, the stub methods (updatePartialAndReturnDocument, updateStatus, updateSetting, updateAppInfo, updateMarketplaceInfo) intentionally throw "Method not implemented." Tests using these methods must stub them using `SpyOn` from the test library rather than relying on actual implementations.

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
  • packages/apps-engine/tests/test-data/utilities.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-12-16T17:29:45.163Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37834
File: apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts:12-22
Timestamp: 2025-12-16T17:29:45.163Z
Learning: In page object files under `apps/meteor/tests/e2e/page-objects/`, always import `expect` from `../../utils/test` (Playwright's async expect), not from Jest. Jest's `expect` has a synchronous signature and will cause TypeScript errors when used with web-first assertions like `toBeVisible()`.

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/index.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Store commonly used locators in variables/constants for reuse

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/index.ts
  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
🧬 Code graph analysis (6)
packages/apps-engine/src/server/managers/AppListenerManager.ts (1)
packages/apps-engine/src/definition/uploads/IFileUploadContext.ts (1)
  • IFileUploadInternalContext (3-6)
apps/meteor/ee/server/apps/orchestrator.js (1)
packages/apps-engine/src/server/AppManager.ts (1)
  • AppManager (71-1232)
apps/meteor/app/apps/server/bridges/listeners.js (1)
packages/apps/src/AppsEngine.ts (1)
  • AppInterface (13-13)
packages/apps-engine/tests/server/compiler/AppImplements.spec.ts (1)
packages/apps/src/AppsEngine.ts (1)
  • AppInterface (13-13)
packages/apps-engine/deno-runtime/handlers/app/handler.ts (1)
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (2)
  • uploadEvents (14-14)
  • handleUploadEvents (28-73)
packages/apps-engine/src/server/compiler/AppImplements.ts (1)
packages/apps/src/AppsEngine.ts (1)
  • AppInterface (13-13)
🪛 Biome (2.1.2)
apps/meteor/ee/server/apps/orchestrator.js

[error] 1-1: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 1-2: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 2-3: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)

apps/meteor/app/apps/server/bridges/listeners.js

[error] 1-1: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 1-2: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 2-3: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 4-5: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 5-6: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)

🪛 markdownlint-cli2 (0.18.1)
apps/meteor/tests/data/apps/app-packages/README.md

14-14: Hard tabs
Column: 1

(MD010, no-hard-tabs)


15-15: Hard tabs
Column: 1

(MD010, no-hard-tabs)


16-16: Hard tabs
Column: 1

(MD010, no-hard-tabs)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: cubic · AI code reviewer
🔇 Additional comments (32)
packages/apps-engine/src/server/ProxiedApp.ts (1)

1-1: LGTM: Standard Node.js import.

The import of inspect from the 'util' module is correctly added to support enhanced error logging.

packages/apps-engine/deno-runtime/deno.jsonc (1)

7-7: Package version and security check complete.

@std/streams@1.0.16 exists in the JSR registry and has no known public security advisories.

packages/apps-engine/src/server/managers/AppListenerManager.ts (1)

28-28: LGTM! Consistent type update to IFileUploadInternalContext.

The transition from IFileUploadContext to IFileUploadInternalContext is applied consistently across the interface definition (line 208), switch case (line 451), and method signature (line 1173). This aligns with the PR's goal of passing temporary file paths instead of file contents for the IPreFileUpload event.

Also applies to: 207-210, 451-451, 1173-1179

.changeset/spotty-steaks-notice.md (1)

1-6: LGTM! Clear changeset description.

The changeset accurately describes the memory usage fix for the IPreFileUpload event handler.

apps/meteor/tests/data/apps/app-packages/README.md (1)

1-54: Helpful test documentation.

The README provides clear instructions and example code for using test app packages, including the app's source code for reference.

packages/apps-engine/tests/test-data/utilities.ts (1)

133-133: LGTM! Appropriate test mock for getTempFilePath.

The mock returns a deterministic constant string, which is suitable for test purposes and consistent with other mock implementations in this test utility class.

packages/apps-engine/src/definition/uploads/IFileUploadContext.ts (1)

3-6: LGTM!

The new IFileUploadInternalContext interface appropriately uses a file path instead of a Buffer, aligning with the PR's goal to reduce memory pressure during file upload events.

apps/meteor/tests/data/apps/helper.ts (2)

24-27: LGTM!

The parallel cleanup of all apps improves test isolation and prevents leftover state from affecting tests.


42-54: LGTM!

The new helper function follows the existing pattern and provides the necessary functionality for installing local test packages.

apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts (2)

12-24: LGTM!

The test suite structure properly handles setup and teardown, ensuring clean state for each test execution.


42-54: LGTM!

The test properly validates the success case when the app doesn't prevent the upload.

apps/meteor/tests/data/apps/app-packages/index.ts (1)

1-3: LGTM!

The path resolution is correct and provides the necessary test package location for the integration tests.

apps/meteor/app/apps/server/bridges/listeners.js (2)

1-3: LGTM!

The new imports and JSDoc annotation support the file streaming implementation appropriately.

Also applies to: 10-13


20-21: LGTM!

The case properly routes IPreFileUpload events to the new uploadEvent handler.

apps/meteor/ee/server/apps/orchestrator.js (2)

1-3: LGTM: Standard Node.js imports for temp directory handling.

The imports are appropriate for the temp file infrastructure being added.


92-92: LGTM: Temp file path correctly passed to AppManager.

The tempFilePath is properly integrated into the AppManager configuration.

packages/apps-engine/src/server/AppManager.ts (2)

57-62: LGTM: Well-documented interface extension.

The tempFilePath addition to IAppManagerDeps is properly typed and documented.


173-180: LGTM: Clear and documented getter.

The getTempFilePath() method is appropriately documented and provides proper encapsulation.

packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts (3)

14-14: LGTM: Import change supports runtime type checking.

Changing from a type-only import to named imports is necessary for the runtime check at line 160 (appPackage.implemented.doesImplement(AppInterface.IPreFileUpload)).


118-142: LGTM: Temp file path properly initialized.

The tempFilePath is correctly retrieved from the AppManager and stored as a readonly field.


157-167: Good security practice: conditional read permissions for temp directory.

The conditional granting of read access to tempFilePath only when the app implements IPreFileUpload follows the principle of least privilege. This ensures apps cannot access temporary files unless they explicitly handle upload events.

packages/apps-engine/deno-runtime/handlers/app/handler.ts (3)

20-24: Type-safe array includes check via global augmentation.

This augmentation enables TypeScript to narrow the type of appMethod when uploadEvents.includes(appMethod) returns true. While global augmentations can have broad impact, this is a common pattern for achieving type narrowing with readonly arrays.


40-48: LGTM: Centralized result formatting improves consistency.

The formatResult helper consolidates logging for success and error cases, ensuring uniform debug output across upload events, UIKit interactions, and listener handlers.


50-60: Proper routing order for upload events.

Upload events are evaluated before UIKit interactions and listeners, which ensures proper priority. All three branches now use the centralized formatResult for consistent logging.

packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (2)

40-48: LGTM: Proper temp file handling with automatic cleanup.

The using syntax ensures the temp file is automatically closed when the scope exits, preventing resource leaks. Reading the file contents into a Buffer is appropriate for the IFileUploadContext.


59-72: Good error handling with type distinction.

The error handling properly distinguishes between AppsEngineException, JsonRpcError, and generic errors, mapping each to an appropriate JSON-RPC response.

Minor: The catch parameter at line 59 lacks a type annotation. Consider catch (e: unknown) for clarity.

packages/apps-engine/tests/server/compiler/AppImplements.spec.ts (1)

14-18: LGTM! Test correctly validates the updated API.

The test properly exercises the new API sequence: calling setImplements to register an interface, then using doesImplement to query implementation status, and finally verifying internal state consistency with getValues(). Good coverage of both positive (implemented) and negative (not implemented) cases.

packages/apps-engine/src/server/compiler/AppImplements.ts (4)

15-19: Method implementation looks correct.

The setImplements method properly validates enum membership with the in check. However, note that this creates a type contract that expects AppInterface enum values, not strings. Callers passing strings (like in AppPackageParser.ts line 88) will need to cast appropriately.


21-23: LGTM! Good API improvement.

The method now returns the implementation status as a boolean, which is more intuitive than the previous void return. The implementation correctly accesses the internal map.


25-27: LGTM! Type-safe accessor with immutability protection.

The return type tightening to Record<AppInterface, boolean> improves type safety, and using deepCloneAndFreeze ensures the internal state cannot be mutated by callers.


29-31: LGTM! Consistent serialization behavior.

The method correctly delegates to getValues() and maintains type consistency with the new Record<AppInterface, boolean> return type.

packages/apps-engine/src/server/compiler/AppPackageParser.ts (1)

87-89: The code is properly typed. The info variable is explicitly cast as IAppInfo on line 31 (as IAppInfo), and the IAppInfo interface declares implements as Array<AppInterface>, not Array<string>. Therefore, interfaceName is typed as AppInterface when it enters the loop, and the parameter passed to setImplements() matches its expected type. Since AppInterface is a string enum, the string values from the JSON naturally align with the enum values, requiring no additional type conversion.

Likely an incorrect or invalid review comment.

Copy link
Contributor

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

Choose a reason for hiding this comment

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

2 issues found across 22 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="apps/meteor/app/apps/server/bridges/listeners.js">

<violation number="1" location="apps/meteor/app/apps/server/bridges/listeners.js:99">
P1: Temporary file will not be cleaned up if `convertToApp()` or `executeListener()` throws an error. Wrap the operations in a try-finally block to ensure cleanup always occurs, preventing disk space leaks over time.</violation>
</file>

<file name="packages/apps-engine/deno-runtime/handlers/app/handler.ts">

<violation number="1" location="packages/apps-engine/deno-runtime/handlers/app/handler.ts:20">
P2: Global type augmentation modifies `ReadonlyArray.includes` for the entire runtime. Consider using a scoped type guard function instead to avoid affecting other code that may rely on the standard signature.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

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: 2

🤖 Fix all issues with AI agents
In @apps/meteor/app/apps/server/bridges/listeners.js:
- Around line 84-88: The JSDoc incorrectly marks the async function as returning
void; update the @return/@returns annotation to Promise<void> (or remove the
@returns line entirely) so the JSDoc matches the actual async return type for
the documented function in listeners.js.
- Around line 99-103: The inline comment "Execute both events for backward
compatibility" is misleading because only AppInterface.IPreFileUpload is being
executed; update or remove it: change the comment to "Execute this event for
backward compatibility" (or remove the comment) near the call to
this.orch.getManager().getListenerManager().executeListener(AppInterface.IPreFileUpload,
{ file: appFile, path: tmpfile }), ensuring the comment accurately reflects that
only IPreFileUpload is invoked after converting the file via
this.orch.getConverters().get('uploads').convertToApp(file).
🧹 Nitpick comments (1)
packages/apps-engine/deno-runtime/handlers/app/handler.ts (1)

35-43: Add missing semicolon after function expression.

Minor style consistency: the function expression should end with a semicolon.

Suggested fix
 		const formatResult = (result: Defined | JsonRpcError): Defined | JsonRpcError => {
 			if (result instanceof JsonRpcError) {
 				app?.getLogger().debug(`'${appMethod}' was unsuccessful.`, result.message);
 			} else {
 				app?.getLogger().debug(`'${appMethod}' was successfully called! The result is:`, result);
 			}

 			return result;
-		}
+		};
📜 Review details

Configuration used: Organization 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 69549c2 and 5beb59f.

⛔ Files ignored due to path filters (1)
  • packages/apps-engine/deno-runtime/deno.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • apps/meteor/app/apps/server/bridges/listeners.js
  • packages/apps-engine/deno-runtime/deno.jsonc
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/apps-engine/deno-runtime/deno.jsonc
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{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:

  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • apps/meteor/app/apps/server/bridges/listeners.js
🧠 Learnings (1)
📚 Learning: 2026-01-08T15:07:47.836Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38068
File: packages/apps-engine/deno-runtime/handlers/lib/assertions.ts:8-12
Timestamp: 2026-01-08T15:07:47.836Z
Learning: In packages/apps-engine/deno-runtime, App objects are never serialized; they are instantiated and kept in the runtime context. Therefore, runtime assertions can rely on duck-typing checks of App methods (including protected ones like extendConfiguration) as reliable. When reviewing code in this area, prefer duck-typing checks for App behavior in assertions and avoid assuming serialization/deserialization will preserve App state. This guideline applies to files under this directory.

Applied to files:

  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
🧬 Code graph analysis (2)
packages/apps-engine/deno-runtime/handlers/app/handler.ts (2)
packages/apps-engine/deno-runtime/handlers/lib/assertions.ts (1)
  • isOneOf (18-20)
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (2)
  • uploadEvents (14-14)
  • handleUploadEvents (28-73)
apps/meteor/app/apps/server/bridges/listeners.js (1)
packages/apps/src/AppsEngine.ts (1)
  • AppInterface (13-13)
🪛 Biome (2.1.2)
apps/meteor/app/apps/server/bridges/listeners.js

[error] 1-1: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 1-2: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 2-3: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 4-5: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 5-6: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (9)
packages/apps-engine/deno-runtime/handlers/app/handler.ts (4)

18-19: LGTM!

Clean imports for the new upload event handling and type-safe membership check utility.


45-47: LGTM!

Correct routing for upload events with proper type narrowing via isOneOf. The placement before the generic check/execute listener check (line 53) correctly ensures executePreFileUpload is routed here rather than to handleListener.


49-55: LGTM!

Good refactoring to use isOneOf for UIKit interactions, maintaining consistency with the new upload events check. The ordering (upload events → UIKit → generic listeners) correctly routes methods from most specific to least specific.


57-111: LGTM!

The switch statement for lifecycle methods remains clean and unchanged. The separate logging path (line 94) for these methods is appropriate since formatResult is only applied to the early-return event handler branches.

apps/meteor/app/apps/server/bridges/listeners.js (5)

1-4: LGTM!

The new imports are necessary for the temporary file handling workflow in uploadEvent.


20-21: LGTM!

The routing for IPreFileUpload follows the established pattern and correctly delegates to the new uploadEvent method.


104-110: LGTM!

The finally block correctly ensures temporary file cleanup occurs regardless of whether the listener succeeds or fails. Logging cleanup failures as warnings (without re-throwing) is the appropriate behavior since the primary operation has already completed.


10-13: Nice improvement!

Adding the JSDoc type annotation for the orch property improves IDE support and code documentation.


89-97: The review comment raises an invalid concern. The getTempFilePath() method is guaranteed to return a valid directory path because:

  1. It's a required string parameter in the AppManager constructor (line 119 of packages/apps-engine/src/server/AppManager.ts)
  2. At server startup (apps/meteor/ee/server/apps/orchestrator.js lines 75-81), the temp directory is created via fs.mkdirSync(path.join(os.tmpdir(), 'apps-engine-temp'))
  3. The temp path is verified to exist before AppManager instantiation
  4. The getter simply returns the initialized this.tempFilePath field directly

The code in listeners.js line 92 is safe.

Likely an incorrect or invalid review comment.

@d-gubert d-gubert force-pushed the feat/apps-file-stream branch from 5beb59f to 5e033ba Compare January 8, 2026 16:08
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: 3

🤖 Fix all issues with AI agents
In @packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts:
- Around line 16-20: The validation in assertIsUpload currently throws a
JsonRpcError.invalidParams referencing the wrong type name ("IUploadDetails");
update the error message to accurately reference "IUpload" (the type this
function asserts) and keep the rest of the payload (err/value) intact so
debugging shows the correct expected type and the failing value; locate this in
the assertIsUpload function and change the message text only.
- Around line 28-29: The function handleUploadEvents currently destructures
params directly; first validate that params is an array with at least one
element and that params[0] is a non-null object before doing const [{ file, path
}]; specifically check Array.isArray(params) && params.length > 0 && typeof
params[0] === "object" && params[0] !== null, then safely extract file and path
(or default them) and return the appropriate JsonRpcError if the check fails so
existing validation logic (and types like IUpload, Defined, JsonRpcError) can
run only on well-formed input.

In @packages/apps-engine/src/server/compiler/AppImplements.ts:
- Around line 7-13: The forEach callback in the AppImplements constructor is
incorrectly typing the iteratee as AppInterface; change the callback parameter
to string (or remove the explicit type) and then cast/validate each key to
AppInterface before assigning into this.implemented; e.g., iterate
Object.keys(AppInterface) with (key: string) and perform a safe cast like const
intf = key as AppInterface (or check membership) before doing
this.implemented[intf] = false to ensure correct typing and avoid misleading
annotations.
🧹 Nitpick comments (3)
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (1)

5-6: Add missing semicolons for consistency.

These import statements are missing trailing semicolons, while all other imports in the file include them.

♻️ Proposed fix
-import type { IFileUploadContext } from '@rocket.chat/apps-engine/definition/uploads/IFileUploadContext.ts'
-import type { IUpload } from '@rocket.chat/apps-engine/definition/uploads/IUpload.ts'
+import type { IFileUploadContext } from '@rocket.chat/apps-engine/definition/uploads/IFileUploadContext.ts';
+import type { IUpload } from '@rocket.chat/apps-engine/definition/uploads/IUpload.ts';
apps/meteor/tests/data/apps/helper.ts (1)

42-54: Consider checking response status for robustness.

The function rejects on network/transport errors but resolves with res.body.app regardless of HTTP status or res.body.success. If the server returns an error response (e.g., 400 with success: false), this would resolve with undefined rather than rejecting.

♻️ Optional: Add response validation
 export const installLocalTestPackage = (path: string) =>
 	new Promise<App>((resolve, reject) => {
 		void request
 			.post(apps())
 			.set(credentials)
 			.attach('app', path)
 			.end((err, res) => {
 				if (err) {
 					return reject(err);
 				}
+				if (!res.body.success) {
+					return reject(new Error(res.body.error || 'Failed to install app'));
+				}
 				return resolve(res.body.app);
 			});
 	});
apps/meteor/ee/server/apps/orchestrator.js (1)

75-85: Consider cleaning stale temp files on startup.

If the server crashes or fails to clean up temp files, they may persist across restarts. While each file has a unique UUID name (from crypto.randomUUID() in listeners.js), orphaned files could accumulate over time.

♻️ Optional: Clean existing files in temp directory on startup
 try {
 	// We call this only once at server startup, so using the synchronous version is fine
 	fs.mkdirSync(tempFilePath);
 } catch (err) {
 	// If the temp directory already exists, we can continue
 	if (err.code !== 'EEXIST') {
 		throw new Error('Failed to initialize the Apps-Engine', { cause: err });
 	}
+	// Clean up any stale temp files from previous runs
+	try {
+		const files = fs.readdirSync(tempFilePath);
+		for (const file of files) {
+			fs.unlinkSync(path.join(tempFilePath, file));
+		}
+	} catch (cleanupErr) {
+		// Non-fatal: log and continue
+		console.warn('Failed to clean up stale temp files:', cleanupErr.message);
+	}
 }
📜 Review details

Configuration used: Organization 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 5beb59f and 5e033ba.

⛔ Files ignored due to path filters (2)
  • apps/meteor/tests/data/apps/app-packages/file-upload-test_0.0.1.zip is excluded by !**/*.zip
  • packages/apps-engine/deno-runtime/deno.lock is excluded by !**/*.lock
📒 Files selected for processing (20)
  • .changeset/spotty-steaks-notice.md
  • apps/meteor/app/apps/server/bridges/listeners.js
  • apps/meteor/ee/server/apps/orchestrator.js
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/deno-runtime/deno.jsonc
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
  • packages/apps-engine/src/definition/uploads/IFileUploadContext.ts
  • packages/apps-engine/src/server/AppManager.ts
  • packages/apps-engine/src/server/ProxiedApp.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • packages/apps-engine/src/server/compiler/AppPackageParser.ts
  • packages/apps-engine/src/server/managers/AppListenerManager.ts
  • packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • packages/apps-engine/tests/test-data/utilities.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/spotty-steaks-notice.md
🚧 Files skipped from review as they are similar to previous changes (8)
  • packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts
  • packages/apps-engine/src/server/ProxiedApp.ts
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/src/server/managers/AppListenerManager.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
  • packages/apps-engine/src/definition/uploads/IFileUploadContext.ts
  • packages/apps-engine/deno-runtime/deno.jsonc
🧰 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:

  • packages/apps-engine/src/server/compiler/AppPackageParser.ts
  • packages/apps-engine/src/server/AppManager.ts
  • packages/apps-engine/tests/test-data/utilities.ts
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • apps/meteor/tests/data/apps/helper.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • apps/meteor/app/apps/server/bridges/listeners.js
  • apps/meteor/ee/server/apps/orchestrator.js
**/*.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:

  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
🧠 Learnings (25)
📚 Learning: 2025-10-06T20:30:45.540Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/storage/storage.ts:101-122
Timestamp: 2025-10-06T20:30:45.540Z
Learning: In `packages/apps-engine/tests/test-data/storage/storage.ts`, the stub methods (updatePartialAndReturnDocument, updateStatus, updateSetting, updateAppInfo, updateMarketplaceInfo) intentionally throw "Method not implemented." Tests using these methods must stub them using `SpyOn` from the test library rather than relying on actual implementations.

Applied to files:

  • packages/apps-engine/tests/test-data/utilities.ts
  • apps/meteor/tests/data/apps/helper.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • packages/apps-engine/tests/test-data/utilities.ts
  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • packages/apps-engine/tests/test-data/utilities.ts
  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2026-01-08T15:07:47.836Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38068
File: packages/apps-engine/deno-runtime/handlers/lib/assertions.ts:8-12
Timestamp: 2026-01-08T15:07:47.836Z
Learning: In packages/apps-engine/deno-runtime, App objects are never serialized; they are instantiated and kept in the runtime context. Therefore, runtime assertions can rely on duck-typing checks of App methods (including protected ones like extendConfiguration) as reliable. When reviewing code in this area, prefer duck-typing checks for App behavior in assertions and avoid assuming serialization/deserialization will preserve App state. This guideline applies to files under this directory.

Applied to files:

  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Store commonly used locators in variables/constants for reuse

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-12-16T17:29:45.163Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37834
File: apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts:12-22
Timestamp: 2025-12-16T17:29:45.163Z
Learning: In page object files under `apps/meteor/tests/e2e/page-objects/`, always import `expect` from `../../utils/test` (Playwright's async expect), not from Jest. Jest's `expect` has a synchronous signature and will cause TypeScript errors when used with web-first assertions like `toBeVisible()`.

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to **/*.spec.ts : Use descriptive test names that clearly communicate expected behavior in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to **/*.{ts,tsx,js} : Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Implement proper wait strategies for dynamic content in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2026-01-08T15:03:45.071Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38068
File: apps/meteor/tests/data/apps/app-packages/README.md:14-16
Timestamp: 2026-01-08T15:03:45.071Z
Learning: For the RocketChat/Rocket.Chat repository, do not analyze or report formatting issues (such as hard tabs vs spaces, line breaks, etc.). The project relies on automated linting tools to enforce formatting standards.

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-19T18:20:07.720Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
🧬 Code graph analysis (7)
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (3)
packages/apps-engine/deno-runtime/handlers/lib/assertions.ts (3)
  • isRecord (4-12)
  • assertAppAvailable (22-26)
  • assertHandlerFunction (29-33)
packages/apps-engine/src/definition/uploads/IFileUploadContext.ts (1)
  • IFileUploadContext (8-11)
packages/apps-engine/deno-runtime/lib/accessors/mod.ts (1)
  • AppAccessorsInstance (322-322)
apps/meteor/tests/data/apps/helper.ts (1)
apps/meteor/tests/data/apps/apps-data.ts (1)
  • apps (10-12)
packages/apps-engine/src/server/compiler/AppImplements.ts (1)
packages/apps/src/AppsEngine.ts (1)
  • AppInterface (13-13)
apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts (3)
apps/meteor/tests/data/apps/helper.ts (2)
  • cleanupApps (24-27)
  • installLocalTestPackage (42-54)
apps/meteor/tests/data/apps/app-packages/index.ts (1)
  • appImplementsIPreFileUpload (3-3)
packages/core-services/src/index.ts (1)
  • api (55-55)
packages/apps-engine/tests/server/compiler/AppImplements.spec.ts (1)
packages/apps/src/AppsEngine.ts (1)
  • AppInterface (13-13)
apps/meteor/app/apps/server/bridges/listeners.js (1)
packages/apps/src/AppsEngine.ts (1)
  • AppInterface (13-13)
apps/meteor/ee/server/apps/orchestrator.js (1)
packages/apps-engine/src/server/AppManager.ts (1)
  • AppManager (71-1232)
🪛 Biome (2.1.2)
apps/meteor/app/apps/server/bridges/listeners.js

[error] 1-1: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 1-2: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 2-3: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 4-5: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 5-6: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)

apps/meteor/ee/server/apps/orchestrator.js

[error] 1-1: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 1-2: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 2-3: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)

🪛 markdownlint-cli2 (0.18.1)
apps/meteor/tests/data/apps/app-packages/README.md

14-14: Hard tabs
Column: 1

(MD010, no-hard-tabs)


15-15: Hard tabs
Column: 1

(MD010, no-hard-tabs)


16-16: Hard tabs
Column: 1

(MD010, no-hard-tabs)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (13)
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (1)

40-58: Well-implemented resource management and handler invocation.

The use of the using keyword for explicit resource management ensures the temporary file is properly closed, and the handler invocation correctly passes all required accessors. The project targets Deno 1.43.5 and TypeScript 5.9.3, which fully support this feature.

apps/meteor/tests/data/apps/app-packages/README.md (1)

1-54: Clear and helpful documentation for test app packages.

The README provides useful instructions for using pre-built test app packages, including a practical code example and details about the available IPreFileUpload test app behavior. Based on learnings, formatting concerns are handled by automated linting tools.

apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts (1)

1-56: Well-structured end-to-end tests for IPreFileUpload event.

The tests properly verify both the rejection and acceptance paths of the IPreFileUpload hook. The setup/teardown correctly cleans up apps and rooms, and the assertions validate the expected API responses. Good use of conditional test execution for EE-only features.

apps/meteor/app/apps/server/bridges/listeners.js (1)

89-111: Solid implementation with proper temp file lifecycle management.

The uploadEvent method correctly:

  • Uses crypto.randomUUID() for secure, unique temp file names
  • Wraps the listener execution in try/finally to ensure cleanup
  • Logs errors appropriately (error for write failures, warn for cleanup failures)
  • Preserves the original error as cause when rethrowing

The cleanup-on-failure approach in the finally block is a good pattern for resource management.

packages/apps-engine/src/server/AppManager.ts (1)

57-62: Clean extension of AppManager to support temp file path configuration.

The implementation properly:

  • Documents the tempFilePath requirement in IAppManagerDeps
  • Stores it as a private readonly field
  • Exposes it via a well-documented getter

The validation of the temp path is appropriately delegated to the orchestrator during initialization.

Also applies to: 115-116, 119-119, 149-150, 173-180

packages/apps-engine/tests/test-data/utilities.ts (1)

133-133: Appropriate mock for the new getTempFilePath method.

The deterministic return value is suitable for test scenarios where the actual path doesn't matter.

apps/meteor/ee/server/apps/orchestrator.js (1)

75-93: Proper temp directory initialization with appropriate error handling.

The implementation correctly:

  • Uses os.tmpdir() for platform-appropriate temp location
  • Handles the EEXIST case gracefully (directory already exists)
  • Preserves error context with the cause option
  • Uses synchronous call appropriately for startup-time initialization
packages/apps-engine/tests/server/compiler/AppImplements.spec.ts (1)

14-18: LGTM!

The test correctly exercises the new API, validating both setImplements and doesImplement methods with proper AppInterface enum values.

packages/apps-engine/src/server/compiler/AppImplements.ts (4)

21-23: LGTM!

The new doesImplement method provides a clear query API, properly separated from the setImplements setter method.


25-27: LGTM!

The return type correctly reflects the stronger typing of the implemented field.


29-31: LGTM!

The return type is correctly aligned with getValues().


15-19: The in operator validation works correctly with this string enum. Since AppInterface is a string enum where each member name equals its value (e.g., IPostMessageSentToBot = 'IPostMessageSentToBot'), checking int in AppInterface effectively validates that the string is a valid enum member by checking it against the property keys. The implementation is correct.

packages/apps-engine/src/server/compiler/AppPackageParser.ts (1)

88-88: No changes needed. The type compatibility is already correct in the codebase.

The interfaceName variable is properly typed as AppInterface (not string) because info.implements is declared as Array<AppInterface> in the IAppInfo interface. When forEach iterates over this array, each element is typed as AppInterface, which perfectly matches the parameter type expected by setImplements(int: AppInterface). The runtime validation in setImplements provides additional safety. There is no type mismatch or TypeScript compilation issue.

Likely an incorrect or invalid review comment.

@d-gubert d-gubert force-pushed the feat/apps-file-stream branch from 5e033ba to 27e5596 Compare January 8, 2026 16:18
@d-gubert
Copy link
Member Author

d-gubert commented Jan 8, 2026

@coderabbitai ignore

Your job here is done 🐰

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: 2

🤖 Fix all issues with AI agents
In @packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts:
- Line 5: The import statement for IFileUploadContext in handleUploadEvents.ts
is missing a trailing semicolon; update the import line "import type {
IFileUploadContext } from
'@rocket.chat/apps-engine/definition/uploads/IFileUploadContext.ts'" to include
a semicolon at the end so it matches the file's import formatting and maintains
consistency.
- Line 59: In handleUploadEvents (in the catch block inside the try/catch around
the upload handling), change the malformed catch clause from "catch(e)" to
"catch (e)" to add a space after the catch keyword for consistent
TypeScript/JavaScript formatting and linting; update the catch in the same
function/block where the error is currently handled to match the project's
formatting conventions.
🧹 Nitpick comments (4)
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (1)

40-49: Initialize context variable to prevent potential undefined usage.

The context variable is declared but not initialized. If the switch statement were to be extended with additional cases in the future and one case fails to assign context, this would lead to a runtime error when context is passed to the handler function. While currently there's only one case, defensive initialization improves type safety.

♻️ Proposed fix

Option 1: Add an explicit default case that throws an error:

 		using tempFile = await Deno.open(path, { read: true, create: false });
-		let context: IFileUploadContext;
 
 		switch (method) {
 			case 'executePreFileUpload': {
 				const fileContents = await toArrayBuffer(tempFile.readable);
-				context = { file, content: Buffer.from(fileContents) };
+				const context: IFileUploadContext = { file, content: Buffer.from(fileContents) };
-				break;
+				return await handlerFunction.call(
+					app,
+					context,
+					AppAccessorsInstance.getReader(),
+					AppAccessorsInstance.getHttp(),
+					AppAccessorsInstance.getPersistence(),
+					AppAccessorsInstance.getModifier(),
+				);
 			}
+			default:
+				throw JsonRpcError.invalidParams({ err: 'Unknown upload event method', value: method });
 		}
-
-		return await handlerFunction.call(
-			app,
-			context,
-			AppAccessorsInstance.getReader(),
-			AppAccessorsInstance.getHttp(),
-			AppAccessorsInstance.getPersistence(),
-			AppAccessorsInstance.getModifier(),
-		);

Option 2: Move the handler invocation inside each case to eliminate the shared variable.

apps/meteor/app/apps/server/bridges/listeners.js (3)

10-13: Consider omitting implementation comments per coding guidelines.

The JSDoc type annotation provides useful type information, but the coding guidelines suggest avoiding code comments in implementation. Since this is type documentation in a .js file, it provides value, so this is optional.


84-88: Consider standard JSDoc convention.

Minor: JSDoc typically uses @returns instead of @return. Also, as mentioned earlier, the coding guidelines suggest avoiding implementation comments.


89-111: Add runtime validation for payload structure.

The temp directory is properly initialized at server startup with error handling for existing directories. However, uploadEvent destructures payload.file and payload.content without runtime validation. While the Deno runtime handlers validate these fields, the Meteor listener bridge does not. Add a guard to fail fast with a clear error if the payload is malformed:

if (!payload?.file || !payload?.content) {
  throw new Error('Invalid upload event payload: missing file or content');
}
📜 Review details

Configuration used: Organization 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 5e033ba and 27e5596.

⛔ Files ignored due to path filters (1)
  • packages/apps-engine/deno-runtime/deno.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • apps/meteor/app/apps/server/bridges/listeners.js
  • packages/apps-engine/deno-runtime/deno.jsonc
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
  • packages/apps-engine/deno-runtime/deno.jsonc
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{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:

  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • apps/meteor/app/apps/server/bridges/listeners.js
🧠 Learnings (2)
📚 Learning: 2026-01-08T15:07:47.836Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38068
File: packages/apps-engine/deno-runtime/handlers/lib/assertions.ts:8-12
Timestamp: 2026-01-08T15:07:47.836Z
Learning: In packages/apps-engine/deno-runtime, App objects are never serialized; they are instantiated and kept in the runtime context. Therefore, runtime assertions can rely on duck-typing checks of App methods (including protected ones like extendConfiguration) as reliable. When reviewing code in this area, prefer duck-typing checks for App behavior in assertions and avoid assuming serialization/deserialization will preserve App state. This guideline applies to files under this directory.

Applied to files:

  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.

Applied to files:

  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
🧬 Code graph analysis (1)
packages/apps-engine/deno-runtime/handlers/app/handler.ts (2)
packages/apps-engine/deno-runtime/handlers/lib/assertions.ts (1)
  • isOneOf (18-20)
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (2)
  • uploadEvents (14-14)
  • handleUploadEvents (28-73)
🪛 Biome (2.1.2)
apps/meteor/app/apps/server/bridges/listeners.js

[error] 1-1: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 1-2: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 2-3: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 4-5: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 5-6: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (7)
packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (2)

16-20: LGTM! Duck-typing validation aligns with codebase patterns.

The assertion function correctly uses duck-typing to validate the IUpload structure, which is the preferred approach in this runtime context.

Based on learnings, App objects are never serialized in packages/apps-engine/deno-runtime, so duck-typing checks are reliable.


40-40: LGTM! Proper resource cleanup with explicit disposal.

The use of the using keyword ensures automatic cleanup of the file handle, preventing resource leaks.

packages/apps-engine/deno-runtime/handlers/app/handler.ts (3)

18-19: LGTM! Clean integration of upload event handling.

The new imports properly integrate the upload event handler and the isOneOf utility for type-safe routing.


35-43: LGTM! Excellent refactor to centralize logging logic.

The formatResult helper eliminates code duplication and provides consistent logging for all async handler branches. This improves maintainability.


45-55: LGTM! Clear and consistent routing pattern.

The routing logic is well-structured with:

  • Type-safe method checking using isOneOf
  • Consistent use of the formatResult wrapper for logging
  • Clear separation of concerns between upload events, UIKit interactions, and listeners
apps/meteor/app/apps/server/bridges/listeners.js (2)

1-4: LGTM! Required imports for temp file handling.

The new imports (crypto, fs, path) are appropriate for the temp file approach. The Biome parse errors about "import outside module" are false positives—this file is part of a module-based project structure.


20-21: LGTM! Correct routing for IPreFileUpload event.

The switch case correctly maps the IPreFileUpload event to the new uploadEvent handler, consistent with the existing pattern.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 8, 2026

Tip

For best results, initiate chat on the files or code changes.

@d-gubert, understood! Thank you for the feedback. Feel free to mention me if you need anything else in the future. 🐰

KevLehman
KevLehman previously approved these changes Jan 9, 2026
Copy link
Member

@KevLehman KevLehman left a comment

Choose a reason for hiding this comment

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

:noice:

d-gubert added a commit that referenced this pull request Jan 10, 2026
…8068

Squashed commit of the following:

commit 27e5596
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Thu Jan 8 12:38:04 2026 -0300

    fix: apply review suggestions

commit ea7ef78
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Thu Jan 8 10:53:50 2026 -0300

    add changeset

commit 356b312
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 20:43:02 2026 -0300

    refactor(deno): result formatting in app method handler

commit bac0f59
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 20:41:53 2026 -0300

    revert: we'll introduce IPreFileUploadStream later

commit a1d1c3a
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 20:12:42 2026 -0300

    test: end-to-end tests for the IPreFileUpload event

commit 1152f31
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 19:52:55 2026 -0300

    fix: runtime event handling

commit 25a7c7b
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:40:17 2026 -0300

    chore: add deprecated tag on AppInterface

commit 3aef174
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:39:18 2026 -0300

    chore: improve error printing on receiving json rpc errors

commit c655f73
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:38:04 2026 -0300

    feat: adapt listener.js to always execute both upload events

commit 8c445e9
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:36:04 2026 -0300

    feat: handle temp file in upload events on the Deno runtime

commit 2489e64
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:22:48 2026 -0300

    feat: Controller spawns runtime process with read permission when app hooks into file upload

commit 2a688a9
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:21:18 2026 -0300

    feat: AppManager gets temp file path on construction

commit 1fff450
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:04:24 2026 -0300

    refactor: AppImplements for better hook registration check

commit adc2ea8
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 18:55:26 2026 -0300

    fix: IPreFileUploadStream docstring and export

commit c5731da
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Dec 31 20:01:22 2025 -0300

    wip: add new handler for uploads to runtime

commit 82d1544
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Dec 29 23:18:56 2025 -0300

    wip: create temp file on upload event

commit d3da123
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Dec 29 23:18:37 2025 -0300

    feat: add new upload event types
@d-gubert d-gubert mentioned this pull request Jan 10, 2026
d-gubert added a commit that referenced this pull request Jan 11, 2026
…8068

Squashed commit of the following:

commit 27e5596
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Thu Jan 8 12:38:04 2026 -0300

    fix: apply review suggestions

commit ea7ef78
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Thu Jan 8 10:53:50 2026 -0300

    add changeset

commit 356b312
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 20:43:02 2026 -0300

    refactor(deno): result formatting in app method handler

commit bac0f59
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 20:41:53 2026 -0300

    revert: we'll introduce IPreFileUploadStream later

commit a1d1c3a
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 20:12:42 2026 -0300

    test: end-to-end tests for the IPreFileUpload event

commit 1152f31
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 19:52:55 2026 -0300

    fix: runtime event handling

commit 25a7c7b
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:40:17 2026 -0300

    chore: add deprecated tag on AppInterface

commit 3aef174
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:39:18 2026 -0300

    chore: improve error printing on receiving json rpc errors

commit c655f73
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:38:04 2026 -0300

    feat: adapt listener.js to always execute both upload events

commit 8c445e9
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:36:04 2026 -0300

    feat: handle temp file in upload events on the Deno runtime

commit 2489e64
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:22:48 2026 -0300

    feat: Controller spawns runtime process with read permission when app hooks into file upload

commit 2a688a9
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:21:18 2026 -0300

    feat: AppManager gets temp file path on construction

commit 1fff450
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:04:24 2026 -0300

    refactor: AppImplements for better hook registration check

commit adc2ea8
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 18:55:26 2026 -0300

    fix: IPreFileUploadStream docstring and export

commit c5731da
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Dec 31 20:01:22 2025 -0300

    wip: add new handler for uploads to runtime

commit 82d1544
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Dec 29 23:18:56 2025 -0300

    wip: create temp file on upload event

commit d3da123
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Dec 29 23:18:37 2025 -0300

    feat: add new upload event types
ricardogarim
ricardogarim previously approved these changes Jan 12, 2026
d-gubert added a commit that referenced this pull request Jan 12, 2026
…8068

Squashed commit of the following:

commit 27e5596
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Thu Jan 8 12:38:04 2026 -0300

    fix: apply review suggestions

commit ea7ef78
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Thu Jan 8 10:53:50 2026 -0300

    add changeset

commit 356b312
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 20:43:02 2026 -0300

    refactor(deno): result formatting in app method handler

commit bac0f59
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 20:41:53 2026 -0300

    revert: we'll introduce IPreFileUploadStream later

commit a1d1c3a
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 20:12:42 2026 -0300

    test: end-to-end tests for the IPreFileUpload event

commit 1152f31
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Jan 7 19:52:55 2026 -0300

    fix: runtime event handling

commit 25a7c7b
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:40:17 2026 -0300

    chore: add deprecated tag on AppInterface

commit 3aef174
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:39:18 2026 -0300

    chore: improve error printing on receiving json rpc errors

commit c655f73
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:38:04 2026 -0300

    feat: adapt listener.js to always execute both upload events

commit 8c445e9
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:36:04 2026 -0300

    feat: handle temp file in upload events on the Deno runtime

commit 2489e64
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:22:48 2026 -0300

    feat: Controller spawns runtime process with read permission when app hooks into file upload

commit 2a688a9
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:21:18 2026 -0300

    feat: AppManager gets temp file path on construction

commit 1fff450
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 19:04:24 2026 -0300

    refactor: AppImplements for better hook registration check

commit adc2ea8
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Jan 5 18:55:26 2026 -0300

    fix: IPreFileUploadStream docstring and export

commit c5731da
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Wed Dec 31 20:01:22 2025 -0300

    wip: add new handler for uploads to runtime

commit 82d1544
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Dec 29 23:18:56 2025 -0300

    wip: create temp file on upload event

commit d3da123
Author: Douglas Gubert <douglas.gubert@gmail.com>
Date:   Mon Dec 29 23:18:37 2025 -0300

    feat: add new upload event types
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

🤖 Fix all issues with AI agents
In `@packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts`:
- Around line 59-72: The catch block in handleUploadEvents.ts accesses e.name,
e.message and e.code without narrowing the caught unknown; update the catch to
treat e as unknown and defensively narrow before property access: first check
typeof e === 'object' && e !== null, then use 'in' or property checks to detect
a string 'name' (compare with AppsEngineException.name) and a 'message' string,
and only then construct a JsonRpcError using those values; for the JsonRpcError
instanceof check, first ensure e is an object/non-null before using instanceof
JsonRpcError, and for the final internalError fallback, use a safe message (e
instanceof Error ? e.message : String(e)) and include code only if the narrowed
object has a numeric code property. Ensure references to AppsEngineException,
JsonRpcError, and JsonRpcError.internalError remain the same.
🧹 Nitpick comments (1)
packages/apps-engine/deno-runtime/handlers/lib/assertions.ts (1)

18-20: Type narrowing relies on unchecked cast.

The value as T cast allows includes() to compile but doesn't verify membership before the cast. This is functionally correct since includes() performs the actual runtime check, but be aware that if T has constraints not expressible at runtime (e.g., branded types), this could produce false positives.

📜 Review details

Configuration used: Organization 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 870f3a3 and 4a84a2a.

⛔ Files ignored due to path filters (2)
  • apps/meteor/tests/data/apps/app-packages/file-upload-test_0.0.1.zip is excluded by !**/*.zip
  • packages/apps-engine/deno-runtime/deno.lock is excluded by !**/*.lock
📒 Files selected for processing (20)
  • .changeset/spotty-steaks-notice.md
  • apps/meteor/app/apps/server/bridges/listeners.ts
  • apps/meteor/ee/server/apps/orchestrator.js
  • apps/meteor/tests/data/apps/app-packages/README.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • apps/meteor/tests/data/apps/helper.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • packages/apps-engine/deno-runtime/deno.jsonc
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
  • packages/apps-engine/src/definition/uploads/IFileUploadContext.ts
  • packages/apps-engine/src/server/AppManager.ts
  • packages/apps-engine/src/server/ProxiedApp.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • packages/apps-engine/src/server/compiler/AppPackageParser.ts
  • packages/apps-engine/src/server/managers/AppListenerManager.ts
  • packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • packages/apps-engine/tests/test-data/utilities.ts
🚧 Files skipped from review as they are similar to previous changes (12)
  • apps/meteor/tests/data/apps/helper.ts
  • packages/apps-engine/deno-runtime/handlers/app/handler.ts
  • packages/apps-engine/tests/server/compiler/AppImplements.spec.ts
  • .changeset/spotty-steaks-notice.md
  • apps/meteor/tests/data/apps/app-packages/index.ts
  • packages/apps-engine/src/server/AppManager.ts
  • packages/apps-engine/src/server/compiler/AppPackageParser.ts
  • packages/apps-engine/src/server/runtime/deno/AppsEngineDenoRuntime.ts
  • packages/apps-engine/tests/test-data/utilities.ts
  • packages/apps-engine/src/definition/uploads/IFileUploadContext.ts
  • packages/apps-engine/deno-runtime/deno.jsonc
  • packages/apps-engine/src/server/ProxiedApp.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{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:

  • packages/apps-engine/src/server/managers/AppListenerManager.ts
  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/app/apps/server/bridges/listeners.ts
  • apps/meteor/ee/server/apps/orchestrator.js
🧠 Learnings (27)
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.

Applied to files:

  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2026-01-08T15:03:59.621Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38068
File: apps/meteor/tests/data/apps/app-packages/README.md:14-16
Timestamp: 2026-01-08T15:03:59.621Z
Learning: For the RocketChat/Rocket.Chat repository, do not analyze or report formatting issues (such as hard tabs vs spaces, line breaks, etc.). The project relies on automated linting tools to enforce formatting standards.

Applied to files:

  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2026-01-08T15:07:47.836Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 38068
File: packages/apps-engine/deno-runtime/handlers/lib/assertions.ts:8-12
Timestamp: 2026-01-08T15:07:47.836Z
Learning: In packages/apps-engine/deno-runtime, App objects are never serialized; they are instantiated and kept in the runtime context. Therefore, runtime assertions can rely on duck-typing checks of App methods (including protected ones like extendConfiguration) as reliable. When reviewing code in this area, prefer duck-typing checks for App behavior in assertions and avoid assuming serialization/deserialization will preserve App state. This guideline applies to files under this directory.

Applied to files:

  • packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts
  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
📚 Learning: 2025-10-06T20:30:45.540Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/storage/storage.ts:101-122
Timestamp: 2025-10-06T20:30:45.540Z
Learning: In `packages/apps-engine/tests/test-data/storage/storage.ts`, the stub methods (updatePartialAndReturnDocument, updateStatus, updateSetting, updateAppInfo, updateMarketplaceInfo) intentionally throw "Method not implemented." Tests using these methods must stub them using `SpyOn` from the test library rather than relying on actual implementations.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-10T19:06:20.146Z
Learnt from: MartinSchoeler
Repo: RocketChat/Rocket.Chat PR: 37408
File: apps/meteor/client/views/admin/ABAC/useRoomAttributeOptions.tsx:53-69
Timestamp: 2025-11-10T19:06:20.146Z
Learning: In the Rocket.Chat repository, do not provide suggestions or recommendations about code sections marked with TODO comments. The maintainers have already identified these as future work and external reviewers lack the full context about implementation plans and timing.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/ee/server/apps/orchestrator.js
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-10-16T21:09:51.816Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36942
File: apps/meteor/client/lib/e2ee/keychain.ts:148-156
Timestamp: 2025-10-16T21:09:51.816Z
Learning: In the RocketChat/Rocket.Chat repository, only platforms with native crypto.randomUUID() support are targeted, so fallback implementations for crypto.randomUUID() are not required in E2EE or cryptographic code.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/app/apps/server/bridges/listeners.ts
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-09-19T15:15:04.642Z
Learnt from: rodrigok
Repo: RocketChat/Rocket.Chat PR: 36991
File: apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts:219-221
Timestamp: 2025-09-19T15:15:04.642Z
Learning: The Federation_Matrix_homeserver_domain setting in apps/meteor/server/services/federation/infrastructure/rocket-chat/adapters/Settings.ts is part of the old federation system and is being deprecated/removed, so configuration issues with this setting should not be flagged for improvement.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • packages/apps-engine/src/server/compiler/AppImplements.ts
  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: UserBridge.doGetUserRoomIds in packages/apps-engine/src/server/bridges/UserBridge.ts has a bug where it implicitly returns undefined when the app lacks read permission (missing return statement in the else case of the permission check).

Applied to files:

  • packages/apps-engine/deno-runtime/handlers/lib/assertions.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.beforeAll()` and `test.afterAll()` for setup/teardown in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-12-16T17:29:45.163Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37834
File: apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts:12-22
Timestamp: 2025-12-16T17:29:45.163Z
Learning: In page object files under `apps/meteor/tests/e2e/page-objects/`, always import `expect` from `../../utils/test` (Playwright's async expect), not from Jest. Jest's `expect` has a synchronous signature and will cause TypeScript errors when used with web-first assertions like `toBeVisible()`.

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to **/*.spec.ts : Use descriptive test names that clearly communicate expected behavior in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to **/*.{ts,tsx,js} : Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Implement proper wait strategies for dynamic content in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests

Applied to files:

  • apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts
  • apps/meteor/tests/data/apps/app-packages/README.md
📚 Learning: 2025-11-19T18:20:07.720Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.

Applied to files:

  • apps/meteor/tests/data/apps/app-packages/README.md
🧬 Code graph analysis (4)
packages/apps-engine/src/server/managers/AppListenerManager.ts (1)
packages/apps-engine/src/definition/uploads/IFileUploadContext.ts (1)
  • IFileUploadInternalContext (3-6)
packages/apps-engine/src/server/compiler/AppImplements.ts (1)
packages/apps/src/AppsEngine.ts (1)
  • AppInterface (13-13)
apps/meteor/app/apps/server/bridges/listeners.ts (2)
packages/apps/src/AppsEngine.ts (1)
  • AppInterface (13-13)
packages/apps-engine/src/definition/uploads/IPreFileUpload.ts (1)
  • IPreFileUpload (18-26)
apps/meteor/ee/server/apps/orchestrator.js (1)
packages/apps-engine/src/server/AppManager.ts (1)
  • AppManager (71-1232)
🪛 Biome (2.1.2)
apps/meteor/ee/server/apps/orchestrator.js

[error] 1-1: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 1-2: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)


[error] 2-3: Illegal use of an import declaration outside of a module

not allowed inside scripts

(parse)

🪛 markdownlint-cli2 (0.18.1)
apps/meteor/tests/data/apps/app-packages/README.md

14-14: Hard tabs
Column: 1

(MD010, no-hard-tabs)


15-15: Hard tabs
Column: 1

(MD010, no-hard-tabs)


16-16: Hard tabs
Column: 1

(MD010, no-hard-tabs)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (20)
packages/apps-engine/src/server/compiler/AppImplements.ts (3)

5-5: Improved type safety with Record<AppInterface, boolean>.

The change from loose string-keyed object to Record<AppInterface, boolean> provides better compile-time guarantees and editor autocompletion. The initialization pattern correctly populates all enum keys with false.

Also applies to: 8-12


15-23: Clear API separation between setter and query methods.

Splitting the original doesImplement into setImplements (mutation) and doesImplement (query) follows the command-query separation principle. The defensive guard on line 16 appropriately validates the input before mutation.


25-31: LGTM on return type updates and immutability pattern.

The updated return types align with the new field typing, and delegating toJSON() to getValues() maintains DRY principles while preserving the deep-freeze immutability guarantee.

apps/meteor/ee/server/apps/orchestrator.js (3)

1-4: LGTM!

The imports for fs, os, and path are appropriate for the temp directory creation logic. The static analysis warnings about "import declaration outside of a module" are false positives—this file consistently uses ES module syntax throughout.


75-85: LGTM!

The temp directory initialization is well-implemented:

  • Cross-platform path construction with path.join and os.tmpdir()
  • Synchronous operation is appropriate at startup (as the comment explains)
  • EEXIST handling correctly allows idempotent initialization
  • Error wrapping with cause preserves the original error for debugging

87-93: LGTM!

The tempFilePath is correctly passed to AppManager via its dependency configuration, enabling the runtime to access the temp storage path for IPreFileUpload events.

packages/apps-engine/src/server/managers/AppListenerManager.ts (1)

28-28: Type migration to IFileUploadInternalContext looks correct.

The import and type references are consistently updated throughout the file to use IFileUploadInternalContext (which carries file metadata and path to the temp file) instead of the previous IFileUploadContext that embedded the file buffer. This aligns with the PR objective to reduce memory pressure by passing file paths rather than serialized buffer contents.

Also applies to: 207-210, 451-451, 1173-1179

apps/meteor/app/apps/server/bridges/listeners.ts (4)

1-3: Imports for temp file handling added appropriately.

The crypto, fs, and path imports support secure temp file generation and cleanup. Using crypto.randomUUID() for temp filenames prevents predictable naming attacks.

Also applies to: 14-14


172-183: Type definitions for file upload events are well-structured.

The HandleFileUploadEvent type clearly defines the payload as [IUpload, Buffer], and the HandleEvent union is properly extended to include the new event type.


252-284: Temp file handling implementation is solid.

The uploadEvent method properly addresses the memory optimization goal:

  1. Secure temp file naming via crypto.randomUUID() prevents path traversal and collision issues
  2. Proper error propagation - write failures are logged with context and re-thrown with cause chaining
  3. Guaranteed cleanup via finally block ensures the temp file is deleted regardless of success or failure in the listener execution
  4. Graceful cleanup failure handling - unlink errors are logged as warnings rather than thrown, which is appropriate since the primary operation has already completed

191-192: Event routing correctly delegates to the specialized handler.

apps/meteor/tests/data/apps/app-packages/README.md (1)

1-54: Documentation for test app packages is clear and helpful.

The README provides useful guidance for test authors:

  • Clear usage example with installLocalTestPackage
  • Documents the available test app (IPreFileUpload handler)
  • Includes the app source code for reference
apps/meteor/tests/end-to-end/apps/apps-hooks-file-upload.ts (2)

12-24: Test setup and teardown are well-structured.

The test properly:

  • Gates execution behind IS_EE
  • Cleans up apps before installing the test package (avoiding state pollution)
  • Creates a unique room with timestamp suffix for isolation
  • Cleans up both room and apps in after()

26-54: Test cases provide good coverage of the file upload hook behavior.

The tests validate:

  1. Rejection path: Files matching the app's rejection pattern are blocked with the expected error response, and the error message contains the file contents (proving the app successfully read the temp file)
  2. Happy path: Non-matching files are allowed through without interference

This effectively validates that the temp file mechanism works correctly for the IPreFileUpload event.

packages/apps-engine/deno-runtime/handlers/lib/assertions.ts (2)

4-12: LGTM! Robust plain-object detection.

The prototype-based check correctly identifies plain objects while excluding arrays, null, and class instances. This is a solid implementation.


22-33: Assertion functions are well-structured.

Both assertAppAvailable and assertHandlerFunction follow the correct assertion pattern with appropriate error types. Based on learnings, the duck-typing check on extendConfiguration is reliable since App objects are never serialized in this runtime context.

packages/apps-engine/deno-runtime/handlers/app/handleUploadEvents.ts (4)

14-14: LGTM! Const assertion for type safety.

The as const assertion correctly narrows the array to a readonly tuple, enabling precise typing for the method parameter.


16-26: Assertion helpers are appropriate for the validation needs.

Both assertIsUpload and assertString provide clear error messages with the actual value for debugging. The IUpload validation checks the nested user and room objects as expected.


40-48: Good use of explicit resource management with using.

The using keyword ensures the file handle is properly closed even if an exception occurs during reading. Reading the file contents via toArrayBuffer aligns with the PR objective of avoiding stdio transfer for large files.


51-58: Handler invocation and accessor provisioning look correct.

The handler is called with the appropriate context and all required accessors (Reader, Http, Persistence, Modifier) matching the expected signature for executePreFileUpload.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@d-gubert d-gubert force-pushed the feat/apps-file-stream branch from 4a84a2a to 0f7416c Compare January 14, 2026 20:59
@ggazzo ggazzo added the stat: QA assured Means it has been tested and approved by a company insider label Jan 15, 2026
@dionisio-bot dionisio-bot bot added the stat: ready to merge PR tested and approved waiting for merge label Jan 15, 2026
@ggazzo ggazzo merged commit c547985 into develop Jan 15, 2026
46 checks passed
@ggazzo ggazzo deleted the feat/apps-file-stream branch January 15, 2026 02:03
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants