feat: redesign API reference page#56
Conversation
New api-v2 components replace EndpointPage with read-only view showing field names and types without editable inputs. Playground dialog and navbar actions to follow in subsequent commits. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Layout: flex justify-between with px-32px, matching Figma content node
- ApiLayout: override parent content padding for horizontal control
- Sections: dividers between sections with proper margin
- Fields: Flex gap numbers, Badge micro size, Apsara CopyButton
- Code snippet: custom component with CodeBlock highlighting, language
dropdown via Menu, title in header
- Response panel: custom status tabs (200/400/404/500), CodeBlock for
JSON highlighting, shows {} for responses without examples
- Typography: all using Apsara design tokens and --rs-font-mono
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Read externalDocs URL from OpenAPI operation, fallback to spec level - Preserve externalDocs in Swagger 2.0 → OpenAPI 3.0 conversion - Shared useApiOperation() hook resolves current endpoint from URL - Button shows in navbar only on API endpoint pages with docs URL Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Test request button in navbar opens playground dialog - Split panel: editable fields left, response right - Auth type selector: API Key, Bearer Token, Basic Auth from OpenAPI securitySchemes, fallback to chronicle.yaml auth config - Preserve securityDefinitions in Swagger 2.0 → OpenAPI 3.0 conversion - Send via /api/apis-proxy, shows status + response time - Bottom bar with method badge, path, copy curl, Send button - Dedup auth header from operation header parameters Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add kind field to SchemaField for reliable type detection - Resolve allOf/oneOf/anyOf in flattenSchema for nested objects - Auto-generate operationId for endpoints missing it (method + path) - Array fields: add/remove UI for primitive arrays (string[], number[]) - Object fields: render child fields recursively with indented layout - Reset dialog state on endpoint change via React key - Field list gap and array item alignment fixes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Toggle between form fields and CodeMirror JSON editor via </> icon - Two-way sync between form and JSON views - Response panel dropdown to switch between Body and Headers view - Proxy returns response headers from upstream - Fix JsonEditor cursor reset by using ref for onChange callback Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Removed: endpoint-page, field-section, field-row, key-value-editor, code-snippets, response-panel. Kept: method-badge, json-editor (still used by api-v2 and other components). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Flat tag groups with plain text headers (not collapsible accordions) - Method text right-aligned in mono font with semantic colors - GET=green (success), POST=blue (accent), PUT=yellow, DELETE=red - Active item with neutral background highlight - Consistent method colors across sidebar, method bar, and playground Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ 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: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (18)
📝 WalkthroughWalkthroughThis PR replaces the API documentation and playground UI with a new v2 implementation. It removes legacy ChangesAPI v2 Component Suite
OpenAPI & Schema Infrastructure
UI Integration & Legacy Migration
Sequence DiagramsequenceDiagram
participant User
participant PlaygroundDialog
participant ApiProxyServer
participant UpstreamAPI
User->>PlaygroundDialog: Fill parameters & auth
User->>PlaygroundDialog: Click Send
PlaygroundDialog->>PlaygroundDialog: Resolve path template
PlaygroundDialog->>PlaygroundDialog: Build query string
PlaygroundDialog->>PlaygroundDialog: Merge headers
PlaygroundDialog->>ApiProxyServer: POST /api/apis-proxy {method, path, headers, body}
ApiProxyServer->>UpstreamAPI: Forward request
UpstreamAPI-->>ApiProxyServer: Response {status, headers, body}
ApiProxyServer-->>PlaygroundDialog: {status, statusText, headers, body, responseTime}
PlaygroundDialog->>PlaygroundDialog: Render response
PlaygroundDialog->>User: Display body/headers with status
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
🚥 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)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. 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 |
- Merge method-badge and json-editor into api folder - Remove api-v2 directory, update all imports - Use Flex components for API sidebar nodes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/chronicle/src/lib/schema.ts (1)
76-86:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winValidate schema type before casting to SchemaFieldKind.
Line 79 casts
prop.typetoSchemaFieldKindwithout validation. If the OpenAPI schema contains non-standard or extended types (e.g.,'null', custom types), the cast will succeed but produce an invalidkindvalue that doesn't match the union type at runtime. This could cause downstream UI rendering issues or type guards to fail.🛡️ Proposed fix with validation
+const validKinds: SchemaFieldKind[] = ['string', 'integer', 'number', 'boolean', 'array', 'object'] +function toKind(type: unknown): SchemaFieldKind { + if (typeof type === 'string' && validKinds.includes(type as SchemaFieldKind)) { + return type as SchemaFieldKind + } + return 'object' +} return { name, type: fieldType, - kind: (prop.type as SchemaFieldKind) ?? 'object', + kind: toKind(prop.type), required: required.includes(name), description: rawProp.description ?? prop.description, default: prop.default, enum: prop.enum, children: children?.length ? children : undefined, }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/chronicle/src/lib/schema.ts` around lines 76 - 86, The code currently casts prop.type to SchemaFieldKind directly when building the returned field object (the kind property), which can accept invalid runtime values; change this to validate prop.type against the allowed SchemaFieldKind union before assigning: implement or use a small validator (e.g., isValidSchemaFieldKind) that checks prop.type against the set of permitted kinds and only then set kind = prop.type as SchemaFieldKind, otherwise fall back to 'object' (or another safe default); update the object creation where kind is set (the line using (prop.type as SchemaFieldKind) ?? 'object') to use this validation helper so downstream consumers get only known kinds.
🧹 Nitpick comments (5)
packages/chronicle/src/components/api-v2/api-response-panel.tsx (1)
5-5: 💤 Low valuePrefer repo path alias for consistency with TS/TSX import policy.
Use the
@/*alias instead of a relative path for this import, if CSS-module alias resolution is configured in this workspace.As per coding guidelines,
**/*.{ts,tsx}: Use path alias@/* → ./src/* configured in tsconfig and vite.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/chronicle/src/components/api-v2/api-response-panel.tsx` at line 5, Replace the relative CSS import in the API response panel component with the repo path alias: change the import statement that currently reads "import styles from './api-response-panel.module.css'" in the api-response-panel.tsx module to use the `@/` alias (e.g. import styles from '@/components/api-v2/api-response-panel.module.css') so it follows the project's TypeScript/Vite path-alias convention; ensure the aliased path matches your tsconfig/vite alias mapping and that the file location corresponds to that alias.packages/chronicle/src/components/api-v2/api-field-list.tsx (1)
58-86: 💤 Low valueConsider avoiding non-null assertion operator.
Line 79 uses
field.children!with a non-null assertion. While safe becauseExpandableChildrenis only called whenhasChildrenis true (line 53), TypeScript best practice is to avoid!operators when the type can be narrowed through explicit checks.♻️ Alternative approach
function ExpandableChildren({ field }: { field: SchemaField }) { const [expanded, setExpanded] = useState(false) + if (!field.children || field.children.length === 0) return null return ( <Flex direction="column"> <button type="button" className={styles.expandButton} onClick={() => setExpanded(!expanded)} > <span className={styles.expandLabel}> {expanded ? 'Hide' : 'Show'} child attributes </span> {expanded ? ( <ChevronDownIcon width={16} height={16} /> ) : ( <ChevronRightIcon width={16} height={16} /> )} </button> {expanded && ( <div className={styles.childFields}> - {field.children!.map((child) => ( + {field.children.map((child) => ( <FieldItem key={child.name} field={child} /> ))} </div> )} </Flex> ) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/chronicle/src/components/api-v2/api-field-list.tsx` around lines 58 - 86, The code uses a non-null assertion on field.children in ExpandableChildren; replace it with an explicit type-narrowing check to avoid "!" — for example, at the top of ExpandableChildren return early if (!field.children || field.children.length === 0) return null, or change the JSX to use optional chaining (field.children?.map(...)) inside the expanded block; update the rendering logic around the expanded conditional accordingly so TypeScript knows children is present without using the non-null operator.packages/chronicle/src/components/api-v2/api-overview.tsx (2)
68-103: ⚖️ Poor tradeoffReduce separator logic duplication.
The code repeats separator conditional logic between each section pair (lines 72-74, 80-82, 88-90, 96-98). This violates DRY and makes it harder to reorder or add/remove sections. Consider extracting the sections into an array and rendering separators programmatically between non-empty sections.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/chronicle/src/components/api-v2/api-overview.tsx` around lines 68 - 103, The repeated Separator conditional logic can be removed by building an ordered array of section descriptors (e.g., objects with keys like id/title/component and a predicate based on authFields, pathFields, queryFields, body?.fields.length, responses) and then mapping that array to render only the non-empty sections; between mapped items insert a single Separator (using Separator and styles.divider) for every index > 0, rendering ApiFieldSection for items referencing authFields/pathFields/queryFields/body.fields and ResponseSection for the responses item; update the JSX in api-overview.tsx to compute visibleSections before return and render them in a single map so adding/reordering sections no longer requires duplicated separator conditionals.
158-170: ⚡ Quick winHandle composed schemas in parameter conversion.
The
paramsToFieldsfunction directly readsschema.typewithout applyingmergeAllOfor other composition logic (line 163-164). If an OpenAPI parameter schema usesallOf,oneOf, oranyOfto compose types, the function will fail to extract the correct type and may produce'string'as a fallback even when the composed type is different.This inconsistency with the
flattenSchemaapproach used for request/response bodies could lead to incorrect parameter type displays in the UI.♻️ Proposed fix using existing schema utilities
+import { flattenSchema } from '@/lib/schema' + function paramsToFields(params: OpenAPIV3.ParameterObject[]): SchemaField[] { return params.map((p) => { const schema = (p.schema ?? {}) as OpenAPIV3.SchemaObject + // For simple params, flatten returns a single-item array or empty + const flattened = flattenSchema(schema) + const field = flattened[0] return { name: p.name, - type: schema.type ? String(schema.type) : 'string', - kind: (schema.type as SchemaField['kind']) ?? 'string', + type: field?.type ?? (schema.type ? String(schema.type) : 'string'), + kind: field?.kind ?? ((schema.type as SchemaField['kind']) ?? 'string'), required: p.required ?? false, description: p.description, default: schema.default, } }) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/chronicle/src/components/api-v2/api-overview.tsx` around lines 158 - 170, The paramsToFields function reads p.schema.type directly and doesn't handle composed schemas; fix it by first flattening/merging the parameter schema (e.g., call the existing flattenSchema or mergeAllOf utility on (p.schema ?? {})) and then derive type, kind, default, and description from the flattened schema instead of p.schema; update paramsToFields to use the flattened schema when computing type/kind (falling back to 'string') while preserving required, description, and default values.packages/chronicle/src/components/api-v2/playground-dialog.tsx (1)
346-353: 💤 Low valueConsider notifying user when JSON-to-form sync fails.
When toggling from JSON mode back to form mode, parse errors are silently ignored (line 350). If the user has entered invalid JSON, their edits are lost without feedback. While less critical than request-time errors, a console warning or toast notification would improve the user experience.
ℹ️ Optional enhancement
} else { - try { setBodyValues(JSON.parse(bodyJsonStr)) } catch { /* ignore */ } + try { + setBodyValues(JSON.parse(bodyJsonStr)) + } catch (e) { + console.warn('Failed to parse JSON, keeping previous form values:', e) + } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/chronicle/src/components/api-v2/playground-dialog.tsx` around lines 346 - 353, The JSON->form toggle handler currently swallows parse errors (inside the IconButton onClick) causing user edits to be lost; update the try/catch around JSON.parse(bodyJsonStr) in that click handler to catch the error, surface feedback (e.g., show a toast or call console.warn with the parse error and a user-friendly message referencing bodyJsonStr), and prevent flipping setJsonMode(!jsonMode) when parsing fails so the user remains in JSON mode and retains their edits; use the existing state setters setBodyValues, setBodyJsonStr and jsonMode to implement this behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/chronicle/src/components/api-v2/api-code-snippet.module.css`:
- Around line 27-29: The CSS module is missing explicit Shiki token color
bindings for inline code spans; update the stylesheet to add rules targeting the
code container selector (e.g. .pre code span) to set color via the Shiki tokens
(use --shiki-light for the default/light theme) and add a dark-theme override
(e.g. a [data-theme="dark"] or .dark root selector) that sets .pre code span to
--shiki-dark; keep the selectors scoped to the same module (reference the
existing .body and the code-snippet container) so Shiki-highlighted spans
inherit the correct light/dark colors.
In `@packages/chronicle/src/components/api-v2/api-code-snippet.tsx`:
- Around line 32-35: The memoized `code` uses useMemo with the wrong dependency
(`selected`) causing stale results because the generator comes from `current`;
change the dependency array to include the actual generator source (`current`)
and the other inputs (`method`, `url`, `headers`, `body`) so the memo recomputes
whenever `current` (which is derived from `selected`/`languages`) or any input
changes; update the useMemo call that assigns `code` (currently calling
`current.generate(...)`) to depend on `current`, `method`, `url`, `headers`, and
`body` instead of `selected`.
In `@packages/chronicle/src/components/api-v2/api-overview.tsx`:
- Around line 121-125: ResponseSection should defensively handle an empty
responses array: change the selectedStatus initial state from the hardcoded
'200' to use responses[0]?.status ?? '' (e.g., useState(() =>
responses[0]?.status ?? '')) and compute active with const active =
responses.find(r => r.status === selectedStatus); then keep the early guard if
(!active) return null; this ensures no properties on an undefined active are
accessed when responses is empty while preserving hook usage in ResponseSection
and symbols selectedStatus, setSelectedStatus, active, and responses.
In `@packages/chronicle/src/components/api-v2/api-response-panel.module.css`:
- Around line 76-79: The module is missing explicit Shiki token color rules for
the response code view; update the CSS for the .codeBlock/.pre code elements to
add light and dark Shiki span color bindings (e.g. add rules targeting ".pre
code span" and a dark-mode variant such as ".dark .pre code span" or
":global(.dark) .pre code span") so that each token uses the CSS vars (e.g.
var(--shiki-light) and var(--shiki-dark)); ensure these selectors are placed
alongside the existing .codeBlock rule in api-response-panel.module.css and
cover all span tokens emitted by Shiki.
In `@packages/chronicle/src/components/api-v2/playground-dialog.module.css`:
- Around line 218-220: The .statusValue CSS rule uses a hard-coded hex color
(`#30a46c`); update this to use the Apsara design token pattern (e.g., replace the
hex with var(--rs-color-success) or the appropriate --rs-color-* token) so the
status color follows the design system and supports theming; modify the
.statusValue declaration to reference the chosen --rs-color-* variable instead
of the literal `#30a46c`.
In `@packages/chronicle/src/components/api-v2/playground-dialog.tsx`:
- Around line 125-134: The reset logic inside setBodyValues currently detects
arrays using f.type.endsWith('[]') which is inconsistent with the initial-state
logic that uses f.kind === 'array'; update the reset handler (the block that
iterates body.fields inside setBodyValues) to use the same array detection as
the initializer (use f.kind === 'array', or a unified helper check) so array
fields are initialized and reset to the same shape (empty array) and
object/primitive fields follow the same rules (f.children -> {}, else '').
- Around line 193-197: The curlSnippet useMemo currently always stringifies
bodyValues; update it to respect jsonMode by using bodyJsonStr when jsonMode is
true (and fall back to JSON.stringify(bodyValues) when false) so the generated
cURL matches what handleSend actually sends; also add jsonMode and bodyJsonStr
to the useMemo dependency array so the snippet updates when JSON mode or the raw
JSON body changes. Ensure you modify the generateCurl call inside the useMemo
(curlSnippet) and adjust the dependency list accordingly.
- Around line 29-30: The code uses scheme.name! when building the schemes entry
in the conditional inside the playground dialog; update the guard to ensure
scheme.name is a non-empty string (e.g., check typeof scheme.name === 'string'
&& scheme.name.trim() !== '') before using it, and if it's missing/empty either
skip pushing this scheme or use a safe fallback like 'api_key' (adjust the
schemes.push call that creates { name: `API Key (${scheme.name})`, headerName:
scheme.name, ... } to use the validated value or fallback).
- Around line 160-164: The current jsonMode branch silently swallows JSON.parse
errors and falls back to bodyValues; instead, when parsing bodyJsonStr inside
the jsonMode branch (where reqBody, bodyJsonStr, bodyValues and jsonMode are
used), catch the error, set a visible parse error (e.g., set a local state like
jsonParseError or call the existing UI feedback mechanism/toast) with the
error.message, and prevent sending the request until the user fixes the JSON;
only assign reqBody = JSON.parse(bodyJsonStr) when parsing succeeds.
In `@packages/chronicle/src/lib/api-routes.ts`:
- Around line 10-12: deriveOperationId can produce an empty or colliding ID for
root/empty paths; update the function (deriveOperationId) to sanitize the path
as before but if the result after replacements is empty, substitute a stable
fallback (e.g., "root" or "empty") and return the method + "_" + fallback; also
normalize case (lowercase) and still collapse duplicate underscores so the final
operation id is always non-empty and deterministic.
In `@packages/chronicle/src/lib/openapi.ts`:
- Around line 143-145: The conversion for OAuth2 security schemes currently sets
result[name] = { type: 'oauth2', flows: {} } and drops v2 fields; update the
conversion in the function handling def (the v2 security definition) so you map
v2.flow -> the appropriate OpenAPIv3 flows object (authorizationCode, implicit,
password, clientCredentials), copy authorizationUrl and tokenUrl into the
corresponding flow object, and transfer scopes into flow.scopes; ensure the
created value remains typed as OpenAPIV3.OAuth2SecurityScheme and replace the
empty flows object assigned to result[name] with the fully populated flows
structure derived from def.flow, def.authorizationUrl, def.tokenUrl, and
def.scopes.
In `@packages/chronicle/src/server/api/apis-proxy.ts`:
- Around line 54-61: The proxied response currently echoes all upstream headers
via responseHeaders which can leak sensitive/internal headers; change the header
collection to filter out unsafe headers by using an allowlist (e.g.,
content-type, content-length, cache-control, etag, last-modified,
content-encoding) or at minimum explicitly exclude known unsafe/hop-by-hop
headers (e.g., set-cookie, cookie, connection, transfer-encoding, keep-alive,
proxy-authenticate, proxy-authorization, te, trailers, upgrade and any
infrastructure-specific headers) before populating responseHeaders; update the
code that iterates response.headers (the responseHeaders variable population in
apis-proxy.ts) to only copy allowed headers (or skip the blacklist) so the
returned Response.json contains only safe headers.
---
Outside diff comments:
In `@packages/chronicle/src/lib/schema.ts`:
- Around line 76-86: The code currently casts prop.type to SchemaFieldKind
directly when building the returned field object (the kind property), which can
accept invalid runtime values; change this to validate prop.type against the
allowed SchemaFieldKind union before assigning: implement or use a small
validator (e.g., isValidSchemaFieldKind) that checks prop.type against the set
of permitted kinds and only then set kind = prop.type as SchemaFieldKind,
otherwise fall back to 'object' (or another safe default); update the object
creation where kind is set (the line using (prop.type as SchemaFieldKind) ??
'object') to use this validation helper so downstream consumers get only known
kinds.
---
Nitpick comments:
In `@packages/chronicle/src/components/api-v2/api-field-list.tsx`:
- Around line 58-86: The code uses a non-null assertion on field.children in
ExpandableChildren; replace it with an explicit type-narrowing check to avoid
"!" — for example, at the top of ExpandableChildren return early if
(!field.children || field.children.length === 0) return null, or change the JSX
to use optional chaining (field.children?.map(...)) inside the expanded block;
update the rendering logic around the expanded conditional accordingly so
TypeScript knows children is present without using the non-null operator.
In `@packages/chronicle/src/components/api-v2/api-overview.tsx`:
- Around line 68-103: The repeated Separator conditional logic can be removed by
building an ordered array of section descriptors (e.g., objects with keys like
id/title/component and a predicate based on authFields, pathFields, queryFields,
body?.fields.length, responses) and then mapping that array to render only the
non-empty sections; between mapped items insert a single Separator (using
Separator and styles.divider) for every index > 0, rendering ApiFieldSection for
items referencing authFields/pathFields/queryFields/body.fields and
ResponseSection for the responses item; update the JSX in api-overview.tsx to
compute visibleSections before return and render them in a single map so
adding/reordering sections no longer requires duplicated separator conditionals.
- Around line 158-170: The paramsToFields function reads p.schema.type directly
and doesn't handle composed schemas; fix it by first flattening/merging the
parameter schema (e.g., call the existing flattenSchema or mergeAllOf utility on
(p.schema ?? {})) and then derive type, kind, default, and description from the
flattened schema instead of p.schema; update paramsToFields to use the flattened
schema when computing type/kind (falling back to 'string') while preserving
required, description, and default values.
In `@packages/chronicle/src/components/api-v2/api-response-panel.tsx`:
- Line 5: Replace the relative CSS import in the API response panel component
with the repo path alias: change the import statement that currently reads
"import styles from './api-response-panel.module.css'" in the
api-response-panel.tsx module to use the `@/` alias (e.g. import styles from
'@/components/api-v2/api-response-panel.module.css') so it follows the project's
TypeScript/Vite path-alias convention; ensure the aliased path matches your
tsconfig/vite alias mapping and that the file location corresponds to that
alias.
In `@packages/chronicle/src/components/api-v2/playground-dialog.tsx`:
- Around line 346-353: The JSON->form toggle handler currently swallows parse
errors (inside the IconButton onClick) causing user edits to be lost; update the
try/catch around JSON.parse(bodyJsonStr) in that click handler to catch the
error, surface feedback (e.g., show a toast or call console.warn with the parse
error and a user-friendly message referencing bodyJsonStr), and prevent flipping
setJsonMode(!jsonMode) when parsing fails so the user remains in JSON mode and
retains their edits; use the existing state setters setBodyValues,
setBodyJsonStr and jsonMode to implement this behavior.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 43081ba5-494e-4aaf-a560-0079153fe47c
📒 Files selected for processing (35)
packages/chronicle/src/components/api-v2/api-code-snippet.module.csspackages/chronicle/src/components/api-v2/api-code-snippet.tsxpackages/chronicle/src/components/api-v2/api-field-list.module.csspackages/chronicle/src/components/api-v2/api-field-list.tsxpackages/chronicle/src/components/api-v2/api-overview.module.csspackages/chronicle/src/components/api-v2/api-overview.tsxpackages/chronicle/src/components/api-v2/api-response-panel.module.csspackages/chronicle/src/components/api-v2/api-response-panel.tsxpackages/chronicle/src/components/api-v2/index.tspackages/chronicle/src/components/api-v2/playground-dialog.module.csspackages/chronicle/src/components/api-v2/playground-dialog.tsxpackages/chronicle/src/components/api/code-snippets.module.csspackages/chronicle/src/components/api/code-snippets.tsxpackages/chronicle/src/components/api/endpoint-page.module.csspackages/chronicle/src/components/api/endpoint-page.tsxpackages/chronicle/src/components/api/field-row.module.csspackages/chronicle/src/components/api/field-row.tsxpackages/chronicle/src/components/api/field-section.module.csspackages/chronicle/src/components/api/field-section.tsxpackages/chronicle/src/components/api/index.tspackages/chronicle/src/components/api/json-editor.tsxpackages/chronicle/src/components/api/key-value-editor.module.csspackages/chronicle/src/components/api/key-value-editor.tsxpackages/chronicle/src/components/api/method-badge.tsxpackages/chronicle/src/components/api/response-panel.module.csspackages/chronicle/src/components/api/response-panel.tsxpackages/chronicle/src/lib/api-routes.tspackages/chronicle/src/lib/openapi.tspackages/chronicle/src/lib/schema.tspackages/chronicle/src/lib/use-api-operation.tspackages/chronicle/src/pages/ApiLayout.module.csspackages/chronicle/src/pages/ApiPage.tsxpackages/chronicle/src/server/api/apis-proxy.tspackages/chronicle/src/themes/default/Layout.module.csspackages/chronicle/src/themes/default/Layout.tsx
💤 Files with no reviewable changes (13)
- packages/chronicle/src/components/api/code-snippets.module.css
- packages/chronicle/src/components/api/key-value-editor.module.css
- packages/chronicle/src/components/api/endpoint-page.tsx
- packages/chronicle/src/components/api/response-panel.module.css
- packages/chronicle/src/components/api/field-section.module.css
- packages/chronicle/src/components/api/endpoint-page.module.css
- packages/chronicle/src/components/api/field-row.module.css
- packages/chronicle/src/components/api/code-snippets.tsx
- packages/chronicle/src/components/api/field-section.tsx
- packages/chronicle/src/components/api/response-panel.tsx
- packages/chronicle/src/components/api/index.ts
- packages/chronicle/src/components/api/field-row.tsx
- packages/chronicle/src/components/api/key-value-editor.tsx
- api-overview: layout, left, right, titleBlock, titleText, methodBar - api-field-list: fieldItem, expandButton, childFields - api-code-snippet: actions - api-response-panel: wrapper, container, header, tabs - playground-dialog: actionNav, splitPanel, leftPanel, panelHeader, sectionHeader, fieldRow (partial) - sidebar: apiGroup, apiGroupItems, apiItem - Remove redundant CSS layout properties handled by Flex Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Validate schema type with toKind() instead of unsafe cast - Derive SchemaFieldKind type from map keys - Fix useMemo dependency in ApiCodeSnippet (current.generate not selected) - Null safety for empty responses in ResponseSection - Replace hard-coded #30a46c with --rs-color-foreground-success-primary - Guard against undefined scheme.name in auth schemes - Unify array detection using kind field in reset handler - Filter sensitive headers (set-cookie, authorization) from proxy response Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverted partial Flex replacement that broke JSX tag matching. Reapplied CodeRabbit fixes: toKind(), scheme.name guard, kind-based array detection in reset handler. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Handle root/empty path in deriveOperationId (fallback to 'root') - Curl snippet reflects JSON mode when body editor is active - Show error on invalid JSON body instead of silent fallback - Preserve OAuth2 flow details in Swagger 2.0 → 3.0 conversion Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
externalDocsfrom OpenAPI specoperationIdfor endpoints missing itallOf/oneOf/anyOfin schema flatteningexternalDocsandsecurityDefinitionsin Swagger 2.0 → OpenAPI 3.0 conversionTest plan
bun run dev:examples:basicand navigate to API reference pages🤖 Generated with Claude Code