Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const CategoryDropDownList = ({ categories, onSelected }: CategoryDropDownListPr
</Box>
)}
{category.items.map((item) => (
<Option key={item.id} {...({ label: item.label } as any)} onClick={(): void => onSelected(item)}>
<Option key={item.id} label={item.label} onClick={(): void => onSelected(item)}>
<CheckBox checked={item.checked} onChange={(): void => onSelected(item)} />
</Option>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const useInstallApp = (file: File): { install: () => void; isInstalling:
return uploadUpdateEndpoint(fileData);
}

return uploadAppEndpoint(fileData) as any;
return uploadAppEndpoint(fileData) as unknown as Promise<{ app: App }>;
},

onSuccess: (data: { app: App }) => {
Comment on lines +43 to 46

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate target file and upload helper:"
fd -a 'useInstallApp\.tsx|useUpload|uploadAppEndpoint|apps/update|apps' . | sed 's#^\./##' | head -200

echo
echo "Target file excerpt:"
sed -n '1,140p' apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx 2>/dev/null || true

echo
echo "Search uploadAppEndpoint definitions/imports:"
rg -n "uploadAppEndpoint|useUpload|\\bapps/.+upload|useMutation\\(.*upload|Upload\\(" apps -g '*.{ts,tsx,js}' --glob '!**/node_modules/**' --glob '!**/.git/**' | head -300

Repository: RocketChat/Rocket.Chat

Length of output: 13792


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "useUpload hook:"
sed -n '1,220p' packages/ui-contexts/src/hooks/useUpload.ts

echo
echo "upload-related market-place/test references:"
rg -n "POST /apps|/apps\\b|/apps/update|AppUpload|uploadApp|app:|upload" apps/meteor/app/apps apps/meteor/public apps/meteor/server/api apps/meteor/tests apps/meteor/client/views/marketplace packages rest-typings --glob '*.{ts,tsx,js,json}' | head -300

echo
echo "apps REST API files:"
fd -a 'apps.*\.(ts|tsx|js)$|.*apps.*\.(ts|tsx|js)$' apps/meteor/server/api apps/meteor/app/apps --ignore-case | head -200

Repository: RocketChat/Rocket.Chat

Length of output: 38964


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "useEndpointUploadMutation type context:"
sed -n '1,120p' apps/meteor/client/hooks/useEndpointUploadMutation.ts

echo
echo "API endpoint candidates that handle multipart app uploads:"
rg -n "POST|POST_API|api\\.v1\\.post|addRoute\\(['\"]apps|/apps|uploadApp|uploadUpdate|apps/update|AppClientUpload|uploadToEndpoint" apps/meteor/server/api apps/meteor/app apps/meteor/ee/server apps/meteor/client packages/ui-contexts src --glob '*.{ts,tsx,js}' | head -400

echo
echo "package ui-contexts contexts/type files:"
fd -a 'ServerContext\.ts|upload.*\.ts|api.*\.ts|Endpoint.*\.ts' packages/ui-contexts src --ignore-case | head -100

Repository: RocketChat/Rocket.Chat

Length of output: 50378


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "ServerProvider upload/result helper context:"
sed -n '1,110p' apps/meteor/client/providers/ServerProvider.tsx

echo
echo "Focused search for APP upload endpoints:"
rg -n "POST_API|api\.v1\.post|addRoute\\(['\"]apps|apiServer|Router|install|private|upload|\\.update\\(|apps/update|/apps\\b" apps/meteor/server/api apps/meteor/app/apps --glob '*.{ts,tsx,js}' | head -250

echo
echo "REST typings app routes relevant to install/update:"
fd -a 'apps.*\.(ts|tsx|json)$|.*apps.*\.(ts|tsx|json)$' packages/rest-typings -i | while read -r f; do echo "--- $f"; rg -n "/apps|apps/update|private|install|upload" "$f" || true; done

Repository: RocketChat/Rocket.Chat

Length of output: 34549


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "REST typings package files:"
git ls-files packages/rest-typings | sed -n '1,200p'

echo
echo "Search for App upload schemas/endpoints in repos:"
rg -n "EndpointResult|OperationResult|POST::|apps/update|apps'\\b|/apps|upload.*App|App.*upload|app:.*upload|apps.private|apps.private|apps.private-create|private-app|private" packages/rest-typings src --glob '*.{ts,tsx,js,json}' | head -300 || true

echo
echo "Client tests/mocks around app upload response shape:"
rg -n "POST /api/apps|/api/apps|\\bapp:|response\\.|body\\.|success|\\.app|installLocalTestPackage|private-apps-upload" apps/meteor/tests apps/meteor/client/providers apps/meteor/tests/mocks packages/ui-contexts --glob '*.{ts,tsx,js}' | head -300

Repository: RocketChat/Rocket.Chat

Length of output: 49201


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "REST typings apps relevant sections:"
sed -n '230,285p' packages/rest-typings/src/apps/index.ts
echo "--- OperationResult excerpt"
sed -n '190,220p' packages/rest-typings/src/index.ts

echo
echo "useEndpointUploadMutation implementation:"
sed -n '1,90p' apps/meteor/client/hooks/useEndpointUploadMutation.ts

echo
echo "Focused endpoint references for app package upload/update:"
rg -n "POST_API|api\.v1\.post|addRoute\\(['\"]apps|apiServer\\.post|apps/private|private-app|updateApp|installApp|AppClientOrchestrator|AppManager|update\\(|install\\(" apps/meteor/server/api apps/meteor/ee/server/apps apps/meteor/app/apps apps/meteor/client --glob '*.{ts,tsx,js}' | head -400

Repository: RocketChat/Rocket.Chat

Length of output: 18157


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "REST typings apps route list around /apps/update:"
rg -n "/apps(update|private|update-app|updateApp|updateApp.*)|update" packages/rest-typings/src/apps/index.ts packages/rest-typings/src/help* packages/rest-typings/src -g '*.ts' | head -250

echo
echo "Server endpoint files that contain updateApp handler:"
rg -n "updateApp\\(|update\\(.*app|APP|app.*update|API\\.v1\\.post|Router|apps/update|update-app" apps/meteor/ee/server/apps apps/meteor/server/api apps/meteor/app/apps apps/meteor/client --glob '*.{ts,tsx,js,jsx}' | head -400

echo
echo "REST typings index imports listing app route file names:"
rg -n "from '.*/apps|from '../apps|from './apps" packages/rest-typings/src/index.ts packages/rest-typings/src/rest* packages/rest-typings/src/v1 packages/rest-typings/src/app packages/rest-typings/src -g '*.ts' | head -200

Repository: RocketChat/Rocket.Chat

Length of output: 47065


Remove the type-unsafe endpoint casts.

useUpload always returns UploadResult, so useMutation should reject on !result.success and type the app-install/update endpoint result separately instead of widening through as unknown. Also add the update endpoint result type to @rocket.chat/rest-typings so /apps/update can share the same typed response contract as /apps.

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

In `@apps/meteor/client/views/marketplace/hooks/useInstallApp.tsx` around lines 43
- 46, Update the useUpload mutation callback in useInstallApp to handle
UploadResult by rejecting when result.success is false and returning the typed
success payload, removing the unknown/type-unsafe casts. Define a separate
app-install/update endpoint result type in `@rocket.chat/rest-typings` and apply
it to the /apps and /apps/update contracts so useMutation receives the correct
typed response.

Source: Coding guidelines

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ export const useComposerBoxPopupQueries = <T extends { _id: string; sort?: numbe

const shouldPopupPreview = useEnablePopupPreview(filter, popup);

const hasCmd = (filter: unknown): filter is { cmd: string } =>
typeof filter === 'object' && filter !== null && 'cmd' in filter && typeof (filter as Record<string, unknown>).cmd === 'string';

const enableQuery =
!popup ||
(popup.preview &&
Boolean(slashCommands.commands[(filter as any)?.cmd]) &&
slashCommands.commands[(filter as any)?.cmd].providesPreview) ||
hasCmd(filter) &&
Boolean(slashCommands.commands[filter.cmd]) &&
slashCommands.commands[filter.cmd].providesPreview) ||
shouldPopupPreview;

const queries = useQueries({
Expand Down