Skip to content

feat: schema json yaml support - #63

Merged
AlyaEngineer merged 40 commits into
feature/3-swagger-editorfrom
story/3-schema-json-yaml-support
Jul 9, 2026
Merged

feat: schema json yaml support#63
AlyaEngineer merged 40 commits into
feature/3-swagger-editorfrom
story/3-schema-json-yaml-support

Conversation

@AlyaEngineer

@AlyaEngineer AlyaEngineer commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

Implements Feature 3 (Swagger Editor) - editing and validation of OpenAPI/Swagger schemas with format auto-detection, JSON/YAML conversion, and responsive split-view.

Changes Made

  • parseSchema/convertSchema (schema-format.ts) - format auto-detection via JSON.parse attempt with YAML fallback, bidirectional conversion without data loss
  • validateSwaggerSchema (swagger-validation.ts) - validation via SwaggerParser.validate, errors surfaced to UI
  • useSwagger hook - 400ms debounce on validation, holds editorValue/schema/format/error state
  • SwaggerMonacoEditor - editor loaded via next/dynamic with ssr: false, json/yaml syntax highlighting
  • SwaggerControl - format toggle, save schema button (POST /api/schema)
  • workspaceSx in SwaggerEditor - grid with orientation landscape/portrait media queries for split-view
  • add test coverage for schema editing flow

Known issues, need fixing before merge

  • SwaggerViewer is not wired into SwaggerEditor - second panel is hardcoded as plain text "SwaggerViewer" instead of the real component
  • swagger-view.tsx has a broken import path ../lib/swagger-endpoints - the file actually lives at utils/swagger-editor/get-swagger-endpoints.ts, this breaks the Vercel build
  • SwaggerViewer is missing from src/components/index.ts

Blocked on Feature 2 (auth)

  • isAuthenticated is a hardcoded stub (true) in swagger-control.tsx and swagger-hook.ts
  • save/restore schema is technically implemented (fetch /api/schema) but can't be counted as a completed criterion until real auth is wired in

Related issue

Closes #40, #41, #42, #43, #46

Feature

Feature 3: Swagger Editor

Acceptance criteria

Feature 1: App Header
  • Non-auth users see Sign In / Sign Up in header (upper right) — 15
  • Auth users see History / Sign Out in header — 10
  • About link in header and footer — 10
  • Expired/invalid token → redirect from private routes to Main — 10
  • Sign In / Sign Up buttons redirect to respective form route — 15
Feature 2: Sign In / Sign Up
  • Sign In / Sign Up / Sign Out buttons present everywhere they should be — 10
  • Client-side validation (email, password: 8+ chars, letter+digit+special, Unicode) — 20
  • Successful login → redirect to Main — 10
  • Logged-in user on Sign In / Sign Up routes → redirect to Main — 10
Feature 3: Swagger Editor
  • Load/paste schema in JSON and YAML — 25
  • Auto-detect input format (JSON vs YAML) — 20
  • Format switch with JSON ↔ YAML conversion, no data loss — 20
  • Schema validation with error indication — 15
  • Auth users save schema; restored on next login — 10
  • Viewer auto-populates with endpoints on valid schema — 10
  • Responsive split view (horizontal/vertical by orientation) — 20
Feature 4: Swagger Viewer
  • Endpoint list organized by path/method — 20
  • Details: method, path, all param types (path/query/header/cookie) — 25
  • Request schema and example payloads displayed — 20
  • Response schema, examples, all status codes displayed — 25
  • Try-It-Out: fill params/headers/body, execute, show response — 20
  • Generate cURL + copy-to-clipboard — 10
Feature 5: History and Analytics
  • SSR-generated; empty state with links to editor/viewer — 15
  • Requests sorted by timestamp (most recent first) — 10
  • Server-side analytics: duration, status, timestamp, method, request size, response size, error details, endpoint/URL — 45
Feature 6: About Page
  • Public route, accessible to all — 5
  • Info about RS School course — 5
  • Team info (names, roles, GitHub links) — 10
  • Design consistent with the app — 5
Feature 7: General Requirements
  • i18n: 2+ languages with toggler in header — 30
  • Sticky header with animation on stick — 10
  • User-friendly error display — 10
  • Private routes protected (401 if not authenticated) — 5
Feature 8: YouTube Video
  • 5–7 min YouTube walkthrough linked, covers all criteria — 50

Screenshots

Снимок экрана 2026-07-09 014615 Снимок экрана 2026-07-09 014638 Снимок экрана 2026-07-09 014730 Снимок экрана 2026-07-09 014806

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would break existing functionality)
  • Documentation update

Checklist

  • Self-review done
  • No console errors / warnings / logs
  • No any / @ts-ignore
  • Tests added / updated and passing

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features
    • Introduced a Swagger/OpenAPI experience with a Monaco-based editor, live schema validation, endpoint viewer, and YAML/JSON toggle.
    • Added schema save/restore with timeout handling and success/error toasts, plus starter default schema.
    • Added editor/viewer/control UI text updates and refreshed page metadata.
  • Bug Fixes
    • Improved feedback for empty/invalid schema states and refined styling/layout behavior.
  • Tests
    • Added component and utility tests covering the editor, viewer, controls, formatting, validation, and the swagger state hook.

@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
swagger-editor-app Ready Ready Preview, Comment Jul 8, 2026 11:08pm

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds a Swagger/OpenAPI editor flow with schema parsing and validation, JSON/YAML conversion, Monaco-based editing, save/format controls, endpoint viewing, and page wiring.

Changes

Swagger Editor Feature

Layer / File(s) Summary
Schema utilities and validation
src/types/index.ts, src/constants/default-schema.ts, src/utils/swagger-editor/*, tsconfig.json
Adds shared OpenAPI types, schema parsing/conversion helpers, endpoint extraction, Swagger validation, and related tests.
Schema state and persistence
src/services/schema-service.ts, src/utils/network/get-signal-with-timeout.ts, src/utils/hooks/use-swagger.ts, src/utils/hooks/use-swagger.test.ts
Adds the schema service, timeout signal helper, and useSwagger hook with debounce, restore, format conversion, and save-related tests.
Editor, control, and viewer components
src/components/swagger-monaco-editor/*, src/components/format-toggle/*, src/components/swagger-control/*, src/components/swagger-view/*
Adds the Monaco editor wrapper, format toggle, save controls, viewer rendering, and component-level tests.
Page and shared UI wiring
src/components/swagger-editor/*, src/components/index.ts, src/app/[locale]/page.tsx, src/components/main-text/*, src/i18n/messages/*.json, src/constants/index.ts, src/components/header/header.tsx, src/app/globals.css, package.json
Composes the Swagger editor into the home page, updates shared exports, messages, layout helpers, and global styling, and adds the MainText component with its test.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: Ivan-khodorov, lexarudak, a-rudak-EIS

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR also adds save/restore, viewer, layout, and styling changes that are not required by schema import issue #40. Split unrelated viewer/save/styling work into separate PRs or link the additional issues these changes are meant to satisfy.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding JSON/YAML schema support.
Linked Issues check ✅ Passed The editor loads dynamically, accepts raw typing/paste, debounces input, supports JSON/YAML, and has tests covering mount and input flow.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch story/3-schema-json-yaml-support

Comment @coderabbitai help to get the list of available commands.

@AlyaEngineer
AlyaEngineer marked this pull request as ready for review July 6, 2026 12:33
@AlyaEngineer AlyaEngineer changed the title Story/3 schema json yaml support feat: schema json yaml support Jul 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (8)
src/utils/swagger-editor/get-swagger-endpoints.ts (1)

30-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Hardcoded fallback string bypasses i18n.

'No summary' is a hardcoded English string, while sibling components (e.g. swagger-view.tsx, swagger-editor.tsx) use useTranslations for all user-facing text and the PR adds ru.json. Consider returning null/undefined for a missing summary and letting the consuming component apply the translated fallback via useTranslations.

🤖 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 `@src/utils/swagger-editor/get-swagger-endpoints.ts` around lines 30 - 39, The
endpoint summary fallback in getSwaggerEndpoints is hardcoded in English, which
bypasses the app’s translation flow. Update the logic in getSwaggerEndpoints to
stop emitting a literal fallback string when summary and operationId are
missing, and instead return a null/undefined-style value so the consuming UI can
apply the localized fallback via useTranslations, consistent with swagger-view
and swagger-editor.
src/utils/swagger-editor/schema-format.ts (1)

40-40: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant option: uniqueKeys already defaults to true.

The yaml package's parse already checks key uniqueness by default, so { uniqueKeys: true } is a no-op here. Harmless, but can be dropped for clarity.

🤖 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 `@src/utils/swagger-editor/schema-format.ts` at line 40, The parse call in
schema-format.ts is passing a redundant uniqueKeys option because yaml.parse
already enforces unique keys by default. Update the parsing logic in
parse/parsedYaml to remove the unnecessary option and keep the call using the
default behavior, preserving the existing YAML validation flow while making the
code clearer.
src/utils/hooks/swagger-hook.test.ts (1)

58-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing coverage for network failure path.

Tests cover HTTP-level failure (ok: false) but not a rejected fetch promise, which is the scenario flagged in the hook review (unhandled rejection). Consider adding a case mocking fetch to reject.

🤖 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 `@src/utils/hooks/swagger-hook.test.ts` around lines 58 - 69, Add a test in
swagger-hook.test.ts to cover the rejected fetch path for useSwaggerHook, since
the current restore-case only checks an HTTP response with ok false. Mock fetch
to reject, render the hook, and verify editorValue stays at the initial/default
value without causing an unhandled rejection; keep the existing assertions
around /api/schema and use the same hook entry points and helpers
(useSwaggerHook, mockFetchOnce, renderHook, waitFor) to place the new coverage
alongside the current restore-response test.
src/utils/hooks/swagger-hook.ts (1)

15-18: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Auth stub always grants access.

isAuthenticated is hardcoded true, so restore-from-server always runs regardless of real auth state. This matches the PR's stated known gap (blocked on real auth), so no action needed now beyond tracking, but worth a reminder before merge to production.

🤖 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 `@src/utils/hooks/swagger-hook.ts` around lines 15 - 18, The Swagger hook
currently hardcodes auth as always true, so the restore-from-server path in
swagger-hook.ts is effectively unguarded. Replace the inline stub in
swagger-hook’s isAuthenticated setup with the real authentication check used by
the app, or keep the TODO clearly isolated behind a temporary mock only for
non-production paths. Make sure the restore flow is gated by the actual auth
state before merging to production.
src/components/swagger-view/swagger-view.tsx (2)

50-57: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

LGTM overall, minor: method chip color is static.

Chip color="primary" is applied uniformly to all HTTP methods (GET/POST/DELETE/etc.), losing an opportunity to visually differentiate methods. Not blocking.

🤖 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 `@src/components/swagger-view/swagger-view.tsx` around lines 50 - 57, The HTTP
method Chip in swagger-view is using a fixed primary color for every verb, so
update the chip rendering in SwaggerView to choose color dynamically based on
endpoint.method instead of hardcoding color="primary". Use the existing
endpoint.method value in the same JSX block to map GET/POST/PUT/PATCH/DELETE and
other methods to distinct chip colors while keeping the current label and sizing
behavior.

29-33: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Untranslated heading text.

"Swagger Viewer" is hardcoded while the rest of the component (and sibling components) uses next-intl via useTranslations. Consider moving this to the swaggerViewer translation namespace for consistency.

🤖 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 `@src/components/swagger-view/swagger-view.tsx` around lines 29 - 33, The
heading in SwaggerView is hardcoded instead of using the existing next-intl
pattern used elsewhere in the component tree. Update the SwaggerView component
to read the title from the swaggerViewer translation namespace via
useTranslations, and replace the literal “Swagger Viewer” with the translated
key so it matches the rest of the localized UI.
src/components/swagger-editor/swagger-editor.tsx (1)

5-14: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Inconsistent import style: alias vs relative paths.

SwaggerMonacoEditor is imported via the @components barrel while MainText and SwaggerControl use relative paths. This is likely a byproduct of SwaggerViewer/related components missing from the barrel index (per PR description); once fixed, consider standardizing on the alias import for consistency.

🤖 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 `@src/components/swagger-editor/swagger-editor.tsx` around lines 5 - 14, The
import style in the Swagger editor component is inconsistent because
`SwaggerMonacoEditor` uses the `@components` barrel while `MainText` and
`SwaggerControl` are pulled in via relative paths. Update the `swagger-editor`
component imports to use the same alias-based pattern throughout, and if the
missing exports are now available in the components barrel, import `MainText`
and `SwaggerControl` from `@components` as well to keep the module references
consistent.
src/components/swagger-editor/swagger-editor.test.tsx (1)

1-55: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

LGTM, though note this suite doesn't yet cover the viewer panel/endpoint-card rendering, since SwaggerViewer is not wired into the component under test. Once wiring is fixed, add coverage asserting SwaggerViewer receives the derived endpoints.

🤖 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 `@src/components/swagger-editor/swagger-editor.test.tsx` around lines 1 - 55,
The SwaggerEditor test suite only covers the alert states and does not verify
viewer rendering, so once SwaggerViewer is connected in SwaggerEditor, add a
test that mocks or spies on SwaggerViewer and asserts it receives the derived
endpoints from the schema. Use the existing SwaggerEditor, SwaggerViewer, and
useSwaggerHook symbols to locate the component flow, and update the test setup
to cover the endpoint-card/viewer panel output when the schema is valid.
🤖 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 `@src/components/swagger-control/swagger-control.tsx`:
- Around line 51-73: The handleSaveSchema request can hang indefinitely because
the fetch call has no timeout or abort handling, leaving isSaving stuck true and
the Save button disabled. Update handleSaveSchema to use an AbortController (or
equivalent timeout mechanism) around the /api/schema fetch, abort the request
after a reasonable delay, and surface a clear timeout-specific error through
setError while ensuring the finally block still resets isSaving. Reference the
handleSaveSchema function and its fetch('/api/schema', ...) call when
implementing the fix.

In `@src/components/swagger-editor/swagger-editor.tsx`:
- Around line 81-87: The viewer panel is still rendering placeholder text
instead of the real Swagger viewer. Update swagger-editor.tsx so the
`SwaggerViewer` component is rendered in the second `Paper` within
`SwaggerEditor`, passing the already-derived `endpoints` and `isValid` props
from the surrounding logic. Remove the literal text and wire the component in
where the current `SwaggerViewer` string appears.

In `@src/components/swagger-monaco-editor/swagger-monaco-editor.tsx`:
- Around line 32-52: The SwaggerMonacoEditor component currently
remounts/reconfigures Monaco purely from value and language changes, which
clears undo history and cursor/view state when switching between JSON and YAML.
Update SwaggerMonacoEditor to keep a stable Monaco model per format by using
persistent models or a unique path for each format, and enable
saveViewState/restoreViewState so toggling format preserves the editor state.
Use the existing SwaggerMonacoEditor and MonacoEditor integration points to wire
this state retention without changing the controlled value behavior.

In `@src/utils/hooks/swagger-hook.ts`:
- Around line 41-56: The restoreSchema helper currently only handles non-OK
responses, so a rejected fetch('/api/schema') can escape as an unhandled promise
rejection. Update restoreSchema in swagger-hook to catch network/runtime errors
around the fetch and JSON parsing, and make the restoreSchema() invocation
safely handle the promise (for example by awaiting it in an async context or
attaching a rejection handler) so failures are contained without noisy console
errors.
- Around line 36-57: The restore logic in useEffect/restoreSchema can overwrite
in-progress user edits when /api/schema resolves late. Update swagger-hook.ts so
restoreSchema only applies setEditorValue and setFormat if the editor is still
pristine, or gate it with a hasUserEdited flag that is set once the user types.
Use the existing isAuthenticated-driven effect and the restoreSchema helper to
place the guard before updating state.

In `@src/utils/swagger-editor/schema-format.ts`:
- Around line 27-38: The JSON parsing path in schema-format.ts is swallowing
both syntax errors and the explicit “Schema must be an object” failure, so the
code always falls through to the YAML fallback. Update the logic around the
JSON.parse block in the schema-format parser to capture that error and only use
the YAML result when appropriate; if YAML also fails, rethrow the original
JSON-related error (or a combined error) so callers get the real failure. Keep
the fix centered in the schema-format parsing flow and make sure the behavior
matches the intent of schema-format-parse.test.ts.

In `@src/utils/swagger-editor/swagger-validation.ts`:
- Around line 14-38: The schema validation flow in validateSwaggerSchema
currently lets SwaggerParser.validate resolve external $ref URLs, which can
trigger browser outbound requests on every edit/restore. Update the validation
call in validateSwaggerSchema to disable external reference resolution by
passing a resolve configuration with external set to false, while keeping the
existing parseSchema, isOpenApiDocument, and error handling behavior intact.

---

Nitpick comments:
In `@src/components/swagger-editor/swagger-editor.test.tsx`:
- Around line 1-55: The SwaggerEditor test suite only covers the alert states
and does not verify viewer rendering, so once SwaggerViewer is connected in
SwaggerEditor, add a test that mocks or spies on SwaggerViewer and asserts it
receives the derived endpoints from the schema. Use the existing SwaggerEditor,
SwaggerViewer, and useSwaggerHook symbols to locate the component flow, and
update the test setup to cover the endpoint-card/viewer panel output when the
schema is valid.

In `@src/components/swagger-editor/swagger-editor.tsx`:
- Around line 5-14: The import style in the Swagger editor component is
inconsistent because `SwaggerMonacoEditor` uses the `@components` barrel while
`MainText` and `SwaggerControl` are pulled in via relative paths. Update the
`swagger-editor` component imports to use the same alias-based pattern
throughout, and if the missing exports are now available in the components
barrel, import `MainText` and `SwaggerControl` from `@components` as well to
keep the module references consistent.

In `@src/components/swagger-view/swagger-view.tsx`:
- Around line 50-57: The HTTP method Chip in swagger-view is using a fixed
primary color for every verb, so update the chip rendering in SwaggerView to
choose color dynamically based on endpoint.method instead of hardcoding
color="primary". Use the existing endpoint.method value in the same JSX block to
map GET/POST/PUT/PATCH/DELETE and other methods to distinct chip colors while
keeping the current label and sizing behavior.
- Around line 29-33: The heading in SwaggerView is hardcoded instead of using
the existing next-intl pattern used elsewhere in the component tree. Update the
SwaggerView component to read the title from the swaggerViewer translation
namespace via useTranslations, and replace the literal “Swagger Viewer” with the
translated key so it matches the rest of the localized UI.

In `@src/utils/hooks/swagger-hook.test.ts`:
- Around line 58-69: Add a test in swagger-hook.test.ts to cover the rejected
fetch path for useSwaggerHook, since the current restore-case only checks an
HTTP response with ok false. Mock fetch to reject, render the hook, and verify
editorValue stays at the initial/default value without causing an unhandled
rejection; keep the existing assertions around /api/schema and use the same hook
entry points and helpers (useSwaggerHook, mockFetchOnce, renderHook, waitFor) to
place the new coverage alongside the current restore-response test.

In `@src/utils/hooks/swagger-hook.ts`:
- Around line 15-18: The Swagger hook currently hardcodes auth as always true,
so the restore-from-server path in swagger-hook.ts is effectively unguarded.
Replace the inline stub in swagger-hook’s isAuthenticated setup with the real
authentication check used by the app, or keep the TODO clearly isolated behind a
temporary mock only for non-production paths. Make sure the restore flow is
gated by the actual auth state before merging to production.

In `@src/utils/swagger-editor/get-swagger-endpoints.ts`:
- Around line 30-39: The endpoint summary fallback in getSwaggerEndpoints is
hardcoded in English, which bypasses the app’s translation flow. Update the
logic in getSwaggerEndpoints to stop emitting a literal fallback string when
summary and operationId are missing, and instead return a null/undefined-style
value so the consuming UI can apply the localized fallback via useTranslations,
consistent with swagger-view and swagger-editor.

In `@src/utils/swagger-editor/schema-format.ts`:
- Line 40: The parse call in schema-format.ts is passing a redundant uniqueKeys
option because yaml.parse already enforces unique keys by default. Update the
parsing logic in parse/parsedYaml to remove the unnecessary option and keep the
call using the default behavior, preserving the existing YAML validation flow
while making the code clearer.
🪄 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 Plus

Run ID: 81bff6ed-6581-488b-8b5f-c5510d59e7a3

📥 Commits

Reviewing files that changed from the base of the PR and between 90dfdf4 and 59226e7.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (29)
  • package.json
  • src/app/[locale]/page.tsx
  • src/app/globals.css
  • src/components/header/header.tsx
  • src/components/index.ts
  • src/components/main-text/main-text.test.tsx
  • src/components/main-text/main-text.tsx
  • src/components/swagger-control/swagger-control.test.tsx
  • src/components/swagger-control/swagger-control.tsx
  • src/components/swagger-editor/swagger-editor.test.tsx
  • src/components/swagger-editor/swagger-editor.tsx
  • src/components/swagger-monaco-editor/swagger-monaco-editor.test.tsx
  • src/components/swagger-monaco-editor/swagger-monaco-editor.tsx
  • src/components/swagger-view/swagger-view.test.tsx
  • src/components/swagger-view/swagger-view.tsx
  • src/constants/default-schema.ts
  • src/constants/index.ts
  • src/i18n/messages/en.json
  • src/i18n/messages/ru.json
  • src/types/index.ts
  • src/utils/hooks/swagger-hook.test.ts
  • src/utils/hooks/swagger-hook.ts
  • src/utils/swagger-editor/get-swagger-endpoints.ts
  • src/utils/swagger-editor/schema-format-convert.test.ts
  • src/utils/swagger-editor/schema-format-parse.test.ts
  • src/utils/swagger-editor/schema-format.ts
  • src/utils/swagger-editor/swagger-validation.test.ts
  • src/utils/swagger-editor/swagger-validation.ts
  • tsconfig.json
💤 Files with no reviewable changes (1)
  • src/app/globals.css

Comment thread src/components/swagger-control/swagger-control.tsx
Comment thread src/components/swagger-editor/swagger-editor.tsx
Comment thread src/components/swagger-monaco-editor/swagger-monaco-editor.tsx
Comment thread src/utils/hooks/swagger-hook.ts Outdated
Comment thread src/utils/hooks/swagger-hook.ts Outdated
Comment thread src/utils/swagger-editor/schema-format.ts Outdated
Comment thread src/utils/swagger-editor/swagger-validation.ts
Comment thread src/utils/hooks/use-swagger.ts Outdated
Comment thread src/utils/swagger-editor/schema-types.ts Outdated
lexarudak
lexarudak previously approved these changes Jul 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/utils/hooks/use-swagger.ts (1)

43-60: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore error can be silently clobbered by the debounced validation effect.

Both this effect and the validation effect (Lines 27-41) write to the same error state. On mount, the validation effect for the initial editorValue fires ~400ms later and unconditionally calls setError(result.error). If restoreSchema() rejects in the meantime (Line 57-59), the restore error gets overwritten by the (likely successful, null) validation result shortly after — so the user never actually sees the restore failure.

Use a dedicated error slot for restore failures (or gate the overwrite) so the two concerns don't race on the same state.

🛡️ Proposed fix
-  const [error, setError] = useState<null | string>(null);
+  const [error, setError] = useState<null | string>(null);
+  const [restoreError, setRestoreError] = useState<null | string>(null);
     restoreSchema().catch((restoreError) => {
-      setError(restoreError instanceof Error ? restoreError.message : t('restoreError'));
+      setRestoreError(restoreError instanceof Error ? restoreError.message : t('restoreError'));
     });

Expose restoreError separately in the returned API (or combine with error only for display, e.g. error ?? restoreError) so it isn't overwritten by unrelated validation runs.

🤖 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 `@src/utils/hooks/use-swagger.ts` around lines 43 - 60, The restore failure
handling in use-swagger’s useEffect is racing with the debounced validation
effect and both are overwriting the same error state. Update the restoreSchema /
restoreError path so restore failures are stored separately from validation
errors (or only merged for display), and make sure the validation effect does
not clear or replace a pending restore error; keep the unique useEffect and
setError / restoreSchema flow easy to locate when applying the fix.
🧹 Nitpick comments (1)
src/utils/hooks/use-swagger.ts (1)

62-79: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Persistence logic split between hook and component; verify undo/cursor preservation on format toggle.

SchemaService.save isn't used anywhere in this hook — per cross-file evidence it's called directly from swagger-control.tsx instead, while restore lives here. Since this hook otherwise owns all schema/editor state, consider consolidating save behind a handleSave returned from useSwagger too, for a single cohesive persistence surface (this also matches the commit history direction of factoring both save/restore into SchemaService).

Separately, handleFormatToggle does a full-string setEditorValue replace on every toggle. The linked issue requires that JSON↔YAML switching preserve undo history and cursor position where possible — whether that holds depends on how swagger-monaco-editor.tsx (not in this batch) reacts to a wholesale value prop change versus an in-place model edit. Worth confirming that component applies the new text via a diff/edit operation rather than resetting the Monaco model.

🤖 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 `@src/utils/hooks/use-swagger.ts` around lines 62 - 79, The persistence flow is
split across useSwagger and swagger-control.tsx, and format toggling may be
resetting the editor state too aggressively. Add a cohesive handleSave from
useSwagger that wraps SchemaService.save so save/restore live behind one hook
API, and update callers accordingly. Also review handleFormatToggle to ensure
the JSON↔YAML update is applied through an in-place Monaco edit path (as handled
by swagger-monaco-editor.tsx) rather than a full value reset, so undo history
and cursor position are preserved where possible.
🤖 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 `@src/services/schema-service.ts`:
- Around line 13-24: The restore() method in SchemaService should not pass
arbitrary /api/schema JSON straight through; after fetching, validate that the
parsed payload includes a schema object with both content and format before
returning it, and otherwise return null. Also update restore() to use the same
timeout/cancellation pattern as save() by passing getSignalWithTimeout() into
fetch so the initial load can be aborted on unmount.

---

Outside diff comments:
In `@src/utils/hooks/use-swagger.ts`:
- Around line 43-60: The restore failure handling in use-swagger’s useEffect is
racing with the debounced validation effect and both are overwriting the same
error state. Update the restoreSchema / restoreError path so restore failures
are stored separately from validation errors (or only merged for display), and
make sure the validation effect does not clear or replace a pending restore
error; keep the unique useEffect and setError / restoreSchema flow easy to
locate when applying the fix.

---

Nitpick comments:
In `@src/utils/hooks/use-swagger.ts`:
- Around line 62-79: The persistence flow is split across useSwagger and
swagger-control.tsx, and format toggling may be resetting the editor state too
aggressively. Add a cohesive handleSave from useSwagger that wraps
SchemaService.save so save/restore live behind one hook API, and update callers
accordingly. Also review handleFormatToggle to ensure the JSON↔YAML update is
applied through an in-place Monaco edit path (as handled by
swagger-monaco-editor.tsx) rather than a full value reset, so undo history and
cursor position are preserved where possible.
🪄 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 Plus

Run ID: be2ddc27-7cfe-4dcd-9c03-a0631e8ef865

📥 Commits

Reviewing files that changed from the base of the PR and between 5329df3 and 63f8ea3.

📒 Files selected for processing (7)
  • src/components/swagger-control/swagger-control.tsx
  • src/services/schema-service.ts
  • src/utils/hooks/use-swagger.ts
  • src/utils/swagger-editor/is-record.ts
  • src/utils/swagger-editor/schema-format.ts
  • src/utils/swagger-editor/schema-types.ts
  • src/utils/swagger-editor/swagger-validation.ts
💤 Files with no reviewable changes (1)
  • src/utils/swagger-editor/schema-types.ts
✅ Files skipped from review due to trivial changes (1)
  • src/utils/swagger-editor/is-record.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/swagger-control/swagger-control.tsx
  • src/utils/swagger-editor/swagger-validation.ts
  • src/utils/swagger-editor/schema-format.ts

Comment thread src/services/schema-service.ts
@AlyaEngineer
AlyaEngineer requested review from Ivan-khodorov and YuliaDemir and removed request for Ivan-khodorov and YuliaDemir July 9, 2026 12:52
@AlyaEngineer
AlyaEngineer merged commit 016c079 into feature/3-swagger-editor Jul 9, 2026
3 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jul 9, 2026
42 tasks
AlyaEngineer added a commit that referenced this pull request Jul 9, 2026
* Story/1 sticky header general (#50)

* feat: install next+ts+linter+prettier+ husky+redux

* feat: configs + perfectionist + lint fix

* feat: install scss

* refactor: add some folders

* feat: install i18n + basic configs

* feat: add internatiolisation

* feat: language switcher

* feat: dependencies update

* feat: add sticky header

* feat: add mui Button-and-Link-like component

* fix: lint

* style: add style for header

* refactor:  remove css from language selector

* refactor: add const for flex styles in the header boxes

* refactor: history style as link

* fix: add some fixes

* feat: schema json yaml support (#63)

* chore: setup libraries

* feat: swagger-editor

* refactor: move title and description into a separated component

* refactor: moved controls into the swaggerControl component

* chore: update package-lock.json

* fix: fix import in swagger-view

* feat: add translations into SwaggerControl, SwaggerEditor, SwaggerViewer

* fix: fix title translation in main text

* fix: enforce unique keys when parsing YAML

* refactor: extract DEFAULT_SCHEMA into a constant

* feat: add tooltip explaining disabled format toggle

* test: add test coverage for schema editing flow

* fix: resolve component type errors in swagger viewer

* fix: add request timeout with AbortController

* fix: preserve Monaco editor undo history and cursor position on format switch

* fix: prevent restore fetch from overwriting user-edited schema

* fix: handle rejected promise in restoreSchema to prevent unhandled rejection

* fix: replace missing setEditorValue with handleEditorChange in SwaggerEditor

* fix: apply syntax highlighting immediately on editor mount

* fix: preserve original JSON parse error

* fix: disable external $ref resolution in schema validation to prevent SSRF

* refactor: split SwaggerControl into service, component, and helper

move save request to schema-service
extract FormatToggle component
extract getSignalWithTimeout helper
switch errors to toast notifications

* refactor: rename useSwaggerHook and drop unnecessary useMemo

* test: fix tests after refactor

* refactor: extract duplicated language-setting logic into helper in SwaggerMonacoEditor

* refactor: remove redundant SwaggerViewer title

* fix: use translated conversionError message instead of hardcoded string

* refactor: extract SchemaFormat and isRecord into shared schema-types module

* fix: reserve space for status alert to prevent layout shift on locale switch

* feat: sync Monaco editor theme with app color scheme

* style: add shadow, border-radius, deduplicate panel styles

* test: fix ReactElement import in swagger-control tests

* feat: extract schema fetch logic into SchemaService with restore and save methods

* fix: extract magic number into named constant

* refactor: extract isRecord type guard into its own module

* fix: validate restore payload and cancel restore request on unmount

* test: add tests for monaco theme

* feat: add SwaggerViewer placeholder component

* fix: route SwaggerControl toast messages through shared toaster namespace

---------

Co-authored-by: Yulia  Demir <Nightelfin91@gmail.com>

* fix: remove duplicate SwaggerViewer implementation in swagger-view folder

* fix: remove unused key from swaggerControl i18n namespace

* fix: guard non-object JSON in SchemaService.restore

* refactor: catch unhandled rejection in debounced validation

---------

Co-authored-by: YuliaDemir <129578495+YuliaDemir@users.noreply.github.com>
Co-authored-by: Yulia  Demir <Nightelfin91@gmail.com>
@AlyaEngineer
AlyaEngineer deleted the story/3-schema-json-yaml-support branch July 11, 2026 09:21
This was referenced Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature-3-editor Feature 3: Swagger Editor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants