Skip to content

fix: core api#105

Merged
hmbanan666 merged 2 commits into
mainfrom
fix
Aug 28, 2025
Merged

fix: core api#105
hmbanan666 merged 2 commits into
mainfrom
fix

Conversation

@hmbanan666
Copy link
Copy Markdown
Collaborator

@hmbanan666 hmbanan666 commented Aug 28, 2025

Summary by CodeRabbit

  • New Features
    • Added an in-app endpoint for submitting epic comment beacons.
  • Style
    • Adjusted toast spacing for improved on-screen positioning.
  • Refactor
    • Beacon submissions now route through the app API; submission feedback switched from toasts to device vibration.
    • Avatar upload now uses the configurable Core API endpoint.
  • Chores
    • Added a public Core API URL configuration and example env entry.
  • Bug Fixes
    • Expanded accepted image formats to include AVIF and HEIF.

@hmbanan666 hmbanan666 self-assigned this Aug 28, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 28, 2025

Walkthrough

Adds a public runtime config key for the core API URL and an env example, introduces a server POST proxy endpoint for comment beaconing, updates components to use the runtime config or local proxy (removing some toast usage), and expands accepted image MIME/formats to include AVIF and HEIF.

Changes

Cohort / File(s) Summary
Environment & Runtime Config
apps/atrium-telegram/.env.example, apps/atrium-telegram/nuxt.config.ts
Adds NUXT_PUBLIC_CORE_API_URL example and runtimeConfig.public.coreApiUrl (default '') to surface the core API base URL.
Server Beacon Proxy
apps/atrium-telegram/server/api/epic/comment/id/[commentId]/beacon.post.ts
New POST handler: validates body (createBeaconSchema), requires commentId, forwards payload to ${publicEnv.coreApiUrl}/epic/comment/id/{commentId}/beacon, returns { ok: true }, errors via errorResolver.
Client Beacon Submission
apps/atrium-telegram/app/components/form/CreateEpicCommentBeacon.vue
Switches from direct external URL to local Nuxt endpoint /api/epic/comment/id/${commentId}/beacon; removes i18n t and useActionToast feedback; keeps vibration and emitted events.
Avatar Upload (client → core API)
apps/atrium-telegram/app/components/form/UploadUserAvatar.vue
Replaces local relative upload endpoint with ${publicEnv.coreApiUrl}/user/id/${userStore.id}/image via useRuntimeConfig(); removed Authorization header; keeps FormData POST and existing flow.
Accepted Image Types (shared)
apps/atrium-telegram/shared/services/media.ts, apps/web-app/shared/services/media.ts
Adds 'image/avif' and 'image/heif' to ACCEPTED_IMAGE_TYPES, enabling AVIF/HEIF file acceptance.
Server Image Validation Formats
apps/web-app/server/api/user/id/[userId]/image.post.ts
Adds 'heif' and 'avif' to ACCEPTED_IMAGE_FORMATS so metadata.format accepts these; output formats unchanged (jpg, webp).
App UI Tweak
apps/atrium-telegram/app/app.vue
Adjusts toaster margin class from mt-16 to mt-20.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as CreateEpicCommentBeacon.vue
  participant N as Nuxt Server (/api/.../beacon)
  participant CORE as Core API

  C->>N: POST /api/epic/comment/id/{commentId}/beacon\npayload
  N->>N: Validate body (createBeaconSchema)\nExtract commentId
  alt valid & commentId present
    N->>CORE: POST {publicEnv.coreApiUrl}/epic/comment/id/{commentId}/beacon\nvalidated payload
    CORE-->>N: 200 OK
    N-->>C: { ok: true }
    note right of C: emit success, vibrate
  else validation / missing id
    N-->>C: 400 / validation error (via errorResolver)
    note right of C: emit error, vibrate
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • chore: feedback rework #99 — Related changes to feedback/haptic handling and form components (matches toast→vibrate and event-change patterns).

Poem

A rabbit taps the proxy gate,
Config carrots line the plate.
AVIF hops in with HEIF beside,
No-toast vibrations now provide.
Beacon sent, the burrow's bright — requests take flight. 🥕🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@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

🧹 Nitpick comments (2)
apps/atrium-telegram/app/app.vue (1)

7-7: Consider safe-area-aware top offset for toaster

On some devices/Telegram WebView, fixed top toasts can overlap the OS/Telegram bars. Prefer a safe-area-aware offset (or compute offset in CSS) instead of a hard mt-20.

Would you like me to propose a tiny CSS utility that uses env(safe-area-inset-top)?

apps/atrium-telegram/.env.example (1)

4-6: Document expected format and sample value

Add a concrete example and note “no trailing slash” to avoid // joins.

-# Main API
-NUXT_CORE_API_URL=
+# Main API (no trailing slash), e.g. https://core.example.com
+NUXT_CORE_API_URL=https://core.example.com
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear 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 281575b and 7af6ab9.

📒 Files selected for processing (5)
  • apps/atrium-telegram/.env.example (1 hunks)
  • apps/atrium-telegram/app/app.vue (1 hunks)
  • apps/atrium-telegram/app/components/form/CreateEpicCommentBeacon.vue (1 hunks)
  • apps/atrium-telegram/nuxt.config.ts (1 hunks)
  • apps/atrium-telegram/server/api/epic/comment/id/[commentId]/beacon.post.ts (1 hunks)
⏰ 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: build
🔇 Additional comments (3)
apps/atrium-telegram/nuxt.config.ts (1)

27-27: Runtime config: verify env mapping and keep it private

Good to keep coreApiUrl private. Please verify NUXT_CORE_API_URL actually maps to runtimeConfig.coreApiUrl in your setup; Nuxt’s env-to-config mapping can be subtle. If there’s any doubt, add a dev-time assertion (or log) and fail fast when empty.

Apply guard in the proxy route (see related comment) to prevent silent 404/loops when coreApiUrl is unset.

apps/atrium-telegram/app/components/form/CreateEpicCommentBeacon.vue (1)

98-101: Switch to internal endpoint looks good

Routing via the Nuxt server endpoint is the right move; cookies will flow and CORS is avoided.

apps/atrium-telegram/server/api/epic/comment/id/[commentId]/beacon.post.ts (1)

14-18: Validation check with arktype is likely incorrect; assert or check issues instead

instanceof type.errors is not a reliable pattern here and can silently pass invalid data. Prefer asserting or inspecting issues.

Proposed (Option A – assert and drop the extra import):

-import { type } from 'arktype'
@@
-    const body = await readBody(event)
-    const data = createBeaconSchema(body)
-    if (data instanceof type.errors) {
-      throw data
-    }
+    const body = await readBody(event)
+    // Throws on invalid and returns typed data on success
+    const data = createBeaconSchema.assert(body)

Alternative (Option B – safe-check):

-    const body = await readBody(event)
-    const data = createBeaconSchema(body)
-    if (data instanceof type.errors) {
-      throw data
-    }
+    const body = await readBody(event)
+    const parsed = createBeaconSchema(body)
+    if (parsed?.issues) {
+      throw createError({ statusCode: 400, message: parsed?.summary ?? 'Invalid payload' })
+    }
+    const data = parsed

Likely an incorrect or invalid review comment.

Comment on lines +14 to +25
const body = await readBody(event)
const data = createBeaconSchema(body)
if (data instanceof type.errors) {
throw data
}

const { coreApiUrl } = useRuntimeConfig()

await $fetch(`${coreApiUrl}/epic/comment/id/${commentId}/beacon`, {
method: 'POST',
body: data,
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Don’t trust client-provided senderId; derive server-side

CreateBeacon includes senderId. The client sets it from userStore.id, which a malicious client can spoof. Server should derive senderId from the authenticated session and either overwrite or drop the field before forwarding.

-    const data = createBeaconSchema.assert(body)
+    const data = createBeaconSchema.assert(body)
+    // Example: enforce from auth (adjust getter to your auth layer)
+    const currentUserId = event.context?.auth?.user?.id
+    if (currentUserId) {
+      // Overwrite or ensure parity
+      // @ts-expect-error - narrow type if needed
+      data.senderId = currentUserId
+    } else {
+      // Optionally fail if unauthenticated
+      throw createError({ statusCode: 401, message: 'Unauthorized' })
+    }

If core API already ignores/overwrites senderId, confirm and we can simply delete (data as any).senderId before forwarding.


🏁 Script executed:

#!/bin/bash
set -e
# Search for createBeaconSchema definition and usages
rg -n "createBeaconSchema" --glob "*.ts" -C3

Length of output: 3588


Enforce server-side senderId
Derive senderId from the authenticated session and never trust client input. For example:

     const body = await readBody(event)
-    const data = createBeaconSchema(body)
+    const data = createBeaconSchema(body)
     if (data instanceof type.errors) throw data

+    const currentUserId = event.context.auth?.user?.id
+    if (!currentUserId) throw createError({ statusCode: 401, message: 'Unauthorized' })
+    const payload = { senderId: currentUserId, usersId: data.usersId }

     const { coreApiUrl } = useRuntimeConfig()
-    await $fetch(`${coreApiUrl}/epic/comment/id/${commentId}/beacon`, {
-      method: 'POST',
-      body: data,
-    })
+    await $fetch(`${coreApiUrl}/epic/comment/id/${commentId}/beacon`, {
+      method: 'POST',
+      body: payload,
+    })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const body = await readBody(event)
const data = createBeaconSchema(body)
if (data instanceof type.errors) {
throw data
}
const { coreApiUrl } = useRuntimeConfig()
await $fetch(`${coreApiUrl}/epic/comment/id/${commentId}/beacon`, {
method: 'POST',
body: data,
})
const body = await readBody(event)
const data = createBeaconSchema(body)
if (data instanceof type.errors) {
throw data
}
// Derive senderId from authenticated session
const currentUserId = event.context.auth?.user?.id
if (!currentUserId) throw createError({ statusCode: 401, message: 'Unauthorized' })
const payload = { senderId: currentUserId, usersId: data.usersId }
const { coreApiUrl } = useRuntimeConfig()
await $fetch(`${coreApiUrl}/epic/comment/id/${commentId}/beacon`, {
method: 'POST',
body: payload,
})
🤖 Prompt for AI Agents
In apps/atrium-telegram/server/api/epic/comment/id/[commentId]/beacon.post.ts
around lines 14–25, the code currently uses client-supplied senderId; instead
derive senderId from the authenticated session, reject requests with no
authenticated user, and never trust or pass through a client-sent senderId.
Retrieve the authenticated user id from the server session/context,
merge/overwrite data.senderId = sessionUserId (or return 401 if missing) before
any schema creation/validation or before sending to core, and ensure the schema
used for createBeaconSchema does not accept or persist a client-provided
senderId (or validate after you overwrite it) so the forwarded POST to core
contains the server-derived senderId only.

Comment on lines +20 to +25
const { coreApiUrl } = useRuntimeConfig()

await $fetch(`${coreApiUrl}/epic/comment/id/${commentId}/beacon`, {
method: 'POST',
body: data,
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Harden proxy: guard missing base URL, normalize URL, forward auth, set timeout

  • Fail fast if coreApiUrl is empty.
  • Normalize join to avoid //.
  • Forward authorization/cookie so the core API can authenticate.
  • Add a reasonable timeout and avoid retries.
-    const { coreApiUrl } = useRuntimeConfig()
-
-    await $fetch(`${coreApiUrl}/epic/comment/id/${commentId}/beacon`, {
-      method: 'POST',
-      body: data,
-    })
+    const { coreApiUrl } = useRuntimeConfig()
+    if (!coreApiUrl) {
+      throw createError({ statusCode: 500, message: 'coreApiUrl is not configured' })
+    }
+
+    const auth = getHeader(event, 'authorization')
+    const cookie = getHeader(event, 'cookie')
+
+    await $fetch(`${coreApiUrl.replace(/\/+$/, '')}/epic/comment/id/${commentId}/beacon`, {
+      method: 'POST',
+      body: data,
+      headers: {
+        ...(auth ? { authorization: auth } : {}),
+        ...(cookie ? { cookie } : {}),
+      },
+      timeout: 10_000,
+      retry: 0,
+    })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { coreApiUrl } = useRuntimeConfig()
await $fetch(`${coreApiUrl}/epic/comment/id/${commentId}/beacon`, {
method: 'POST',
body: data,
})
const { coreApiUrl } = useRuntimeConfig()
if (!coreApiUrl) {
throw createError({ statusCode: 500, message: 'coreApiUrl is not configured' })
}
const auth = getHeader(event, 'authorization')
const cookie = getHeader(event, 'cookie')
await $fetch(`${coreApiUrl.replace(/\/+$/, '')}/epic/comment/id/${commentId}/beacon`, {
method: 'POST',
body: data,
headers: {
...(auth ? { authorization: auth } : {}),
...(cookie ? { cookie } : {}),
},
timeout: 10_000,
retry: 0,
})

Comment on lines +30 to +32
} catch (error) {
throw errorResolver(error)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Ensure errorResolver is available/imported

errorResolver isn’t a Nitro/H3 builtin. If not globally auto-imported, this will throw at runtime. Please verify and add an explicit import if needed.

Run to locate its definition:

If it lives under a util path, import it explicitly at the top of this file.


🏁 Script executed:

#!/bin/bash
rg -nP -C2 '\b(errorResolver)\b' --type=ts --type=js

Length of output: 44144


🏁 Script executed:

#!/bin/bash
head -n 20 apps/atrium-telegram/server/api/epic/comment/id/[commentId]/beacon.post.ts

Length of output: 620


Import errorResolver at the top of beacon.post.ts
This handler calls errorResolver (from apps/atrium-telegram/server/utils/error.ts) but never imports it. Add, for example, immediately after the existing imports:

import { errorResolver } from '../../../../../utils/error'

—adjust the relative path or alias to match your project’s resolver.

🤖 Prompt for AI Agents
In apps/atrium-telegram/server/api/epic/comment/id/[commentId]/beacon.post.ts
around lines 30 to 32 the file uses errorResolver but never imports it; add an
import for errorResolver from the utils/error module at the top of the file (for
example: import { errorResolver } from '../../../../../utils/error') or adjust
the path/alias to match the project, then ensure the import is included with the
other imports so the catch block can call errorResolver without a
ReferenceError.

@sonarqubecloud
Copy link
Copy Markdown

@hmbanan666 hmbanan666 merged commit d86ea05 into main Aug 28, 2025
7 of 8 checks passed
@hmbanan666 hmbanan666 deleted the fix branch August 28, 2025 12:55
Copy link
Copy Markdown

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

Caution

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

⚠️ Outside diff range comments (1)
apps/web-app/server/api/user/id/[userId]/image.post.ts (1)

96-104: Use sharp.clone() per rendition; fix typing; remove manual nulling.

Reusing the same Sharp instance across iterations risks transform carryover and unnecessary mutation. Also don’t type the buffer as unknown.

Apply:

-        let buffer: unknown = await sharpStream
-          .resize({ width: size, height: size })
-          .toFormat(format, { quality: 90 })
-          .toBuffer()
+        const buffer: Buffer = await sharpStream
+          .clone()
+          .rotate() // honor EXIF orientation
+          .resize({ width: size, height: size })
+          .toFormat(format, { quality: 90 })
+          .toBuffer()
@@
-        // Clear
-        buffer = null

Also applies to: 113-115

🧹 Nitpick comments (2)
apps/web-app/shared/services/media.ts (1)

4-12: Deduplicate accepted image type lists across apps.

This list is duplicated in multiple apps; drift is likely. Extract to a shared module (e.g., packages/shared-media) and import in both places.

apps/atrium-telegram/app/components/form/UploadUserAvatar.vue (1)

69-71: Guard against double slashes in coreApiUrl.

If coreApiUrl ends with '/', the URL may contain '//'. Harmless for most CDNs, but can break signed URLs. Consider joinURL from ufo or trimEnd('/').

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear 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 7af6ab9 and d0c91fc.

📒 Files selected for processing (7)
  • apps/atrium-telegram/.env.example (1 hunks)
  • apps/atrium-telegram/app/components/form/UploadUserAvatar.vue (1 hunks)
  • apps/atrium-telegram/nuxt.config.ts (1 hunks)
  • apps/atrium-telegram/server/api/epic/comment/id/[commentId]/beacon.post.ts (1 hunks)
  • apps/atrium-telegram/shared/services/media.ts (1 hunks)
  • apps/web-app/server/api/user/id/[userId]/image.post.ts (1 hunks)
  • apps/web-app/shared/services/media.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/atrium-telegram/nuxt.config.ts
  • apps/atrium-telegram/.env.example
  • apps/atrium-telegram/server/api/epic/comment/id/[commentId]/beacon.post.ts
⏰ 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: build

Comment on lines +67 to 72
const { public: publicEnv } = useRuntimeConfig()

await $fetch(`${publicEnv.coreApiUrl}/user/id/${userStore.id}/image`, {
method: 'POST',
headers: {
Authorization: `tma ${userStore.initDataRaw}`,
},
body: formData,
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Auth regression: cross-origin request sends no credentials.

Switching to coreApiUrl without Authorization or credentials will 401. Either route via a local proxy endpoint or include credentials.

Apply minimal fix:

-    await $fetch(`${publicEnv.coreApiUrl}/user/id/${userStore.id}/image`, {
+    await $fetch(`${publicEnv.coreApiUrl}/user/id/${userStore.id}/image`, {
       method: 'POST',
       body: formData,
+      credentials: 'include',
     })

If cookies aren’t first-party to coreApiUrl, prefer a Nuxt server proxy (e.g., POST /api/user/id/[id]/image) to avoid CORS + cookies pitfalls.


🏁 Script executed:

#!/bin/bash
# Confirm no remaining direct calls to core API that need credentials
rg -nP --type=vue --type=ts '\$\s*fetch\(\s*`?\${?publicEnv\.coreApiUrl' -C2

Length of output: 106


🏁 Script executed:

#!/bin/bash
# Confirm no other direct $fetch calls to coreApiUrl without credentials
rg -nP '\$fetch\(\s*`.*publicEnv\.coreApiUrl' -C2 --glob '*.vue'
rg -nP '\$fetch\(\s*`.*publicEnv\.coreApiUrl' -C2 --glob '*.ts'

Length of output: 1197


Auth regression: include credentials or proxy for all coreApiUrl fetch calls

Two direct $fetch calls to publicEnv.coreApiUrl lack credentials/authorization and will 401:

  • apps/atrium-telegram/app/components/form/UploadUserAvatar.vue (lines 69–72)
  • apps/atrium-telegram/server/api/epic/comment/id/[commentId]/beacon.post.ts (lines 22–24)

Apply minimal fixes:

# File: UploadUserAvatar.vue
 await $fetch(`${publicEnv.coreApiUrl}/user/id/${userStore.id}/image`, {
   method: 'POST',
   body: formData,
+  credentials: 'include',
 })

# File: beacon.post.ts
 await $fetch(`${publicEnv.coreApiUrl}/epic/comment/id/${commentId}/beacon`, {
   method: 'POST',
   body: data,
+  credentials: 'include',
 })

If cookies aren’t first-party to coreApiUrl, route client calls via a Nuxt server proxy endpoint to avoid CORS and cookie pitfalls.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { public: publicEnv } = useRuntimeConfig()
await $fetch(`${publicEnv.coreApiUrl}/user/id/${userStore.id}/image`, {
method: 'POST',
headers: {
Authorization: `tma ${userStore.initDataRaw}`,
},
body: formData,
})
const { public: publicEnv } = useRuntimeConfig()
await $fetch(`${publicEnv.coreApiUrl}/user/id/${userStore.id}/image`, {
method: 'POST',
body: formData,
credentials: 'include',
})
🤖 Prompt for AI Agents
In apps/atrium-telegram/app/components/form/UploadUserAvatar.vue around lines 67
to 72, the client $fetch to publicEnv.coreApiUrl is missing credentials and will
401; either add credentials to the client request (e.g., pass credentials:
"include" / appropriate auth headers via useFetch/$fetch options) or, if
coreApiUrl cookies are not first‑party, replace the direct call with a Nuxt
server proxy endpoint: create a server API route that receives the form data
from the client and forwards the POST to coreApiUrl including server-side
cookies/authorization, then call that internal endpoint from the component.
Ensure the chosen fix propagates formData correctly and handles/forwards errors.

Comment on lines +10 to +11
'image/avif',
'image/heif',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add image/heic to accepted MIME types (iOS default).

Mirror the web-app change; otherwise HEIC uploads from iOS will be rejected client-side.

Apply:

   'image/gif',
   'image/avif',
   'image/heif',
+  'image/heic',
 ]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'image/avif',
'image/heif',
'image/gif',
'image/avif',
'image/heif',
'image/heic',
]
🤖 Prompt for AI Agents
In apps/atrium-telegram/shared/services/media.ts around lines 10 to 11, the
accepted MIME types array is missing 'image/heic' (iOS default) which causes
HEIC uploads to be rejected; add the string 'image/heic' to the list of accepted
MIME types (e.g., alongside 'image/heif' and 'image/avif') so the client will
allow HEIC images.

const IMAGE_SIZES = [256, 512]
const IMAGE_FORMATS = ['jpg', 'webp'] as const
const ACCEPTED_IMAGE_FORMATS = ['jpeg', 'jpg', 'png', 'webp']
const ACCEPTED_IMAGE_FORMATS = ['jpeg', 'jpg', 'png', 'webp', 'heif', 'avif']
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Include ‘heic’ and confirm runtime decode support.

  • Add 'heic' for broader HEIF coverage.
  • Ensure the deployment’s sharp/libvips build supports HEIF/AVIF decode; otherwise uploads will fail at metadata().

Apply:

-const ACCEPTED_IMAGE_FORMATS = ['jpeg', 'jpg', 'png', 'webp', 'heif', 'avif']
+const ACCEPTED_IMAGE_FORMATS = ['jpeg', 'jpg', 'png', 'webp', 'heif', 'heic', 'avif'] as const

To verify support and avoid regressions, run:

And confirm environment support:


🏁 Script executed:

#!/bin/bash
# Find all places that mention HEIF/AVIF and ensure consistency
rg -nC2 -i 'heif|heic|avif|ACCEPTED_IMAGE_FORMATS|ACCEPTED_IMAGE_TYPES'

# Optional: check sharp version used (lockfile)
fd lock | xargs -I{} rg -n 'sharp@' {}

Length of output: 5647


🌐 Web query:

Does the current sharp version used by Nuxt/Nitro support decoding HEIF/HEIC and AVIF by default, or does it require libvips/OS dependencies?

💡 Result:

Short answer: You still need libvips / OS libs for full HEIF/HEIC (HEVC) support; AVIF is supported by sharp’s prebuilt binaries. sharp’s docs/state that AVIF is included in prebuilt binaries, but HEIF/HEIC using HEVC requires a globally installed libvips compiled with libheif (and codecs like libde265/x265). [1][2]

Sources:

  • sharp API (HEIF notes). [1]
  • sharp changelog (AVIF/prebuilt binaries; HEIF requires libvips compiled with libheif). [2]

Add HEIC support and verify HEIF/HEIC decode dependencies

  • Update apps/web-app/server/api/user/id/[userId]/image.post.ts (line 10): include 'heic' in ACCEPTED_IMAGE_FORMATS (e.g. ['jpeg','jpg','png','webp','heif','heic','avif']) and consider appending as const.
  • Mirror in apps/web-app/shared/services/media.ts (line 10): add 'image/heic' to ACCEPTED_IMAGE_TYPES.
  • Confirm your deployment’s libvips build is compiled with libheif and HEVC codecs (sharp’s prebuilt binaries include AVIF but not full HEIF/HEIC support).
🤖 Prompt for AI Agents
In apps/web-app/server/api/user/id/[userId]/image.post.ts around line 10, add
'heic' to ACCEPTED_IMAGE_FORMATS (e.g.
['jpeg','jpg','png','webp','heif','heic','avif']) and consider marking the array
as readonly (as const); in apps/web-app/shared/services/media.ts around line 10,
add 'image/heic' to ACCEPTED_IMAGE_TYPES to mirror the change; finally, ensure
your deployment's libvips/sharp build includes libheif and required HEVC codecs
(or document fallback behavior) because sharp’s prebuilt binaries may not
provide full HEIF/HEIC support.

Comment on lines +10 to +11
'image/avif',
'image/heif',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add image/heic to accepted MIME types (iOS default).

Many devices (notably iOS) upload HEIC as image/heic; current schema will reject them.

Apply:

   'image/gif',
   'image/avif',
   'image/heif',
+  'image/heic',
 ]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
'image/avif',
'image/heif',
'image/gif',
'image/avif',
'image/heif',
'image/heic',
]
🤖 Prompt for AI Agents
In apps/web-app/shared/services/media.ts around lines 10-11 the accepted MIME
types list is missing the iOS default 'image/heic', so uploads from many iOS
devices will be rejected; add 'image/heic' to the array of accepted MIME types
alongside the existing image/avif and image/heif entries, and run/update any
related validation/schema tests or type definitions that reference this list to
include the new value.

@coderabbitai coderabbitai Bot mentioned this pull request Aug 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant