docs(config): finish #933 — kill BACKEND_URL stragglers + document runtime precedence#1042
Conversation
Wraps services/backendUrl#getBackendUrl in a small React hook so components can read the core-derived API URL (resolved at runtime via openhuman.config_resolve_api_url) without importing the build-time BACKEND_URL constant. Returns null while the resolution is in flight or if it fails so callers render a placeholder rather than guessing a hardcoded host. Refs tinyhumansai#933.
…_url Adds Vitest coverage for services/backendUrl#getBackendUrl: the Tauri happy-path that pulls api_url from openhuman.config_resolve_api_url, trailing-slash trimming, in-process caching, the camelCase apiUrl alias, and the empty-response refusal that prevents callers from silently using a stale fallback. Refs tinyhumansai#933.
WebhooksDebugPanel and TunnelList previously imported the build-time BACKEND_URL constant from utils/config and short-circuited to 'https://api.tinyhumans.ai' when it was empty, so the rendered tunnel ingress URLs ignored whatever core sidecar the user pointed the app at on the login screen. Switch both components to useBackendUrl() so the URL the core resolves over JSON-RPC is the one shown in the UI, and surface a 'Resolving backend URL…' placeholder while the lookup is in flight. Refs tinyhumansai#933.
Spells out the runtime precedence chain for the core RPC URL (login-screen field > Tauri core_rpc_url command > VITE_OPENHUMAN_CORE_RPC_URL > hardcoded default) and clarifies that VITE_BACKEND_URL is a web-only fallback once desktop builds derive api_url from the core via openhuman.config_resolve_api_url. Updates app/.env.example, docs/src/01-architecture.md, and docs/src/08-hooks-utils.md so contributors know to call useBackendUrl() or getBackendUrl() instead of importing the build-time BACKEND_URL constant. Logs the migration in CHANGELOG.md under the existing tinyhumansai#933 entry. Refs tinyhumansai#933.
|
Warning Rate limit exceeded
To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe changes implement runtime backend URL resolution by introducing a Changes
Sequence DiagramsequenceDiagram
actor User
participant Component as WebhooksDebugPanel<br/>TunnelList
participant Hook as useBackendUrl
participant Service as getBackendUrl
participant Tauri as Tauri IPC
participant Core as Rust Core
participant Web as Web API
User->>Component: Load component
Component->>Hook: Call useBackendUrl()
Hook->>Service: Call getBackendUrl()
Service->>Tauri: Invoke config_resolve_api_url
Tauri->>Core: Request api_url from config
Core-->>Tauri: Return api_url
Tauri-->>Service: Return response
Service->>Service: Cache result
Service-->>Hook: Return backend URL
Hook->>Component: Update with resolved URL
Component->>Web: Render with live backend URL
Component-->>User: Display webhook ingress URLs
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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. Review rate limit: 0/1 reviews remaining, refill in 32 minutes and 14 seconds.Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
app/src/services/__tests__/backendUrl.test.ts (1)
21-64: ⚡ Quick winAdd coverage for the non-Tauri fallback path.
This suite exercises the RPC-backed Tauri branch thoroughly, but the new contract also depends on the web-only fallback when
isTauri()is false. A test here would keep Storybook/web-preview behavior from regressing.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src/services/__tests__/backendUrl.test.ts` around lines 21 - 64, Add a test that covers the non-Tauri fallback path by setting hoisted.isTauriMock.mockReturnValue(false) and verifying getBackendUrl (loaded via loadFreshModule) returns the expected fallback value (e.g., process.env or hardcoded fallback used by the module) and that hoisted.callCoreRpcMock is not called; place this alongside the existing tests and mirror patterns used in the suite (use hoisted.callCoreRpcMock.mockReset() in beforeEach) so the web-only branch of getBackendUrl is exercised and protected from regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/src/hooks/useBackendUrl.test.ts`:
- Around line 34-51: The test currently uses a fixed sleep (setTimeout) after
resolving the deferred mock promise which is flaky; instead, after calling
resolveFn?.('https://api.example.com'), immediately flush pending microtasks by
awaiting a resolved promise (e.g. await Promise.resolve()) or wrapping that in
testing-library's act (e.g. await act(() => Promise.resolve())) so the hook's
async resolution runs before asserting result.current; update the test that uses
mockGetBackendUrl, resolveFn, renderHook(() => useBackendUrl()), unmount(), and
result.current to replace the setTimeout wait with a microtask flush.
In `@CHANGELOG.md`:
- Around line 27-29: Update the CHANGELOG.md entry so the test-coverage bullet
lists both added tests: services/__tests__/backendUrl.test.ts and
hooks/useBackendUrl.test.ts; locate the existing bullet that mentions
services/__tests__/backendUrl.test.ts and append or replace it with a single
line that names both files (e.g., "Added services/__tests__/backendUrl.test.ts
and hooks/useBackendUrl.test.ts covering...") so the changelog accurately
reflects shipped coverage.
---
Nitpick comments:
In `@app/src/services/__tests__/backendUrl.test.ts`:
- Around line 21-64: Add a test that covers the non-Tauri fallback path by
setting hoisted.isTauriMock.mockReturnValue(false) and verifying getBackendUrl
(loaded via loadFreshModule) returns the expected fallback value (e.g.,
process.env or hardcoded fallback used by the module) and that
hoisted.callCoreRpcMock is not called; place this alongside the existing tests
and mirror patterns used in the suite (use hoisted.callCoreRpcMock.mockReset()
in beforeEach) so the web-only branch of getBackendUrl is exercised and
protected from regressions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6c8f9c92-ea16-4195-9b83-6ce5c94044c0
📒 Files selected for processing (9)
CHANGELOG.mdapp/.env.exampleapp/src/components/settings/panels/WebhooksDebugPanel.tsxapp/src/components/webhooks/TunnelList.tsxapp/src/hooks/useBackendUrl.test.tsapp/src/hooks/useBackendUrl.tsapp/src/services/__tests__/backendUrl.test.tsdocs/src/01-architecture.mddocs/src/08-hooks-utils.md
- Replace `setTimeout(10)` with `await Promise.resolve()` - Hook's `.then` cancel path runs on the microtask queue, so a flush is enough; drops a 10ms wall-clock wait and removes timing flake.
…verage - Test-coverage bullet now names both files added in this PR (`backendUrl.test.ts` + `useBackendUrl.test.ts`) instead of just the resolver test.
Summary
useBackendUrlReact hook + matching unit tests so components resolve the API URL at runtime fromopenhuman.config_resolve_api_urlinstead of the build-timeBACKEND_URLconstant.BACKEND_URLconsumers (WebhooksDebugPanel,TunnelList) off the build-time short-circuit so the URLs they render reflect whichever core sidecar the user picked on the login screen.core_rpc_url→VITE_*→ hardcoded default) and the new "use the hook, not the constant" rule inapp/.env.example,docs/src/01-architecture.md, anddocs/src/08-hooks-utils.md.Problem
PR #948 already shipped most of the umbrella (#933): the login-screen RPC URL field, persistence,
coreRpcClientcache, andservices/backendUrl#getBackendUrlcallingopenhuman.config_resolve_api_url. The remaining acceptance criteria were:app/src/components/settings/panels/WebhooksDebugPanel.tsx:19andapp/src/components/webhooks/TunnelList.tsx:57— still imported the build-timeBACKEND_URLsynchronously and short-circuited tohttps://api.tinyhumans.aiwhen it was empty. That bypassed the runtime resolver, so a self-hosted user pointing the app at a custom sidecar would still see the canonical hostnames in the webhook panels.BACKEND_URLwas build-time-only and that runtime callers must usegetBackendUrl().services/backendUrlresolver — easy for a future refactor to silently break theconfig_resolve_api_urlhappy path.Solution
app/src/hooks/useBackendUrl.tswrapsgetBackendUrl()in a tiny hook that returnsnullwhile the resolution is in flight or if it fails. Components render aResolving backend URL…placeholder rather than guessing a hardcoded host.WebhooksDebugPanelandTunnelListswap to the hook and gate the rendered ingress URL + Copy button on the resolved value, dropping theBACKEND_URLimport +https://api.tinyhumans.aifallback entirely.app/src/services/__tests__/backendUrl.test.tsexercises the realservices/backendUrl(it's globally mocked inapp/src/test/setup.ts, so the suite usesvi.unmockto opt out): Tauri happy-path againstopenhuman.config_resolve_api_url, trailing-slash trim, in-process cache, theapiUrlcamelCase alias, and the empty-response refusal that stops callers silently using a stale fallback.Submission Checklist
app/src/hooks/useBackendUrl.test.ts(3 cases: resolve, failure, unmount-safety) andapp/src/services/__tests__/backendUrl.test.ts(4 cases: happy path, cache, empty refusal,apiUrlalias). Full Vitest suite green: 1042 passed / 4 skipped / 1 todo.tests/json_rpc_e2e.rscoverage ofopenhuman.config_resolve_api_urlis sufficient.useBackendUrlcarries a JSDoc that explains whynullis the in-flight signal and that the underlying resolver caches.vi.unmock('../backendUrl')line in the new test, since the global setup mock is otherwise non-obvious.Impact
webFallbackBackendUrlthatgetBackendUrlalready uses).openhuman.config_resolve_api_url.VITE_BACKEND_URLis now documented as a web-only fallback. Existing local dev keeps working because the hook falls through to the same value when not running in Tauri.Related
config_resolve_api_urlplumbing)Summary by CodeRabbit
New Features
Bug Fixes
Documentation