-
Notifications
You must be signed in to change notification settings - Fork 177
feat: add ERD demo page for pre-parsed schema JSON #3703
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
Add /erd/demo/[...slug] route that displays pre-parsed schema JSON from GitHub URLs. Unlike /erd/p which parses raw schema files, /erd/demo expects JSON that matches the Schema type and validates it with valibot. Features: - Fetch JSON from GitHub URLs (converts blob URLs to raw URLs) - Validate against schemaSchema - Error handling for network, JSON parsing, and validation failures - Share ERDViewer component with /erd/p route 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughAdds a new ERD demo Next.js page that resolves a content URL, fetches JSON, validates it against a schema, handles errors, and renders an ERD viewer with cookie-derived UI state and metadata. Also introduces three JSON schema fixtures representing complex database schemas for testing. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as User Browser
participant R as Next.js Route Page
participant UR as URL Resolver
participant F as Fetch
participant JP as JSON Parser
participant SV as Schema Validator
participant CK as Cookie Store
participant V as ERDViewer
U->>R: Navigate to /erd/demo/[...slug]
R->>CK: Read cookies (sidebar, panellayout)
R->>UR: Build and resolve content URL
alt Valid content URL
R->>F: fetch(contentUrl, { cache: "no-store" })
alt 200 OK
F-->>R: Response
R->>JP: Parse JSON
alt JSON parsed
R->>SV: Validate against schemaSchema
alt Valid schema
R->>V: Render ERDViewer(schema, uiState)
else ValidationError
R->>V: Render ERDViewer(empty, errors=[ValidationError])
end
else ParseError
R->>V: Render ERDViewer(empty, errors=[ParseError])
end
else NetworkError/Non-OK
R->>V: Render ERDViewer(empty, errors=[NetworkError])
end
else Invalid URL
R->>V: Render ERDViewer(empty, errors=[InvalidURL])
end
note over R,V: Metadata generated from slug (title, OG)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 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 |
Updates to Preview Branch (show-erd) ↗︎
Tasks are run on every commit but only new migration files are pushed.
View logs for this Workflow Run ↗︎. |
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
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
frontend/apps/app/app/erd/demo/[...slug]/page.tsx
(1 hunks)pm-testcases-after.json
(1 hunks)pm-testcases-before.json
(1 hunks)pm-testcases-case-001.json
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Name React component files in PascalCase and use TSX (e.g., App.tsx)
Prefix event handler functions with “handle” (e.g., handleClick)
Files:
frontend/apps/app/app/erd/demo/[...slug]/page.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript/TSX across the codebase
**/*.{ts,tsx}
: Prefer early returns for readability
Use named exports only (no default exports)
Prefer const arrow functions over function declarations for simple utilities (e.g., const toggle = () => {})
Files:
frontend/apps/app/app/erd/demo/[...slug]/page.tsx
frontend/apps/**
📄 CodeRabbit inference engine (AGENTS.md)
Next.js apps live under frontend/apps; target app-specific scripts and configs there
Files:
frontend/apps/app/app/erd/demo/[...slug]/page.tsx
frontend/apps/**/app/**/page.tsx
📄 CodeRabbit inference engine (CLAUDE.md)
Do not implement page logic directly in page.tsx; create separate page components
Files:
frontend/apps/app/app/erd/demo/[...slug]/page.tsx
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Follow existing import patterns and tsconfig path aliases
Files:
frontend/apps/app/app/erd/demo/[...slug]/page.tsx
frontend/apps/**/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
frontend/apps/**/app/**/*.{ts,tsx}
: Use Server Components for server-side data fetching
Do client-side data fetching only when necessary
Align data fetching responsibilities with component roles
Use Server Actions for all data mutations (create/update/delete)
Files:
frontend/apps/app/app/erd/demo/[...slug]/page.tsx
🧬 Code graph analysis (1)
frontend/apps/app/app/erd/demo/[...slug]/page.tsx (1)
frontend/apps/app/app/erd/p/[...slug]/erdViewer.tsx (1)
ERDViewer
(23-59)
⏰ 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). (4)
- GitHub Check: frontend-lint
- GitHub Check: frontend-ci
- GitHub Check: security-review
- GitHub Check: Supabase Preview
const resolveContentUrl = (url: string): string | undefined => { | ||
try { | ||
const parsedUrl = new URL(url) | ||
|
||
if (parsedUrl.hostname === 'github.com' && url.includes('/blob/')) { | ||
return url | ||
.replace('github.com', 'raw.githubusercontent.com') | ||
.replace('/blob', '') | ||
} | ||
|
||
return url | ||
} catch { | ||
return undefined | ||
} | ||
} |
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.
Block SSRF by allowlisting trusted hosts
resolveContentUrl
currently returns any https://${joinedPath}
that a visitor supplies. Because the slug comes straight from the request path, an attacker can coerce the server into fetching arbitrary HTTPS endpoints (e.g. internal control planes or metadata services), which is a classic SSRF vector. Please harden this by restricting outbound fetches to the small set of hosts we trust (e.g. GitHub blob/raw) and reject everything else.
+const ALLOWED_SCHEMA_HOSTS = new Set([
+ 'github.com',
+ 'raw.githubusercontent.com',
+ 'gist.githubusercontent.com',
+])
+
const resolveContentUrl = (url: string): string | undefined => {
try {
const parsedUrl = new URL(url)
+ if (parsedUrl.protocol !== 'https:' || !ALLOWED_SCHEMA_HOSTS.has(parsedUrl.hostname)) {
+ return undefined
+ }
+
if (parsedUrl.hostname === 'github.com' && url.includes('/blob/')) {
return url
.replace('github.com', 'raw.githubusercontent.com')
.replace('/blob', '')
}
- return url
+ return parsedUrl.toString()
} catch {
return undefined
}
}
📝 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.
const resolveContentUrl = (url: string): string | undefined => { | |
try { | |
const parsedUrl = new URL(url) | |
if (parsedUrl.hostname === 'github.com' && url.includes('/blob/')) { | |
return url | |
.replace('github.com', 'raw.githubusercontent.com') | |
.replace('/blob', '') | |
} | |
return url | |
} catch { | |
return undefined | |
} | |
} | |
const ALLOWED_SCHEMA_HOSTS = new Set([ | |
'github.com', | |
'raw.githubusercontent.com', | |
'gist.githubusercontent.com', | |
]) | |
const resolveContentUrl = (url: string): string | undefined => { | |
try { | |
const parsedUrl = new URL(url) | |
if (parsedUrl.protocol !== 'https:' || !ALLOWED_SCHEMA_HOSTS.has(parsedUrl.hostname)) { | |
return undefined | |
} | |
if (parsedUrl.hostname === 'github.com' && url.includes('/blob/')) { | |
return url | |
.replace('github.com', 'raw.githubusercontent.com') | |
.replace('/blob', '') | |
} | |
return parsedUrl.toString() | |
} catch { | |
return undefined | |
} | |
} |
Issue
Why is this change needed?
Add a new
/erd/demo/[...slug]
route that displays pre-parsed schema JSON from GitHub URLs.Unlike
/erd/p
which parses raw schema files (SQL, Prisma, etc.),/erd/demo
expects JSON that already matches theSchema
type and validates it using valibot'sschemaSchema
.Summary
/erd/demo/[...slug]
page componentschemaSchema
using valibotERDViewer
component from/erd/p
routeTest plan
/erd/demo/[github-url-to-schema-json]
and verify ERD is displayed🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests