feat(apps/ensadmin): add interactive REST API playground to ENSAdmin#1951
feat(apps/ensadmin): add interactive REST API playground to ENSAdmin#1951
Conversation
…t`) powered by Scalar, loading the OpenAPI spec from the connected ENSApi instance. Introduced `@ensnode/scalar-react` wrapper package.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
🦋 Changeset detectedLatest commit: ba62521 The changes in this PR will be included in the next version bump. This PR includes changesets to release 24 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 45 minutes and 57 seconds. ⌛ 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: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughAdds an interactive REST API Reference at /api/rest in ENSAdmin using a new Changes
Sequence Diagram(s)sequenceDiagram
participant Browser
participant ENSAdmin as ENSAdmin (client page)
participant ENSApi as ENSApi (server /openapi.json)
participant Scalar as Scalar UI (ApiReferenceReact)
Browser->>ENSAdmin: navigate to /api/rest
ENSAdmin->>ENSAdmin: useValidatedSelectedConnection(), useOpenApiUrl()
ENSAdmin->>ENSApi: GET /openapi.json (computed URL)
ENSApi-->>ENSAdmin: OpenAPI JSON URL / spec
ENSAdmin->>Scalar: render ScalarApiReference with url + serverUrl
Scalar-->>Browser: interactive API playground UI
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 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. Comment |
There was a problem hiding this comment.
Pull request overview
Adds an interactive REST API playground to ENSAdmin by introducing an ENSNode-themed wrapper around Scalar’s React API Reference component and wiring it into the ENSAdmin navigation and route structure.
Changes:
- Introduces new workspace package
@ensnode/scalar-reactwrapping@scalar/api-reference-reactwith ENSNode styling defaults. - Adds
/api/restpage (plus breadcrumb/actions parallel routes + loading state) to render Scalar against the connected ENSApi’s/openapi.json. - Exposes the new page via the ENSAdmin sidebar and gates it behind a new
restApifeature flag.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds Scalar + transitive dependencies required for the REST API reference UI. |
| packages/scalar-react/package.json | Defines new @ensnode/scalar-react package metadata and dependencies. |
| packages/scalar-react/tsup.config.ts | Adds build config for the new wrapper package. |
| packages/scalar-react/tsconfig.json | Adds TypeScript config for the new wrapper package. |
| packages/scalar-react/src/index.ts | Exposes the wrapper component entrypoint. |
| packages/scalar-react/src/api-reference.tsx | Implements the Scalar wrapper + ENSNode-themed defaults. |
| apps/ensadmin/package.json | Adds dependency on @ensnode/scalar-react. |
| apps/ensadmin/src/hooks/active/use-ensadmin-features.tsx | Adds restApi feature status used for gating the new page. |
| apps/ensadmin/src/components/app-sidebar.tsx | Adds “REST API Reference” nav item under APIs. |
| apps/ensadmin/src/app/api/rest/page.tsx | New REST API reference page loading /openapi.json from the selected connection. |
| apps/ensadmin/src/app/api/rest/loading.tsx | Loading state for the new route. |
| apps/ensadmin/src/app/@breadcrumbs/(apis)/api/rest/page.tsx | Breadcrumb slot content for the new page. |
| apps/ensadmin/src/app/@actions/api/rest/page.tsx | Actions slot (copy OpenAPI URL) for the new page. |
| .changeset/tangy-pants-camp.md | Changeset entry describing the feature addition. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
One remaining UX issue I need to resolve with this is when you scroll it has a sticky container so the header moves. I'll try modify the class for the docs/playground area so it sits within the normal scrollable |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/ensadmin/src/app/`@actions/api/rest/page.tsx:
- Around line 10-14: Extract the duplicated URL derivation into a shared hook
named useOpenApiUrl that calls useValidatedSelectedConnection and returns
useMemo(() => new URL("/openapi.json", selectedConnection).toString(),
[selectedConnection]); colocate the new hook with the REST feature (e.g.,
hooks/active) and then replace the inline useMemo in both
useValidatedSelectedConnection call sites (the components referencing the exact
expression in `@actions/api/rest/page.tsx` and api/rest/page.tsx) to instead call
useOpenApiUrl().
In `@packages/scalar-react/package.json`:
- Line 31: Replace the deprecated "prepublish" script in package.json with an
explicit "build" script and add a "prepack" script that invokes it: remove the
"prepublish": "tsup" entry, add "build": "tsup" and add "prepack": "npm run
build" so packaging/publishing reliably runs the build step; ensure you update
any CI/publish docs that referenced "prepublish".
- Around line 20-25: The exports object in package.json currently lists the
"default" condition before "types", which causes Node's condition-resolution to
pick "default" and skip the "types" entry; update the exports "." entry so the
"types" key appears before "default" (i.e., reorder the keys under "exports" ->
"." to place "types" first) to ensure TypeScript moduleResolution
(bundler/node16/nodenext) can find the declared types.
In `@packages/scalar-react/src/api-reference.tsx`:
- Around line 27-47: Replace the typeof window check in ScalarApiReference with
the project's useHydrated hook: import useHydrated from "@/hooks/use-hydrated",
call const hydrated = useHydrated() inside the ScalarApiReference function and
return null when !hydrated; keep the configuration object and the
ApiReferenceReact render (configuration and ApiReferenceReact identifiers remain
unchanged) so the component renders consistently between server and client and
avoids hydration mismatch.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5957238b-9a9d-4b2a-bc0e-e4025d0a63ef
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (13)
.changeset/tangy-pants-camp.mdapps/ensadmin/package.jsonapps/ensadmin/src/app/@actions/api/rest/page.tsxapps/ensadmin/src/app/@breadcrumbs/(apis)/api/rest/page.tsxapps/ensadmin/src/app/api/rest/loading.tsxapps/ensadmin/src/app/api/rest/page.tsxapps/ensadmin/src/components/app-sidebar.tsxapps/ensadmin/src/hooks/active/use-ensadmin-features.tsxpackages/scalar-react/package.jsonpackages/scalar-react/src/api-reference.tsxpackages/scalar-react/src/index.tspackages/scalar-react/tsconfig.jsonpackages/scalar-react/tsup.config.ts
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 15 changed files in this pull request and generated 2 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/scalar-react/src/api-reference.tsx (1)
53-70:⚠️ Potential issue | 🟠 MajorUse a mount guard instead of
typeof windowfor Scalar.Line 54 can hydrate as
nullon the server but as the full Scalar tree on the first browser render. Keep the first client render identical, then mount Scalar after hydration.🐛 Proposed fix
+import { useEffect, useState } from "react"; import { ApiReferenceReact, type ReferenceProps } from "@scalar/api-reference-react"; import "@scalar/api-reference-react/style.css"; @@ export function ScalarApiReference({ url, serverUrl }: ScalarApiReferenceProps) { - if (typeof window === "undefined") return null; + const [isMounted, setIsMounted] = useState(false); + + useEffect(() => { + setIsMounted(true); + }, []); + + if (!isMounted) return null; const configuration: NonNullable<ReferenceProps["configuration"]> = {Scalar’s React integration docs describe the wrapper as client-side and call out SSR/SSG caveats: https://scalar.com/products/api-references/integrations/react
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/scalar-react/src/api-reference.tsx` around lines 53 - 70, The current server/client guard in ScalarApiReference uses typeof window and can cause a hydration mismatch; replace it with a mount guard inside the component: add a mounted state (e.g., useState(false)) and set it to true in useEffect(() => setMounted(true), []), return null while !mounted, and only render ApiReferenceReact after mounted; keep the existing configuration object (configuration) and all props (url, serverUrl) unchanged and ensure React plus useState/useEffect are imported so the first client render matches the server render.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/ensadmin/src/app/`@actions/api/rest/page.tsx:
- Around line 12-20: The URL span can grow indefinitely in the flex row; update
the container div (the element rendering the URL and CopyButton) to include
"min-w-0" and make the URL span (the element rendering {url}) use truncation
classes (e.g., add "truncate" and keep "overflow-hidden" if needed) so long
OpenAPI/local URLs are ellipsized instead of pushing the CopyButton; optionally
add a title attribute to the span to surface the full URL on hover.
In `@packages/scalar-react/src/api-reference.tsx`:
- Around line 16-31: The CUSTOM_CSS currently hardcodes a 4rem header and forces
an internal scroll (see .references-layout, .references-rendered,
.references-navigation-list) which makes Scalar own page layout; remove the
calc(100svh - 4rem) usage and the forced overflow-y:auto and instead let the
component inherit height from its parent (use height: 100% / max-height: 100% or
unset those rules) so the ENSAdmin route container can control header height and
global scrolling; update the CUSTOM_CSS constant to drop those hard-coded
size/scroll rules and rely on parent-provided sizing, and document in the
component README that the parent must provide the available height or scrolling
container.
---
Duplicate comments:
In `@packages/scalar-react/src/api-reference.tsx`:
- Around line 53-70: The current server/client guard in ScalarApiReference uses
typeof window and can cause a hydration mismatch; replace it with a mount guard
inside the component: add a mounted state (e.g., useState(false)) and set it to
true in useEffect(() => setMounted(true), []), return null while !mounted, and
only render ApiReferenceReact after mounted; keep the existing configuration
object (configuration) and all props (url, serverUrl) unchanged and ensure React
plus useState/useEffect are imported so the first client render matches the
server render.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: d1b33048-79c9-4daa-9278-28b31235351c
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
apps/ensadmin/src/app/@actions/api/rest/page.tsxapps/ensadmin/src/app/api/rest/page.tsxapps/ensadmin/src/components/header.tsxapps/ensadmin/src/hooks/active/use-openapi-url.tspackages/scalar-react/package.jsonpackages/scalar-react/src/api-reference.tsx
|
@copilot resolve the merge conflicts in this pull request |
Greptile SummaryThis PR adds an interactive REST API playground at Confidence Score: 5/5Safe to merge — no logic or data-integrity issues found. All findings are P2 (style/best-practice) suggestions. The feature gating, URL construction, routing slots, and global header change are all correctly implemented and follow existing patterns. packages/scalar-react/src/api-reference.tsx — minor: Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User visits /api/rest] --> B[RequireENSAdminFeature\nfeature=restApi]
B --> C{configQuery status}
C -- pending --> D[Show loading spinner]
C -- error --> E[Show error card]
C -- success --> F[restApi = supported]
F --> G[RestApiPage]
G --> H[useOpenApiUrl\nnew URL /openapi.json, connection]
G --> I[useValidatedSelectedConnection]
H --> J[ScalarApiReference\nurl, serverUrl]
I --> J
J --> K[ApiReferenceReact\nVue-under-the-hood\nfetches OpenAPI spec]
K --> L[Interactive REST playground]
Reviews (1): Last reviewed commit: "apply code suggestions" | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 15 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot resolve the merge conflicts in this pull request |
Lite PR
Summary
@ensnode/scalar-reactwrapper package around@scalar/api-reference-reactwith ENSNode-themed styling defaults/api/restpage in ENSAdmin that renders an interactvie REST API playground powered by the connected ENSApi instance's/openapi.jsonWhy
Testing
pnpm buildsucceeds with/api/restin the route tableapi/graphqlerrors remain)/api/rest?connection=https://api.alpha.ensnode.iowith HTTP 200Notes for Reviewer (Optional)
The
restApifeature is gated simply on config loading successfully (no plugin check), since/openapi.jsonis always served by any ENSApi instance (same as other pages)@scalar/api-reference-reactis a Vue-under-the-hood wrapper (it's client-side only, which is fine since the page requires an active connection anyway)The links in the nav are still static, and not dynamic.
Pre-Review Checklist (Blocking)