-
Notifications
You must be signed in to change notification settings - Fork 992
Distinguish videoUpload modes for more accurate progress reporting #1196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughCentralizes desktop semver checks, adds a Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant D as Desktop Client
participant API as /api/desktop/.../video
participant DB as Database
D->>API: POST create/progress (X-Cap-Desktop-Version)
API->>API: isFromDesktopSemver(UPLOAD_PROGRESS_VERSION)?
API->>DB: SELECT video LEFT JOIN video_uploads
alt No upload row
API->>DB: INSERT video_uploads (init state)
else Existing row
alt singlepart complete
API->>DB: DELETE video_uploads row
else update in-progress
API->>DB: UPDATE uploaded/total/updatedAt
end
end
API-->>D: JSON response
sequenceDiagram
autonumber
participant C as Client
participant S as /api/upload/.../signed
participant DB as Database
participant S3 as S3
C->>S: GET presigned URL (fileKey)
S->>S: Parse videoId, validate presence
alt valid videoId
S->>DB: UPDATE videos (duration,width,height,fps)
opt fileKey == "result.mp4" AND isFromDesktopSemver(UPLOAD_PROGRESS_VERSION)
S->>DB: UPDATE/UPSERT video_uploads.mode = "singlepart"
end
end
S->>S3: Create presigned URL
S3-->>S: URL
S-->>C: URL
sequenceDiagram
autonumber
participant C as Client
participant M as /api/upload/.../multipart:initiate
participant DB as Database
participant S3 as S3
C->>M: POST initiate multipart (fileKey/body)
M->>M: Derive videoId, validate
alt Video not found
M-->>C: 404 JSON (Video not found)
else Found
M->>DB: UPSERT video_uploads.mode = "multipart"
M->>S3: Create multipart upload
S3-->>M: UploadId, parts info
M-->>C: JSON (UploadId, parts)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
apps/web/app/api/desktop/[...route]/video.ts(3 hunks)apps/web/app/api/upload/[...route]/multipart.ts(1 hunks)apps/web/app/api/upload/[...route]/signed.ts(3 hunks)apps/web/utils/desktop.ts(1 hunks)packages/database/schema.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.Use strict TypeScript and avoid any; leverage shared types
Files:
packages/database/schema.tsapps/web/utils/desktop.tsapps/web/app/api/desktop/[...route]/video.tsapps/web/app/api/upload/[...route]/multipart.tsapps/web/app/api/upload/[...route]/signed.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
packages/database/schema.tsapps/web/utils/desktop.tsapps/web/app/api/desktop/[...route]/video.tsapps/web/app/api/upload/[...route]/multipart.tsapps/web/app/api/upload/[...route]/signed.ts
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/utils/desktop.tsapps/web/app/api/desktop/[...route]/video.tsapps/web/app/api/upload/[...route]/multipart.tsapps/web/app/api/upload/[...route]/signed.ts
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and fetching in the web app
Mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData
Run server-side effects via the ManagedRuntime from apps/web/lib/server.ts using EffectRuntime.runPromise/runPromiseExit; do not create runtimes ad hoc
Client code should use helpers from apps/web/lib/EffectRuntime.ts (useEffectQuery, useEffectMutation, useRpcClient); never call ManagedRuntime.make inside components
Files:
apps/web/utils/desktop.tsapps/web/app/api/desktop/[...route]/video.tsapps/web/app/api/upload/[...route]/multipart.tsapps/web/app/api/upload/[...route]/signed.ts
apps/web/app/api/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/app/api/**/*.{ts,tsx}: Prefer Server Actions for API surface; when routes are necessary, implement under app/api and export only the handler from apiToHandler(ApiLive)
Construct API routes with @effect/platform HttpApi/HttpApiBuilder, declare contracts with Schema, and only export the handler
Use HttpAuthMiddleware for required auth and provideOptionalAuth for guests; avoid duplicating session lookups
Map domain errors to transport with HttpApiError.* and keep translation exhaustive (catchTags/tapErrorCause)
Inside HttpApiBuilder.group, acquire services with Effect.gen and provide dependencies via Layer.provide instead of manual provideService
Files:
apps/web/app/api/desktop/[...route]/video.tsapps/web/app/api/upload/[...route]/multipart.tsapps/web/app/api/upload/[...route]/signed.ts
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Server components needing Effect services must call EffectRuntime.runPromise(effect.pipe(provideOptionalAuth))
Files:
apps/web/app/api/desktop/[...route]/video.tsapps/web/app/api/upload/[...route]/multipart.tsapps/web/app/api/upload/[...route]/signed.ts
🧬 Code graph analysis (4)
apps/web/utils/desktop.ts (1)
apps/desktop/scripts/prepare.js (1)
major(30-30)
apps/web/app/api/desktop/[...route]/video.ts (2)
apps/web/utils/desktop.ts (2)
isFromDesktopSemver(3-10)UPLOAD_PROGRESS_VERSION(12-12)packages/database/schema.ts (2)
videos(277-332)videoUploads(710-717)
apps/web/app/api/upload/[...route]/multipart.ts (4)
packages/web-backend/src/Videos/index.ts (1)
Videos(12-230)packages/web-backend/src/Database.ts (1)
Database(5-15)packages/web-backend/src/Auth.ts (1)
provideOptionalAuth(91-113)apps/web/lib/server.ts (1)
runPromise(124-136)
apps/web/app/api/upload/[...route]/signed.ts (2)
packages/database/index.ts (2)
db(18-25)updateIfDefined(28-29)apps/web/utils/desktop.ts (2)
isFromDesktopSemver(3-10)UPLOAD_PROGRESS_VERSION(12-12)
⏰ 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 Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
There was a problem hiding this 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
♻️ Duplicate comments (1)
apps/web/app/api/upload/[...route]/signed.ts (1)
183-183: The fileKey comparison never matches.The condition
fileKey === "result.mp4"will never be true becausefileKeyis a full path (e.g.,userId/videoId/result.mp4), as confirmed by the comment on line 161 and the split logic. The singlepart mode update never runs.Apply the suggested fix from the previous review:
- if (fileKey === "result.mp4" && clientSupportsUploadProgress) + if ( + fileKey.split("/").at(-1) === "result.mp4" && + clientSupportsUploadProgress + ) await db() .update(Db.videoUploads) .set({ mode: "singlepart" }) .where(eq(Db.videoUploads.videoId, videoId));
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/app/api/upload/[...route]/signed.ts(4 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.Use strict TypeScript and avoid any; leverage shared types
Files:
apps/web/app/api/upload/[...route]/signed.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/api/upload/[...route]/signed.ts
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/api/upload/[...route]/signed.ts
apps/web/app/api/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/app/api/**/*.{ts,tsx}: Prefer Server Actions for API surface; when routes are necessary, implement under app/api and export only the handler from apiToHandler(ApiLive)
Construct API routes with @effect/platform HttpApi/HttpApiBuilder, declare contracts with Schema, and only export the handler
Use HttpAuthMiddleware for required auth and provideOptionalAuth for guests; avoid duplicating session lookups
Map domain errors to transport with HttpApiError.* and keep translation exhaustive (catchTags/tapErrorCause)
Inside HttpApiBuilder.group, acquire services with Effect.gen and provide dependencies via Layer.provide instead of manual provideService
Files:
apps/web/app/api/upload/[...route]/signed.ts
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and fetching in the web app
Mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData
Run server-side effects via the ManagedRuntime from apps/web/lib/server.ts using EffectRuntime.runPromise/runPromiseExit; do not create runtimes ad hoc
Client code should use helpers from apps/web/lib/EffectRuntime.ts (useEffectQuery, useEffectMutation, useRpcClient); never call ManagedRuntime.make inside components
Files:
apps/web/app/api/upload/[...route]/signed.ts
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Server components needing Effect services must call EffectRuntime.runPromise(effect.pipe(provideOptionalAuth))
Files:
apps/web/app/api/upload/[...route]/signed.ts
🧬 Code graph analysis (1)
apps/web/app/api/upload/[...route]/signed.ts (2)
packages/database/index.ts (2)
db(18-25)updateIfDefined(28-29)apps/web/utils/desktop.ts (2)
isFromDesktopSemver(3-10)UPLOAD_PROGRESS_VERSION(12-12)
⏰ 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 Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Build Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Analyze (rust)
🔇 Additional comments (2)
apps/web/app/api/upload/[...route]/signed.ts (2)
7-7: LGTM: Clean namespace migration and utility imports.The migration to the
Dbnamespace for schema references improves clarity, and the desktop utility imports enable proper client version checking for upload progress features.Also applies to: 18-22, 59-60, 167-167, 169-172, 175-175
164-176: LGTM: Robust video metadata update logic.The guard on line 164 prevents errors when videoId is unavailable, and the use of
updateIfDefinedcorrectly preserves existing values for optional fields. TheownerIdconstraint ensures updates are properly scoped to the authenticated user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/web/app/api/upload/[...route]/multipart.ts (2)
49-51: Extract duplicated videoId derivation logic.The past review comment has been correctly addressed—the code now derives the actual
videoIdfrom the request instead of usinguser.id. However, this exact logic is duplicated in the/completeendpoint (lines 245-247).Extract this into a shared helper function to maintain DRY:
// In a shared utility file or at the top of this file function deriveVideoId(body: { videoId?: string; fileKey?: string }, fileKey: string): string { const videoIdFromFileKey = fileKey.split("/")[1]; const videoId = "videoId" in body && body.videoId ? body.videoId : videoIdFromFileKey; if (!videoId) throw new Error("Video ID is required"); return videoId; }Then use it in both endpoints:
-const videoIdFromFileKey = fileKey.split("/")[1]; -const videoId = "videoId" in body ? body.videoId : videoIdFromFileKey; -if (!videoId) throw new Error("Video ID is required"); +const videoId = deriveVideoId(body, fileKey);
51-51: Consider Effect error handling for consistency.Throwing a plain
Errorhere is inconsistent with the Effect-based error handling used throughout the preprocessing block. While this works as an early validation, moving it inside the Effect.gen would maintain a uniform error handling pattern.Refactor to handle the validation inside Effect.gen:
const fileKey = parseVideoIdOrFileKey(user.id, { ...body, subpath: "result.mp4", }); const videoIdFromFileKey = fileKey.split("/")[1]; const videoId = "videoId" in body ? body.videoId : videoIdFromFileKey; - if (!videoId) throw new Error("Video ID is required"); const resp = await Effect.gen(function* () { + if (!videoId) return yield* Effect.fail(new Error("Video ID is required")); + const videos = yield* Videos; const db = yield* Database; const video = yield* videos.getById(Video.VideoId.make(videoId)); if (Option.isNone(video)) return yield* new Video.NotFoundError(); yield* db.use((db) => db .update(Db.videoUploads) .set({ mode: "multipart" }) .where(eq(Db.videoUploads.videoId, video.value[0].id)), ); }).pipe( provideOptionalAuth, Effect.tapError(Effect.logError), Effect.catchAll((e) => { if (e._tag === "VideoNotFoundError") return Effect.succeed<Response>(c.text("Video not found", 404)); return Effect.succeed<Response>( c.json({ error: "Error initiating multipart upload" }, 500), ); }), runPromise, ); if (resp) return resp;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/app/api/upload/[...route]/multipart.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.Use strict TypeScript and avoid any; leverage shared types
Files:
apps/web/app/api/upload/[...route]/multipart.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/api/upload/[...route]/multipart.ts
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/api/upload/[...route]/multipart.ts
apps/web/app/api/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/app/api/**/*.{ts,tsx}: Prefer Server Actions for API surface; when routes are necessary, implement under app/api and export only the handler from apiToHandler(ApiLive)
Construct API routes with @effect/platform HttpApi/HttpApiBuilder, declare contracts with Schema, and only export the handler
Use HttpAuthMiddleware for required auth and provideOptionalAuth for guests; avoid duplicating session lookups
Map domain errors to transport with HttpApiError.* and keep translation exhaustive (catchTags/tapErrorCause)
Inside HttpApiBuilder.group, acquire services with Effect.gen and provide dependencies via Layer.provide instead of manual provideService
Files:
apps/web/app/api/upload/[...route]/multipart.ts
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and fetching in the web app
Mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData
Run server-side effects via the ManagedRuntime from apps/web/lib/server.ts using EffectRuntime.runPromise/runPromiseExit; do not create runtimes ad hoc
Client code should use helpers from apps/web/lib/EffectRuntime.ts (useEffectQuery, useEffectMutation, useRpcClient); never call ManagedRuntime.make inside components
Files:
apps/web/app/api/upload/[...route]/multipart.ts
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Server components needing Effect services must call EffectRuntime.runPromise(effect.pipe(provideOptionalAuth))
Files:
apps/web/app/api/upload/[...route]/multipart.ts
🧬 Code graph analysis (1)
apps/web/app/api/upload/[...route]/multipart.ts (5)
packages/web-backend/src/Videos/index.ts (1)
Videos(12-230)packages/web-backend/src/Database.ts (1)
Database(5-15)packages/web-domain/src/Video.ts (1)
Video(16-59)packages/web-backend/src/Auth.ts (1)
provideOptionalAuth(91-113)apps/web/lib/server.ts (1)
runPromise(124-136)
⏰ 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 Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
🔇 Additional comments (1)
apps/web/app/api/upload/[...route]/multipart.ts (1)
359-386: LGTM: Multipart completion correctly deletes videoUploads row.The transaction properly updates video metadata and deletes the corresponding
videoUploadsrow upon completion, which aligns with the PR objective: "For multipart uploads: delete as part of completion."
There was a problem hiding this 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
♻️ Duplicate comments (1)
apps/web/app/api/upload/[...route]/signed.ts (1)
183-187: Still need to ensure thevideo_uploadsrow exists before updating the modeThis update continues to assume a
video_uploadsrecord already exists, so single-part flows that never calledmultipart/initiatestill end up touching 0 rows and we never mark them as"singlepart". Please insert (or upsert) the row before updating, mirroring the multipart path—e.g.insert(...).onDuplicateKeyUpdate({ set: { mode: "singlepart" } }).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/web/app/api/upload/[...route]/signed.ts(4 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use a 2-space indent for TypeScript code.
Use Biome for formatting and linting TypeScript/JavaScript files by runningpnpm format.Use strict TypeScript and avoid any; leverage shared types
Files:
apps/web/app/api/upload/[...route]/signed.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use kebab-case for filenames for TypeScript/JavaScript modules (e.g.,user-menu.tsx).
Use PascalCase for React/Solid components.
Files:
apps/web/app/api/upload/[...route]/signed.ts
apps/web/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
On the client, always use
useEffectQueryoruseEffectMutationfrom@/lib/EffectRuntime; never callEffectRuntime.run*directly in components.
Files:
apps/web/app/api/upload/[...route]/signed.ts
apps/web/app/api/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/app/api/**/*.{ts,tsx}: Prefer Server Actions for API surface; when routes are necessary, implement under app/api and export only the handler from apiToHandler(ApiLive)
Construct API routes with @effect/platform HttpApi/HttpApiBuilder, declare contracts with Schema, and only export the handler
Use HttpAuthMiddleware for required auth and provideOptionalAuth for guests; avoid duplicating session lookups
Map domain errors to transport with HttpApiError.* and keep translation exhaustive (catchTags/tapErrorCause)
Inside HttpApiBuilder.group, acquire services with Effect.gen and provide dependencies via Layer.provide instead of manual provideService
Files:
apps/web/app/api/upload/[...route]/signed.ts
apps/web/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/web/**/*.{ts,tsx}: Use TanStack Query v5 for all client-side server state and fetching in the web app
Mutations should call Server Actions directly and perform targeted cache updates with setQueryData/setQueriesData
Run server-side effects via the ManagedRuntime from apps/web/lib/server.ts using EffectRuntime.runPromise/runPromiseExit; do not create runtimes ad hoc
Client code should use helpers from apps/web/lib/EffectRuntime.ts (useEffectQuery, useEffectMutation, useRpcClient); never call ManagedRuntime.make inside components
Files:
apps/web/app/api/upload/[...route]/signed.ts
apps/web/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Server components needing Effect services must call EffectRuntime.runPromise(effect.pipe(provideOptionalAuth))
Files:
apps/web/app/api/upload/[...route]/signed.ts
🧬 Code graph analysis (1)
apps/web/app/api/upload/[...route]/signed.ts (2)
packages/database/index.ts (2)
db(18-25)updateIfDefined(28-29)apps/web/utils/desktop.ts (2)
isFromDesktopSemver(3-10)UPLOAD_PROGRESS_VERSION(12-12)
⏰ 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 Desktop (x86_64-pc-windows-msvc, windows-latest)
- GitHub Check: Build Desktop (aarch64-apple-darwin, macos-latest)
- GitHub Check: Analyze (rust)
| import { | ||
| isAtLeastSemver, | ||
| isFromDesktopSemver, | ||
| UPLOAD_PROGRESS_VERSION, | ||
| } from "@/utils/desktop"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the unused isAtLeastSemver import
isAtLeastSemver isn’t referenced anywhere in this file, so TypeScript (with noUnusedLocals) or Biome will fail the build. Please drop the unused symbol from the import.
-import {
- isAtLeastSemver,
- isFromDesktopSemver,
- UPLOAD_PROGRESS_VERSION,
-} from "@/utils/desktop";
+import {
+ isFromDesktopSemver,
+ UPLOAD_PROGRESS_VERSION,
+} from "@/utils/desktop";📝 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.
| import { | |
| isAtLeastSemver, | |
| isFromDesktopSemver, | |
| UPLOAD_PROGRESS_VERSION, | |
| } from "@/utils/desktop"; | |
| import { | |
| isFromDesktopSemver, | |
| UPLOAD_PROGRESS_VERSION, | |
| } from "@/utils/desktop"; |
🤖 Prompt for AI Agents
In apps/web/app/api/upload/[...route]/signed.ts around lines 18 to 22, the
import list includes isAtLeastSemver which is not used in this file; remove
isAtLeastSemver from the import statement so only isFromDesktopSemver and
UPLOAD_PROGRESS_VERSION are imported to satisfy TypeScript/Biome noUnusedLocals
rules and allow the build to pass.
For multipart uploads: Delete as part of completion
multipart/initiateFor singlepart uploads: Delete in progress handler
upload/signedif client supports itSummary by CodeRabbit
New Features
Bug Fixes
UX