Migrate server to elysia and bun runtime#28
Conversation
…ances of trpc on web and mobile
📝 WalkthroughWalkthroughThe pull request migrates the backend from Node.js/Express/tRPC to Bun/Elysia/Eden Treaty, updates CI/CD deployment configurations with Sentry release management, and converts all client-side API integrations from tRPC to Eden Treaty across the mobile and web applications. Changes
Sequence Diagram(s)sequenceDiagram
participant Client as Client<br/>(Mobile/Web)
participant Server as Elysia Server
participant Auth as Auth Handler<br/>(better-auth)
participant DB as Database
participant Sentry as Sentry
Client->>Server: HTTP Request<br/>(with Cookie)
activate Server
rect rgb(200, 220, 255)
Note over Server: betterAuthGuard<br/>Middleware Plugin
Server->>Auth: getSession(headers)
activate Auth
Auth->>Auth: Validate Token
Auth-->>Server: Session + User
deactivate Auth
end
alt Auth Success (User Role)
rect rgb(200, 255, 220)
Note over Server: Route Handler
Server->>DB: Query/Execute
activate DB
DB-->>Server: Result
deactivate DB
end
Server-->>Client: 200 + Response
else Auth Failure
rect rgb(255, 200, 200)
Note over Server: Error Path
Server->>Sentry: Capture Error<br/>(via onError hook)
Server-->>Client: 401/403
end
end
deactivate Server
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 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 |
Deploying bahar with
|
| Latest commit: |
10e366d
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://b89efd1d.bahar-5xu.pages.dev |
| Branch Preview URL: | https://chore-migrate-to-bun-runtime.bahar-5xu.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/actions/fly-deploy/action.yml (1)
15-30: Sentry release tracking has been removed.The deployment action no longer includes Sentry-related inputs (
sentry_api_auth_token,sentry_api_project,sentry_org) or build arguments. This removes the ability to track releases in Sentry during deployment.If Sentry release tracking is still needed, consider implementing it elsewhere in the deployment pipeline or documenting why it was removed.
🧹 Nitpick comments (6)
apps/web/src/routes/_authorized-layout/route.tsx (1)
233-234: Remove debug console.log statement.This console.log appears to be debug code that was left in. The
errReasonis already captured in the Sentry context on line 239, making this redundant. Remove it to keep the production code clean.🔎 Proposed fix
- console.log(errReason); - Sentry.captureException(new Error(error.type), {apps/api/README.md (1)
191-192: Documentation incomplete: missing example after the note.Line 191 states that environment values should NOT have quotes, but there's no example showing the correct format. Consider adding a brief example:
🔎 Suggested addition
**Important:** When using `--env-file`, values should NOT have quotes around them: + +```bash +# Correct +DATABASE_URL=libsql://example.turso.io + +# Incorrect +DATABASE_URL="libsql://example.turso.io" +```apps/web/src/lib/api.ts (1)
5-5: Consider validating the base URL at runtime.The client initialization doesn't validate that
VITE_API_BASE_URLis defined. While build-time checks may catch this, adding a runtime assertion would provide clearer error messages during development.🔎 Optional improvement
+const baseUrl = import.meta.env.VITE_API_BASE_URL; +if (!baseUrl) { + throw new Error("VITE_API_BASE_URL environment variable is not defined"); +} + -export const api = treaty<App>(import.meta.env.VITE_API_BASE_URL, { +export const api = treaty<App>(baseUrl, { fetch: { credentials: "include", }, headers: () => ({ [TRACE_ID_HEADER]: generateTraceId(), }), });apps/api/src/index.ts (1)
55-59: Consider returning an error response from the global error handler.The
onErrorhook captures exceptions to Sentry and logs them, but doesn't return a structured error response. Elysia may return the raw error message to clients. Consider returning a generic error response to avoid leaking internal details.🔎 Suggested improvement
.onError(({ error, code }) => { Sentry.captureException(error); logger.error({ error, code }, "Request error"); + + return { error: "Internal server error" }; })apps/api/src/routers/databases.ts (1)
30-63: Consider adding error handling for the token refresh operation.The token refresh logic is correct, but if
tursoPlatformClient.databases.createTokenfails, the error will propagate unhandled. Consider wrapping the external call in a try/catch to return a more specific error response.🔎 Suggested improvement
if (userDb?.access_token && isJwtExpired(userDb.access_token)) { + try { const newToken = await tursoPlatformClient.databases.createToken( userDb.db_name, ); await db .update(databases) .set({ access_token: newToken.jwt }) .where(eq(databases.id, userDb.id)); return { ...userDb, access_token: newToken.jwt }; + } catch (error) { + return status(500, { message: "Failed to refresh database token" }); + } }apps/api/src/routers/migrations.ts (1)
83-91: Consider pagination for the /full endpoint.Returning all migrations unbounded could become problematic as the migrations table grows over time.
This is likely fine for now if migrations are expected to remain relatively small in number, but consider adding pagination or a limit if this could scale.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (41)
.github/actions/fly-deploy/action.yml.github/workflows/deploy-server.yml.gitignoreCLAUDE.mdREADME.mdapps/api/Dockerfileapps/api/README.mdapps/api/build.mjsapps/api/entrypoint.shapps/api/fly.tomlapps/api/instrument.mjsapps/api/package.jsonapps/api/src/db/migrate.tsapps/api/src/index.tsapps/api/src/middleware.tsapps/api/src/routers/databases.tsapps/api/src/routers/migrations.tsapps/api/src/trpc.tsapps/mobile/README.mdapps/mobile/package.jsonapps/mobile/src/app/(search)/(home)/add-word.tsxapps/mobile/src/app/(search)/(home)/edit-word/[id].tsxapps/mobile/src/app/(search)/_layout.tsxapps/mobile/src/app/(search)/decks.tsxapps/mobile/src/app/(search)/settings.tsxapps/mobile/src/app/_layout.tsxapps/mobile/src/components/decks/CreateDeckForm.tsxapps/mobile/src/components/flashcards/FlashcardReview.tsxapps/mobile/src/components/settings/SettingsScreen.tsxapps/mobile/src/lib/db/index.tsapps/mobile/src/utils/api.tsapps/mobile/src/utils/trpc.tsapps/web/README.mdapps/web/package.jsonapps/web/src/App.tsxapps/web/src/components/features/settings/AdminSettingsCardSection.tsxapps/web/src/lib/api.tsapps/web/src/lib/db/index.tsapps/web/src/lib/trpc.tsapps/web/src/routes/_authorized-layout/route.tsxpackage.json
💤 Files with no reviewable changes (6)
- apps/api/src/trpc.ts
- apps/mobile/src/utils/trpc.ts
- apps/web/src/lib/trpc.ts
- apps/api/build.mjs
- apps/api/instrument.mjs
- apps/api/entrypoint.sh
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript with strict typing across entire codebase
Do not useanytype unless absolutely necessary
Write self-documenting code and avoid overuse of comments
Error handling with try/catch blocks and structured error types
UseDisplayErrorclass for user-friendly error messages andResult<T, E>type for explicit error handling (Rust-like pattern)
Files:
apps/mobile/src/components/flashcards/FlashcardReview.tsxapps/mobile/src/components/decks/CreateDeckForm.tsxapps/mobile/src/app/(search)/decks.tsxapps/mobile/src/app/(search)/settings.tsxapps/mobile/src/lib/db/index.tsapps/mobile/src/app/(search)/_layout.tsxapps/mobile/src/components/settings/SettingsScreen.tsxapps/api/src/middleware.tsapps/mobile/src/utils/api.tsapps/mobile/src/app/(search)/(home)/edit-word/[id].tsxapps/api/src/routers/migrations.tsapps/mobile/src/app/(search)/(home)/add-word.tsxapps/web/src/lib/db/index.tsapps/web/src/components/features/settings/AdminSettingsCardSection.tsxapps/api/src/index.tsapps/api/src/routers/databases.tsapps/api/src/db/migrate.tsapps/mobile/src/app/_layout.tsxapps/web/src/App.tsxapps/web/src/lib/api.tsapps/web/src/routes/_authorized-layout/route.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{tsx,jsx}: React components use functional style with hooks
Prefer using Jotai atoms over React Context for state management
State management: Use Tanstack Query for async state, Jotai for atomic state
Files:
apps/mobile/src/components/flashcards/FlashcardReview.tsxapps/mobile/src/components/decks/CreateDeckForm.tsxapps/mobile/src/app/(search)/decks.tsxapps/mobile/src/app/(search)/settings.tsxapps/mobile/src/app/(search)/_layout.tsxapps/mobile/src/components/settings/SettingsScreen.tsxapps/mobile/src/app/(search)/(home)/edit-word/[id].tsxapps/mobile/src/app/(search)/(home)/add-word.tsxapps/web/src/components/features/settings/AdminSettingsCardSection.tsxapps/mobile/src/app/_layout.tsxapps/web/src/App.tsxapps/web/src/routes/_authorized-layout/route.tsx
apps/mobile/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Mobile app uses UniWind (Tailwind for React Native) with Tailwind CSS v4
Files:
apps/mobile/src/components/flashcards/FlashcardReview.tsxapps/mobile/src/components/decks/CreateDeckForm.tsxapps/mobile/src/app/(search)/decks.tsxapps/mobile/src/app/(search)/settings.tsxapps/mobile/src/app/(search)/_layout.tsxapps/mobile/src/components/settings/SettingsScreen.tsxapps/mobile/src/app/(search)/(home)/edit-word/[id].tsxapps/mobile/src/app/(search)/(home)/add-word.tsxapps/mobile/src/app/_layout.tsx
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Component naming: PascalCase for components, camelCase for functions/variables
Files:
apps/mobile/src/components/flashcards/FlashcardReview.tsxapps/mobile/src/components/decks/CreateDeckForm.tsxapps/mobile/src/app/(search)/decks.tsxapps/mobile/src/app/(search)/settings.tsxapps/mobile/src/lib/db/index.tsapps/mobile/src/app/(search)/_layout.tsxapps/mobile/src/components/settings/SettingsScreen.tsxapps/api/src/middleware.tsapps/mobile/src/utils/api.tsapps/mobile/src/app/(search)/(home)/edit-word/[id].tsxapps/api/src/routers/migrations.tsapps/mobile/src/app/(search)/(home)/add-word.tsxapps/web/src/lib/db/index.tsapps/web/src/components/features/settings/AdminSettingsCardSection.tsxapps/api/src/index.tsapps/api/src/routers/databases.tsapps/api/src/db/migrate.tsapps/mobile/src/app/_layout.tsxapps/web/src/App.tsxapps/web/src/lib/api.tsapps/web/src/routes/_authorized-layout/route.tsx
apps/web/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Web app uses Shadcn/UI components and Tailwind CSS v4 for styling, using the
cn()utility function for combining and conditionally applying Tailwind classes
Files:
apps/web/src/components/features/settings/AdminSettingsCardSection.tsxapps/web/src/App.tsxapps/web/src/routes/_authorized-layout/route.tsx
🧠 Learnings (14)
📚 Learning: 2025-11-27T06:02:25.941Z
Learnt from: Shunseii
Repo: Shunseii/bahar PR: 24
File: apps/web/src/components/features/decks/DeckDialogContent.tsx:195-201
Timestamp: 2025-11-27T06:02:25.941Z
Learning: In apps/web/src/components/features/decks/DeckDialogContent.tsx, the backend API calls (trpc.decks.create and trpc.decks.update) are temporary and planned to be removed after migration is complete.
Applied to files:
apps/mobile/src/components/flashcards/FlashcardReview.tsxapps/mobile/src/components/decks/CreateDeckForm.tsxapps/mobile/src/app/(search)/decks.tsxapps/mobile/src/app/(search)/settings.tsxapps/mobile/src/lib/db/index.tsapps/mobile/src/app/(search)/_layout.tsxapps/mobile/src/app/(search)/(home)/edit-word/[id].tsxapps/mobile/src/app/(search)/(home)/add-word.tsxapps/web/src/lib/db/index.tsapps/web/src/components/features/settings/AdminSettingsCardSection.tsxapps/mobile/src/app/_layout.tsxapps/web/src/App.tsx
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Applies to **/*.{tsx,jsx} : State management: Use Tanstack Query for async state, Jotai for atomic state
Applied to files:
apps/mobile/src/components/decks/CreateDeckForm.tsxapps/mobile/src/app/(search)/decks.tsxapps/mobile/src/app/(search)/_layout.tsxapps/mobile/src/components/settings/SettingsScreen.tsxapps/mobile/src/app/(search)/(home)/add-word.tsxapps/mobile/src/app/_layout.tsxapps/web/src/App.tsxapps/web/package.json
📚 Learning: 2025-12-25T22:07:07.504Z
Learnt from: Shunseii
Repo: Shunseii/bahar PR: 27
File: apps/api/src/db/schema/auth.ts:34-36
Timestamp: 2025-12-25T22:07:07.504Z
Learning: Files in apps/api/src/db/schema/auth.ts are auto-generated by better-auth and should not be manually modified as changes will be overwritten. Any schema issues should be tested and reported upstream to better-auth.
Applied to files:
apps/mobile/src/app/(search)/decks.tsxapps/mobile/src/lib/db/index.tsapps/api/src/middleware.tsapps/api/src/routers/migrations.tsapps/web/src/lib/db/index.tsapps/api/src/routers/databases.tsapps/api/src/db/migrate.tsapps/web/src/routes/_authorized-layout/route.tsx
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Use Orama client-side WASM search engine with multi-language support (Arabic + English) for the search feature, indexed from local database on app initialization
Applied to files:
apps/web/README.mdapps/mobile/README.md
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Web app implements local-first architecture with cloud sync using hybrid approach: local Turso database via sync-wasm with background sync interval of 60 seconds
Applied to files:
apps/web/README.mdapps/mobile/src/lib/db/index.tsapps/api/README.mdREADME.md
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Applies to apps/mobile/**/*.{tsx,jsx} : Mobile app uses UniWind (Tailwind for React Native) with Tailwind CSS v4
Applied to files:
apps/mobile/src/app/(search)/settings.tsxapps/mobile/src/app/(search)/_layout.tsxapps/mobile/package.jsonapps/mobile/src/app/(search)/(home)/edit-word/[id].tsxapps/mobile/src/app/_layout.tsxapps/web/src/App.tsx
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Applies to apps/web/**/*.{tsx,jsx} : Web app uses Shadcn/UI components and Tailwind CSS v4 for styling, using the `cn()` utility function for combining and conditionally applying Tailwind classes
Applied to files:
apps/mobile/src/app/(search)/_layout.tsxapps/mobile/src/app/_layout.tsxapps/web/src/App.tsx
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Applies to **/*.{tsx,jsx} : Prefer using Jotai atoms over React Context for state management
Applied to files:
apps/mobile/src/app/(search)/_layout.tsx
📚 Learning: 2025-11-30T06:57:48.510Z
Learnt from: Shunseii
Repo: Shunseii/bahar PR: 24
File: apps/web/src/lib/db/operations/settings.ts:15-21
Timestamp: 2025-11-30T06:57:48.510Z
Learning: In apps/web/src/lib/db/operations/settings.ts, the settings table is intentionally implemented as a de-facto singleton without schema-level enforcement. Multiple rows can exist due to initialization races, but all operations (SELECT without WHERE, UPDATE without WHERE) treat rows as synchronized and interchangeable. This is a conscious design decision where code clarity could be improved but functional correctness is maintained.
Applied to files:
apps/mobile/src/components/settings/SettingsScreen.tsx
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Mobile app uses Expo with file-based routing (Expo Router)
Applied to files:
apps/mobile/README.md
📚 Learning: 2025-11-27T23:01:26.752Z
Learnt from: Shunseii
Repo: Shunseii/bahar PR: 24
File: packages/drizzle-user-db-schemas/package.json:1-20
Timestamp: 2025-11-27T23:01:26.752Z
Learning: drizzle-zod0.5.1 has peer dependencies of "zod": "*" (accepts any version) and "drizzle-orm": ">=0.23.13". The zod wildcard peer dependency means any zod version is compatible with drizzle-zod0.5.1.
Applied to files:
apps/api/package.jsonapps/web/package.json
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Applies to **/*.{tsx,jsx} : React components use functional style with hooks
Applied to files:
apps/web/src/App.tsx
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Web app uses Tanstack Router for client-side routing
Applied to files:
apps/web/src/App.tsx
📚 Learning: 2025-12-26T00:10:55.894Z
Learnt from: CR
Repo: Shunseii/bahar PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-26T00:10:55.894Z
Learning: Applies to **/*.{ts,tsx} : Error handling with try/catch blocks and structured error types
Applied to files:
apps/web/src/routes/_authorized-layout/route.tsx
🧬 Code graph analysis (7)
apps/api/src/middleware.ts (2)
apps/api/src/auth.ts (1)
auth(29-373)apps/api/src/utils/logger.ts (1)
getTraceContext(15-25)
apps/mobile/src/utils/api.ts (2)
apps/web/src/lib/api.ts (1)
api(5-12)apps/api/src/index.ts (1)
App(67-67)
apps/web/src/lib/db/index.ts (3)
apps/mobile/src/utils/api.ts (1)
api(8-12)apps/web/src/lib/api.ts (1)
api(5-12)apps/web/src/lib/error.ts (1)
error(42-44)
apps/web/src/components/features/settings/AdminSettingsCardSection.tsx (1)
apps/web/src/lib/api.ts (1)
api(5-12)
apps/api/src/index.ts (5)
apps/api/src/utils/index.ts (1)
getAllowedDomains(7-14)apps/api/src/utils/logger.ts (1)
logger(33-77)apps/api/src/middleware.ts (1)
betterAuthGuard(6-32)apps/api/src/routers/migrations.ts (1)
migrationsRouter(8-91)apps/api/src/routers/databases.ts (1)
databasesRouter(9-63)
apps/api/src/routers/databases.ts (3)
apps/api/src/middleware.ts (1)
betterAuthGuard(6-32)apps/api/src/db/index.ts (1)
db(11-11)apps/api/src/db/schema/databases.ts (1)
databases(5-15)
apps/web/src/App.tsx (4)
apps/mobile/src/utils/api.ts (1)
queryClient(6-6)apps/web/src/lib/query.ts (1)
queryClient(4-19)apps/web/src/components/ui/tooltip.tsx (1)
TooltipProvider(28-28)apps/web/src/router.ts (1)
router(7-13)
⏰ 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). (2)
- GitHub Check: Workers Builds: bahar-marketing
- GitHub Check: Cloudflare Pages
🔇 Additional comments (44)
CLAUDE.md (1)
28-29: LGTM! Documentation accurately reflects the stack migration.The updated backend description correctly documents the shift from Node.js/Express/tRPC to Bun/Elysia/Eden Treaty.
.gitignore (1)
14-17: LGTM! Appropriate gitignore entries for Bun binaries.The new entries correctly ignore the
serverandmigratebinaries produced by the Bun build process.README.md (1)
58-66: LGTM! API documentation correctly updated.The API section accurately reflects the migration to Bun/Elysia and includes helpful details about logging and hosting infrastructure.
apps/api/fly.toml (1)
8-9: LGTM! Proper use of Fly.io release command for migrations.The
release_commandconfiguration correctly executes migrations before the application starts, following Fly.io best practices.apps/web/README.md (2)
15-15: LGTM! Documentation correctly reflects Eden Treaty integration.The README accurately documents the migration from tRPC to Eden Treaty for type-safe API communication.
48-48: LGTM! API architecture description updated correctly.The architecture section accurately describes the new Elysia/Eden Treaty API integration.
apps/api/src/db/migrate.ts (1)
1-14: Environment variables are properly loaded via Bun's built-in .env loading.Bun automatically loads
.envfiles, so the removal ofdotenv/configfrom migrate.ts is safe and follows best practices. Environment variables are validated at startup inapps/api/src/utils/config.tsusing Zod—if any required variables are missing, the process exits with a clear error message. This validation runs whendb/index.tsis imported and when the main app starts insrc/index.ts. Thedrizzle.config.tsfile retainsdotenv/configfor drizzle-kit commands, ensuring migrations work consistently across local development, production deployments, and CI/CD pipelines.package.json (1)
23-23: The Bun version requirement>=1.3is appropriate and already permits the current latest stable version (1.3.5). No update is needed.apps/web/package.json (1)
14-15: LGTM!The dependency changes correctly reflect the migration from TRPC to Eden Treaty. The
@elysiajs/edenpackage is the appropriate type-safe client for the Elysia backend.apps/web/src/App.tsx (1)
47-53: LGTM!The TRPC provider has been cleanly removed. The simplified provider hierarchy with
QueryClientProviderdirectly wrapping the app is correct for the Eden Treaty migration. As per the coding guidelines, the component follows React functional style with hooks and appropriately uses TanStack Query for async state.apps/api/README.md (1)
7-9: LGTM!The tech stack documentation accurately reflects the migration to Bun runtime, Elysia framework, and Eden Treaty for type-safe clients.
apps/api/Dockerfile (2)
59-79: LGTM!The Dockerfile multi-stage build is well-structured. Using
debian:12-slimfor the final image is appropriate since Bun compiles to native binaries. The external@libsql/linux-x64-gnumodule handling is correct, and the drizzle migrations are properly copied for runtime schema management.
1-4: Bun version 1.3.5 is confirmed to be available and compliant.The Docker Hub registry confirms that Bun 1.3.5 is available across all image variants. The pinned version satisfies the README requirement of
>= 1.3, and no availability or stability issues were identified.apps/mobile/src/app/(search)/decks.tsx (1)
22-22: LGTM!The import path update from
@/utils/trpcto@/utils/apicorrectly aligns with the Eden Treaty migration. ThequeryClientusage for cache invalidation remains unchanged and follows the TanStack Query patterns per the coding guidelines.apps/mobile/src/components/settings/SettingsScreen.tsx (1)
24-24: LGTM!The import path update aligns with the project-wide migration to Eden Treaty. The
queryClientusage for cache invalidation after settings updates is unchanged and correct.apps/mobile/src/app/(search)/(home)/add-word.tsx (1)
34-34: LGTM!The import path update is consistent with the Eden Treaty migration. The component continues to use
queryClientcorrectly for cache invalidation after word creation.apps/mobile/src/app/(search)/_layout.tsx (1)
27-27: LGTM!The import path update aligns with the Eden Treaty migration. The layout's sync handling with
queryClient.invalidateQueries()and Jotai atoms for sync state follows the coding guidelines correctly.apps/mobile/src/components/flashcards/FlashcardReview.tsx (1)
29-29: LGTM! Import path updated correctly.The queryClient import source has been properly updated to align with the Eden Treaty migration, with no changes to usage or behavior.
apps/mobile/src/app/(search)/settings.tsx (1)
28-28: LGTM! Import path updated correctly.The queryClient import source has been properly updated to align with the Eden Treaty migration.
apps/mobile/src/app/_layout.tsx (1)
35-35: LGTM! Import path updated correctly.The queryClient import has been updated to use the new API utilities module, maintaining the same usage pattern in the QueryClientProvider.
apps/mobile/src/components/decks/CreateDeckForm.tsx (1)
16-16: LGTM! Import path updated correctly.The queryClient import has been updated to align with the Eden Treaty migration.
apps/mobile/README.md (1)
16-16: LGTM! Documentation updated correctly.The tech stack documentation accurately reflects the migration from tRPC to Eden Treaty for type-safe API communication.
apps/mobile/src/app/(search)/(home)/edit-word/[id].tsx (1)
35-35: LGTM! Import path updated correctly.The queryClient import has been updated to use the new API utilities module, with no changes to the invalidateQueries usage.
apps/web/src/lib/api.ts (1)
1-12: LGTM! Eden Treaty client properly configured.The API client setup correctly:
- Uses type-safe Eden Treaty with the App type from the API server
- Includes credentials for authentication cookies
- Adds trace IDs to all requests for observability
- Generates fresh trace IDs per request via the headers function
.github/actions/fly-deploy/action.yml (1)
15-17: The workflow that uses this action (.github/workflows/deploy-server.yml) has been properly updated to pass thegithub_shainput with${{ github.sha }}. The integration is correct and there are no compatibility issues.apps/mobile/src/utils/api.ts (1)
8-12: Missingcredentials: "include"and trace header compared to web client.The web client at
apps/web/src/lib/api.tsincludesfetch: { credentials: "include" }and a trace ID header, but this mobile client only passes a cookie header. While the cookie header handles authentication, verify that Eden Treaty properly sends credentials for cross-origin requests in React Native context. Consider adding a trace ID header for consistent observability across clients.export const api = treaty<App>(process.env.EXPO_PUBLIC_API_BASE_URL!, { + fetch: { + credentials: "include", + }, headers: () => ({ cookie: authClient.getCookie(), + "x-request-id": crypto.randomUUID(), }), });apps/mobile/package.json (1)
19-19: LGTM!The migration from tRPC packages to
@elysiajs/edenis clean. Theapiworkspace dependency in devDependencies correctly enables type imports for the treaty client.apps/mobile/src/lib/db/index.ts (3)
78-82: LGTM!The Eden Treaty API call pattern with destructured
{ data, error }and error throwing is consistent with the web client implementation. The error handling withintryCatchpreserves the existing Result-based error mapping.
111-115: LGTM!Token refresh API call correctly migrated to Eden Treaty pattern.
192-196: LGTM!Migrations API call correctly migrated to Eden Treaty pattern.
.github/workflows/deploy-server.yml (2)
32-42: LGTM!Sentry release management is properly configured with commit association and sourcemap uploads. Using
github.shaas the release identifier aligns with theGITHUB_SHAenvironment variable used inapps/api/src/index.tsline 8.
28-30: No action needed. The workflow build command is correct for its purpose.The
bun build --sourcemap --outdir distin the workflow (lines 28-30) is specifically for generating source maps to upload to Sentry (lines 32-42), not for deployment. The actual deployment uses the Dockerfile, which independently compiles the server binary viabun build --compile --outfile server. These are two separate builds serving different purposes: the workflow generates sourcemaps for debugging, while the Dockerfile creates the production binary. No mismatch exists.Likely an incorrect or invalid review comment.
apps/api/src/index.ts (2)
1-10: LGTM!Sentry initialization is correctly placed before any other imports, which is critical for proper instrumentation. The release is tied to
GITHUB_SHAfor traceability to specific deployments.
40-51: LGTM!The request tracing setup correctly propagates existing
x-request-idheaders or generates new UUIDs, and usesAsyncLocalStorageviatraceContext.enterWith()for request-scoped context.apps/web/src/lib/db/index.ts (3)
72-76: LGTM!Eden Treaty API call pattern is consistent with the mobile implementation and correctly integrated with the existing
tryCatcherror handling.
113-117: LGTM!Token refresh API call correctly migrated.
186-190: LGTM!Migrations API call correctly migrated.
apps/api/package.json (2)
21-39: LGTM!Clean migration from Express/tRPC ecosystem to Elysia with appropriate dependencies. The
@sentry/bunpackage correctly replaces the Node.js-specific Sentry packages for Bun runtime.
10-10: The deployment is specifically configured for Linux x86_64 (debian:12-slim), and the--external @libsql/linux-x64-gnuflag is correctly handling the native module for that platform. The Dockerfile explicitly copies the native module at runtime, andfly.tomlcontains no multi-platform or ARM64 configuration. No additional platform-specific externals are needed for the current deployment setup.apps/api/src/middleware.ts (1)
6-32: LGTM!The Elysia macro pattern for authentication is well-structured. The guard correctly:
- Mounts better-auth handler for auth routes
- Returns 401 for unauthenticated requests
- Returns 403 for non-admin users when admin role is required
- Enriches trace context and Sentry with user information
- Passes user/session to downstream handlers
The
role="user"simply means "authenticated user required" (any role passes), which aligns with usage inapps/api/src/routers/databases.tsandapps/api/src/routers/migrations.ts.apps/api/src/routers/databases.ts (1)
9-29: LGTM! Clean migration to Elysia for the GET /user endpoint.The route correctly uses the
betterAuthGuardmiddleware and route-level authentication. The error handling withstatus(404, ...)is appropriate for the Elysia framework.apps/api/src/routers/migrations.ts (3)
8-31: LGTM! Good use of admin-level authentication for migration registration.The route correctly restricts access to admin users and uses Zod for body validation. The error handling with a 400 status for insert failures is appropriate.
32-48: LGTM! Clean implementation of version retrieval.Returning
{ version: 0 }when no migrations exist is a sensible default for new databases.
49-82: LGTM! Migration verification logic is correct.The
as constassertions properly narrow the status type for type-safe client consumption. The logic correctly identifies required migrations and returns appropriate responses.
| const { mutate } = useMutation({ | ||
| ...trpcNew.migrations.registerSchema.mutationOptions(), | ||
| mutationFn: async ( | ||
| data: Parameters<typeof api.migrations.register.post>[0], | ||
| ) => { | ||
| const { data: result, error } = await api.migrations.register.post(data); | ||
|
|
||
| switch (error?.status) { | ||
| case 401: | ||
| case 403: | ||
| toast({ | ||
| title: t`Failed to upload migration`, | ||
| description: t`You do not have access to upload schema migrations.`, | ||
| }); | ||
| break; | ||
|
|
||
| case 400: | ||
| case 422: | ||
| toast({ | ||
| title: t`Failed to upload migration`, | ||
| description: t`There was an error uploading your SQL migration`, | ||
| }); | ||
| break; | ||
| } | ||
|
|
||
| if (error) throw error; | ||
| return result; | ||
| }, |
There was a problem hiding this comment.
Incomplete error handling for non-HTTP and server errors.
The error handling only covers specific HTTP status codes (401/403, 400/422) but doesn't handle:
- Network errors (no status property)
- Server errors (5xx status codes)
- Other client errors (404, 409, etc.)
Users may encounter unhandled errors with no feedback, degrading the UX.
🔎 Proposed fix to add comprehensive error handling
mutationFn: async (
data: Parameters<typeof api.migrations.register.post>[0],
) => {
const { data: result, error } = await api.migrations.register.post(data);
switch (error?.status) {
case 401:
case 403:
toast({
title: t`Failed to upload migration`,
description: t`You do not have access to upload schema migrations.`,
});
break;
case 400:
case 422:
toast({
title: t`Failed to upload migration`,
description: t`There was an error uploading your SQL migration`,
});
break;
+
+ default:
+ if (error) {
+ toast({
+ title: t`Failed to upload migration`,
+ description: t`An unexpected error occurred. Please try again.`,
+ });
+ }
+ break;
}
if (error) throw error;
return result;
},🤖 Prompt for AI Agents
In apps/web/src/components/features/settings/AdminSettingsCardSection.tsx around
lines 36 to 62, the mutation only handles a few HTTP statuses and ignores
network errors, 5xx server errors, and other status codes; update the
switch/error handling to: detect if error is falsy and return result normally,
if error.status is undefined treat as a network error and show a toast like
"Network error: please check your connection" (include error.message if
present), handle 5xx with a server error toast, handle other/unexpected status
codes with a generic failure toast that includes status and message when
available, ensure you still throw the error after showing a toast and optionally
log full error details to console or telemetry for debugging.
| import { treaty } from "@elysiajs/eden"; | ||
| import type { App } from "../../../api/src/index"; | ||
| import { TRACE_ID_HEADER, generateTraceId } from "./utils"; | ||
|
|
||
| export const api = treaty<App>(import.meta.env.VITE_API_BASE_URL, { | ||
| fetch: { | ||
| credentials: "include", | ||
| }, | ||
| headers: () => ({ | ||
| [TRACE_ID_HEADER]: generateTraceId(), | ||
| }), | ||
| }); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Check for VITE_API_BASE_URL usage and documentation
rg "VITE_API_BASE_URL" --type ts --type tsx --type md -iRepository: Shunseii/bahar
Length of output: 85
🏁 Script executed:
# Check for .env example files
fd -t f "\.env" | head -20Repository: Shunseii/bahar
Length of output: 40
🏁 Script executed:
# Check if the utils file exists and what it exports
cat apps/web/src/lib/utils.ts 2>/dev/null || echo "File not found"Repository: Shunseii/bahar
Length of output: 4321
🏁 Script executed:
# Look for environment variable documentation
find . -name "*.md" -type f | xargs rg -l "VITE_API_BASE_URL|environment|.env" 2>/dev/null | head -10Repository: Shunseii/bahar
Length of output: 140
🏁 Script executed:
# Search for VITE_API_BASE_URL across all files (without file type limitation)
rg "VITE_API_BASE_URL"Repository: Shunseii/bahar
Length of output: 307
🏁 Script executed:
# Check the main README for environment variable documentation
cat README.md 2>/dev/null | head -100Repository: Shunseii/bahar
Length of output: 3405
🏁 Script executed:
# Check web app README for setup instructions
cat apps/web/README.md 2>/dev/nullRepository: Shunseii/bahar
Length of output: 1750
🏁 Script executed:
# Look for vite configuration files
fd -t f "vite\.config\.(ts|js)"Repository: Shunseii/bahar
Length of output: 81
🏁 Script executed:
# Check for .env.example or .env.local files
fd -t f "\.(env|config)" | grep -E "\.(env|example)"Repository: Shunseii/bahar
Length of output: 40
🏁 Script executed:
# Check vite.config.ts
cat apps/web/vite.config.tsRepository: Shunseii/bahar
Length of output: 1846
🏁 Script executed:
# Search for all variations of the API base URL env var name
rg "VITE_API" apps/web/src/Repository: Shunseii/bahar
Length of output: 307
🏁 Script executed:
# Check if there's any .env.example or documentation about setup
fd -type f -name "*env*" -o -name "*.md" | xargs rg -l "VITE_API" 2>/dev/nullRepository: Shunseii/bahar
Length of output: 343
🏁 Script executed:
# Check for any infisical or deployment docs that might clarify the env var name
rg "API_BASE_URL|API_URL" --type-list | head -20Repository: Shunseii/bahar
Length of output: 447
🏁 Script executed:
# Look at router.ts and auth-client.ts to see full context of usage
sed -n '1,20p' apps/web/src/router.tsRepository: Shunseii/bahar
Length of output: 594
🏁 Script executed:
# Check if there's an .env.example or similar
fd "example\|sample\|template" -type f | grep -i envRepository: Shunseii/bahar
Length of output: 228
🏁 Script executed:
# Search for environment variable documentation more broadly
rg "VITE_API" --no-headingRepository: Shunseii/bahar
Length of output: 361
🏁 Script executed:
# Check the Getting Started section more carefully
cat README.md | grep -A 20 "Getting Started"Repository: Shunseii/bahar
Length of output: 633
🏁 Script executed:
# Look for any github workflows or CI/CD that might document env vars
fd -type f "\.yml\|\.yaml" | xargs rg "VITE_API" 2>/dev/nullRepository: Shunseii/bahar
Length of output: 549
Fix documentation: the environment variable should be VITE_API_BASE_URL, not VITE_API_URL.
The web app README documents VITE_API_URL as a required environment variable, but the code consistently uses VITE_API_BASE_URL across api.ts, auth-client.ts, and router.ts. Update the README to reflect the correct variable name.
The utility imports (TRACE_ID_HEADER and generateTraceId) are correctly exported and the treaty configuration itself is sound.
🤖 Prompt for AI Agents
In apps/web/src/lib/api.ts around lines 1 to 12, the code uses VITE_API_BASE_URL
but the README documents VITE_API_URL; update the README (and any other docs) to
reference VITE_API_BASE_URL instead of VITE_API_URL so the documented env var
matches the code (also scan auth-client.ts and router.ts to ensure documentation
matches their use of VITE_API_BASE_URL).
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
bahar-marketing | 10e366d | Commit Preview URL | Dec 27 2025, 04:58 AM |
Summary by CodeRabbit
New Features
Documentation
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.