Skip to content

test: RSS-SE-31 cover editor viewer with tests - #40

Merged
FierceSloth merged 29 commits into
feature/videoAndTestingfrom
test/RSS-SE-31_coverEditorAndViewerWithTests
Jul 13, 2026
Merged

FierceSloth merged 29 commits into
feature/videoAndTestingfrom
test/RSS-SE-31_coverEditorAndViewerWithTests

Conversation

@FierceSloth

@FierceSloth FierceSloth commented Jul 13, 2026 •

Copy link
Copy Markdown
Owner

📋 Trello Task ID

  • RSS-SE-31 (Task ID / Trello Card)
  • No ID (Global fix or chore)

⚡️ Summary

  • Add unit tests for Swagger Editor and Viewer components
  • Cover try-it-out form and curl command generation with tests
  • Implement testing for Proxy API and SSR routing
  • Refactor codemirror-linter and add validation logic tests
  • Achieve over 92% overall code coverage

🛠 Type of change

  • feat (New feature)
  • fix (Bug fix)
  • refactor (Code improvement / Refactoring without changing logic)
  • style (Formatting, CSS)
  • docs (Documentation)
  • chore (Configs, Build)
  • test (Testing)

Summary by CodeRabbit

  • Новые возможности

    • Добавлен просмотр OpenAPI-документации с группировкой эндпоинтов, параметрами, телами запросов и ответами.
    • Добавлена форма «Попробовать» для выполнения запросов, просмотра результатов и копирования команд cURL.
    • Реализована поддержка проксирования HTTP-запросов с проверкой URL и обработкой таймаутов.
    • Расширены переводы экранов авторизации и интерфейса документации на русском и английском языках.
    • Улучшена визуальная индикация HTTP-методов, статусов и ошибок.
  • Тесты

    • Добавлено покрытие ключевых сценариев прокси, редактора схем, эндпоинтов и интерактивных запросов.

FierceSloth and others added 28 commits June 29, 2026 22:17
- Add AuthForm feature component with login/register variants
- Implement SignIn and SignUp pages
- Add localization (ru/en) for auth forms
- Add strict Zod validation schemas for login and registration
- Integrate react-hook-form with zodResolver into AuthForm
- Configure dynamic mode validation on field change
- Add validation error translations for en and ru locales
- add auth-provider, get-current-user
- add AuthProvider to layout
- add checks in middleware
- implement next.js route handler for proxying requests
- add client utility to perform requests via proxy
- add tests for proxy client utility
- add translations for errors
- add submit form and database errors
- add styles and edits to app router
- delete try catch
* chore: change name of env

* refactor: add edits

* chore: change package-lock.json

* chore: change package-lock

* chore: change package-lock

* fix: fix package-lock

---------

Co-authored-by: dilmun1101 <dilmun94@gmail.com>
- add auth
- add connection to supabase
…maSavingToSupabase

- implement schema saving to supabase
- Implement groupEndpoints logic with unit tests
- Define strict TypeScript interfaces for OpenAPI schema 
- Create EndpointList UI component to render grouped paths
- Build SwaggerViewer widget and connect it with parsed schema
- Extract OpenAPI parameter and endpoint type declarations to openapi-types.ts
- Create EndpointParameters UI component to display query, header, path, and cookie parameters
- Implement i18n support in English and Russian for endpoint parameters table
- Integrate EndpointParameters into the EndpointList accordion view
- Add parameter merging logic in groupEndpoints to combine path-level and operation-level parameters
- Apply code review suggestions to home-page schema validation and Badge component exports
- Add tests for endpoint parameters component
- Create interactive TryItOutForm UI component for parameters input and request body construction
- Add withErrorPlug property to Input component to handle error container spacing and prevent layout shifts
- Adjust Accordion component paddings and styles to match structural design specs
- Add request and response schema rendering to Swagger Viewer.
- Generate JSON examples from OpenAPI schemas and display them in read-only CodeEditor blocks.
- Show response status cards with descriptions and schema examples.
- Implement Try-It-Out request execution via proxy and display response status, headers, and body
* Render endpoint list in viewer organized by path and method
* Display endpoint parameter details (path, query, header, cookie)
* Render request and response schemas and example payloads
* Implement interactive Try-It-Out form to edit request parameters and body
* Create server proxy client to execute requests and bypass CORS
* Display request execution results (status, headers, body)
* Generate and copy cURL commands from the request state
@vercel

vercel Bot commented Jul 13, 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 13, 2026 12:42pm

@coderabbitai

coderabbitai Bot commented Jul 13, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Добавлены API-прокси с фильтрацией заголовков и обработкой ошибок, интерактивный Swagger viewer с группировкой endpoint’ов, отображением OpenAPI-данных и выполнением запросов, новые типы, локализации, UI-компоненты и тестовое покрытие.

Changes

Основной функциональный контур

Layer / File(s) Summary
Прокси-запросы
app/api/proxy/*, src/shared/api/proxy-client.*
Добавлены proxy-клиент и API-обработчики с проверкой targetUrl, фильтрацией заголовков, передачей тела, таймаутом и ответами 502/504.
OpenAPI-модель и группировка
src/entities/endpoint/types/*, src/entities/endpoint/lib/*, src/entities/endpoint/index.ts
Добавлены OpenAPI-типы, генерация примеров, группировка endpoint’ов по тегам и слияние параметров с тестами.
Отображение endpoint-данных
src/entities/endpoint/ui/endpoint-list/*, endpoint-parameters/*, method-badge/*, request-body/*, response-list/*, src/shared/ui/accordion/*
Добавлены accordion-based список endpoint’ов, таблица параметров, method badges, request body и response list.
Try It Out и cURL
src/entities/endpoint/ui/try-it-out-form/*
Добавлена форма построения URL и заголовков, отправки запросов через proxy, отображения ответа, генерации cURL и копирования команды.
Swagger viewer и интеграция
src/widgets/swagger-viewer/*, src/pages/home-page/ui/home-page.tsx
Добавлен SwaggerViewer, который отображает метаданные схемы, сервер и сгруппированные endpoint’ы; home page передаёт ему разобранную схему.
Валидация редактора
src/features/schema-validator/lib/*, src/widgets/swagger-editor/ui/*
Логика преобразования Spectral-диагностик в CodeMirror вынесена в runOpenapiLinter и покрыта тестами.
Общие UI, локализация и тестовая среда
messages/*, src/shared/ui/*, src/app/styles/*, package.json, vitest.setup.ts
Расширены переводы, добавлены зависимости, обновлены стили layout, цвета Badge, поведение Input и моки CodeMirror.

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

Possibly related PRs

Suggested reviewers: dilmun1101

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Заголовок короткий и относится к изменениям, хотя охватывает лишь часть добавленных тестов.
Description check ✅ Passed Описание содержит ID задачи, summary и тип изменения, но для UI-изменений не хватает секции со скриншотами или GIF.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/RSS-SE-31_coverEditorAndViewerWithTests

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

@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: 20

Caution

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

⚠️ Outside diff range comments (3)
src/pages/login/ui/login.tsx (1)

1-12: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Убрать лишнюю обёртку LoginPage или переиспользовать её в маршруте
src/pages/login/ui/login.tsx сейчас не используется, а app/[locale]/login/page.tsx собирает тот же AuthForm напрямую, как и register. Лучше оставить один источник для этой композиции и удалить дублирующий слой.

🤖 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/pages/login/ui/login.tsx` around lines 1 - 12, Remove the unused
LoginPage wrapper from the login page composition, or update the login route to
reuse LoginPage so AuthForm with the login variant has a single source of truth.
Keep the existing styling and login behavior unchanged, matching the route’s
current composition.
src/pages/register/ui/register.tsx (1)

1-12: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Удалить лишнюю обёртку RegisterPage — app/[locale]/register/page.tsx уже рендерит AuthForm напрямую; аналогичная LoginPage тоже нигде не используется. Лучше оставить один общий слой, а не дублировать пустые страницы.

🤖 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/pages/register/ui/register.tsx` around lines 1 - 12, Remove the unused
RegisterPage wrapper from the registration UI module and update its consumers so
the route renders AuthForm with the register variant directly, matching the
existing app/[locale]/register/page.tsx behavior. Apply the same cleanup to the
analogous unused LoginPage wrapper if present, preserving the shared AuthForm
usage without empty intermediary page components.
src/entities/endpoint/ui/request-body/request-body.module.scss (1)

1-27: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Отсутствует класс .description, используемый в request-body.tsx.

В request-body.tsx (строка 32) применяется className={styles.description}, но в этом файле такого класса нет (есть только .requestBody, .title, .contentType, .block). В результате className будет undefined, и текст описания request body останется без стилизации. Для сравнения, в response-list.module.scss аналогичный класс .description определён (строки 71-76).

💡 Предлагаемое исправление
 .contentType {
   color: rgb(255 255 255 / 0.3);
   font-size: 11px;
 }
+
+.description {
+  margin: 0;
+  color: var(--text-secondary);
+  font-size: 0.875rem;
+  line-height: 1.25rem;
+}
🤖 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/entities/endpoint/ui/request-body/request-body.module.scss` around lines
1 - 27, Добавьте в request-body.module.scss класс .description, используемый
свойством styles.description в request-body.tsx, и перенесите для него
соответствующие стили из аналогичного класса .description в
response-list.module.scss.
🧹 Nitpick comments (7)
src/features/auth-form/ui/auth-form.tsx (1)

21-44: 🎯 Functional Correctness | 🔵 Trivial | 🏗️ Heavy lift

Union-typed form values may fight zodResolver/register typing.

AuthFormValues is a bare union (LoginFormValues | RegisterFormValues) rather than a single shape with an optional confirmPassword, and schema is likewise a runtime union of two different Zod schema instances passed into useForm<AuthFormValues>({ resolver: zodResolver(schema) }). This is a known pain point in the react-hook-form + Zod v4 ecosystem — union TFieldValues/schema combos have produced resolver type-mismatch errors in several tracked issues. The 'confirmPassword' in errors guard at line 99 suggests the union already causes friction for keyof. Please confirm this compiles cleanly under the project's tsc --noEmit (or whatever the CI type-check step is), and consider a simpler alternative such as a single schema with an optional confirmPassword field, or two small dedicated components.

Also applies to: 91-104

🤖 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/features/auth-form/ui/auth-form.tsx` around lines 21 - 44, Validate the
AuthForm typing with the project’s TypeScript check, focusing on
useForm<AuthFormValues>, zodResolver(schema), and the register/error handling
around the confirmPassword guard. If the union causes resolver or field-key type
errors, replace it with a single compatible form-value shape and schema using
optional confirmPassword, or split login and registration into dedicated typed
components while preserving both variants’ behavior.
src/features/auth/model/action.ts (1)

14-28: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Fallback по тексту сообщения ошибки — хрупкий паттерн.

Ветка default в mapAuthError определяет userAlreadyExists по подстроке 'already registered' в error.message. Официальная документация Supabase советует: "Always use error.code and error.name to identify errors, not string matching on error messages." Такое сопоставление может сломаться при изменении формулировок ошибок в будущих версиях @supabase/ssr/@supabase/supabase-js.

Стоит проверить, всегда ли error.code присутствует для этого случая в текущей версии клиента, и по возможности убрать зависимость от текста сообщения.

🤖 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/features/auth/model/action.ts` around lines 14 - 28, Update mapAuthError
to stop identifying userAlreadyExists by matching the message text. Use the
documented error code (and error name if available through the existing caller’s
error data) for this case, preserving the current mappings and returning
unknownError when no recognized structured identifier is present.
src/features/schema-persistence/api/editor-schema.ts (1)

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

Отсутствуют unit-тесты для editor-schema.ts.

В отличие от других изменённых модулей слоя persistence/viewer, для loadEditorSchema/saveEditorSchema не добавлен тест-файл, хотя цель PR — покрытие >92%. Логика с isEditorSchema-гардом и обработкой ошибок Supabase легко покрывается моками клиента.

Хотите, чтобы я сгенерировал тесты для loadEditorSchema/saveEditorSchema с моком Supabase-клиента?

🤖 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/features/schema-persistence/api/editor-schema.ts` around lines 1 - 33,
Добавьте unit-тесты для loadEditorSchema и saveEditorSchema, замокав
createClient и Supabase-цепочки запросов. Покройте валидный результат,
null/некорректный content через isEditorSchema, проброс ошибок чтения и записи,
а также проверку параметров select/eq/maybeSingle и upsert.
src/entities/endpoint/lib/group-endpoints.test.ts (1)

73-76: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Не покрыт вызов groupEndpoints с undefined.

В group-endpoints.ts есть защитная проверка if (!paths) return [];, рассчитанная в том числе на случай schema.paths === undefined (см. вызов в SwaggerViewer). Текущий тест проверяет только пустой объект {}, ветка с undefined остаётся непроверенной.

♻️ Предлагаемый дополнительный тест
   it('should handle empty paths object', () => {
     const result = groupEndpoints({});
     expect(result).toEqual([]);
   });
+
+  it('should handle undefined paths', () => {
+    const result = groupEndpoints(undefined as unknown as Record<string, IOpenApiPathItem>);
+    expect(result).toEqual([]);
+  });
🤖 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/entities/endpoint/lib/group-endpoints.test.ts` around lines 73 - 76,
Добавьте в тестовый набор для groupEndpoints отдельный тестовый случай с
аргументом undefined и проверьте, что он возвращает пустой массив. Разместите
его рядом с тестом для пустого объекта, чтобы покрыть защитную ветку функции
groupEndpoints.
src/entities/endpoint/lib/generate-example.test.ts (1)

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

Не покрыт случай объекта без явного type: 'object'.

Ветка schema.type === 'object' || schema.properties в generateExample может сработать только благодаря наличию properties, без type. Такие схемы часто встречаются в реальных OpenAPI-документах, но этот случай не проверяется отдельным тестом (в текущем тесте type указан явно).

♻️ Предлагаемый дополнительный тест
   it('should generate object schema example recursively', () => {
     const schema: IOpenApiSchema = {
       type: 'object',
       properties: {
         id: { type: 'integer' },
         name: { type: 'string' },
       },
     };
     expect(generateExample(schema)).toEqual({
       id: 0,
       name: 'string',
     });
   });
+
+  it('should treat schema with properties but without explicit type as object', () => {
+    const schema: IOpenApiSchema = {
+      properties: {
+        id: { type: 'integer' },
+      },
+    };
+    expect(generateExample(schema)).toEqual({ id: 0 });
+  });
🤖 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/entities/endpoint/lib/generate-example.test.ts` around lines 30 - 42,
Добавьте в тесты generateExample отдельный сценарий для объектной схемы с
properties, но без явного type: 'object'. Используйте уникальный символ
generateExample и проверьте, что схема корректно распознаётся как объект и
возвращает пример со значениями свойств, аналогичный существующей проверке.
src/entities/endpoint/ui/try-it-out-form/try-it-out-form.test.tsx (1)

13-18: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Стабить только navigator.clipboard, а не весь navigator.

vi.stubGlobal('navigator', { clipboard: { writeText: mockWriteText } }) полностью заменяет navigator, убирая остальные Navigator API. Это может привести к неожиданным побочным эффектам, если что-то в дереве рендера обращается к другим полям navigator.

🔧 Предлагаемый фикс
 const mockWriteText = vi.fn();
-vi.stubGlobal('navigator', {
-  clipboard: {
-    writeText: mockWriteText,
-  },
-});
+vi.stubGlobal('navigator', {
+  ...navigator,
+  clipboard: {
+    writeText: mockWriteText,
+  },
+});

И добавить восстановление после тестов:

 beforeEach(() => {
   vi.clearAllMocks();
 });
+
+afterEach(() => {
+  vi.unstubAllGlobals();
+});
🤖 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/entities/endpoint/ui/try-it-out-form/try-it-out-form.test.tsx` around
lines 13 - 18, Измените настройку мока в try-it-out-form тестах так, чтобы
подменялся только navigator.clipboard.writeText, сохраняя остальные свойства
navigator. Добавьте восстановление исходного состояния после тестов через
соответствующий механизм Vitest.
src/entities/endpoint/ui/method-badge/method-badge.test.tsx (1)

6-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Расширить покрытие тестами оставшихся методов.

Покрыты только get/post/delete, тогда как methodMaps определяет 7 методов (put, patch, options, head не проверяются), а также не тестируется fallback-ветка на неизвестный тип.

♻️ Пример дополнения теста
   it('should render standard methods correctly', () => {
     const { rerender } = render(<MethodBadge type="get" />);
     expect(screen.getByText('GET')).toBeInTheDocument();

     rerender(<MethodBadge type="post" />);
     expect(screen.getByText('POST')).toBeInTheDocument();

     rerender(<MethodBadge type="delete" />);
     expect(screen.getByText('DELETE')).toBeInTheDocument();
+
+    rerender(<MethodBadge type="put" />);
+    expect(screen.getByText('PUT')).toBeInTheDocument();
+
+    rerender(<MethodBadge type="patch" />);
+    expect(screen.getByText('PATCH')).toBeInTheDocument();
+
+    rerender(<MethodBadge type="options" />);
+    expect(screen.getByText('OPTIONS')).toBeInTheDocument();
+
+    rerender(<MethodBadge type="head" />);
+    expect(screen.getByText('HEAD')).toBeInTheDocument();
   });
🤖 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/entities/endpoint/ui/method-badge/method-badge.test.tsx` around lines 6 -
15, Расширьте тест `should render standard methods correctly` для проверки
методов `put`, `patch`, `options` и `head` с ожидаемыми текстовыми значениями.
Добавьте отдельный тест для `MethodBadge` с неизвестным `type`, который
подтверждает поведение fallback-ветки.
🤖 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 @.gitignore:
- Line 34: Расширьте правило игнорирования env-файлов в .gitignore: замените
отдельное правило .env.local шаблоном .env*.local, чтобы также игнорировались
.env.development.local, .env.production.local и .env.test.local, сохранив
существующее правило для .env.

In `@app/`[locale]/layout.tsx:
- Around line 54-65: Обновите функцию getCurrentUser, обернув её через
React.cache(), чтобы вызовы из RootLayout и Header переиспользовали результат в
рамках одного рендера. Сохраните текущую передачу пользователя через initialUser
в AuthProvider и не изменяйте остальную структуру компонентов.

In `@app/`[locale]/login/page.tsx:
- Around line 1-10: Replace the direct AuthForm rendering in the app route’s
Page component with the existing LoginPage from src/pages/login, delegating the
route to that page component and removing the redundant styles.main wrapper.

In `@app/`[locale]/register/page.tsx:
- Around line 1-10: Вынеси общий компонент страницы регистрации из
`app/[locale]/register/page.tsx` и `src/pages/register/ui/register.tsx`, чтобы
рендеринг `AuthForm` с `variant="register"` был определён в одном месте.
Переиспользуй этот компонент в обоих маршрутах, сохранив необходимую обёртку
`main` и стили без дублирования разметки.

In `@app/api/proxy/route.ts`:
- Around line 6-23: Усильте функцию proxyRequest для предотвращения SSRF:
добавьте проверку хоста и IP targetUrl по denylist/allowlist до DNS-резолва и
фактического адреса после него, блокируя localhost, приватные, loopback,
link-local и metadata-диапазоны. Настройте проксирование без небезопасных
автоматических редиректов либо повторяйте эти проверки для каждого Location;
если маршрут не предназначен для публичного доступа, добавьте проверку
аутентификации непосредственно в route.
- Around line 33-39: Update the proxy handler’s fetch flow around
parsedTargetUrl and controller to construct a new Response instead of returning
fetch(...) directly. Copy only an explicit allowlist of safe response headers,
excluding Set-Cookie and other sensitive headers, while preserving the upstream
response body, status, and status text.

In `@app/app.module.scss`:
- Around line 3-20: Remove the empty line before the padding declaration in the
.container rule while preserving all existing styles and responsive overrides.

In `@src/entities/endpoint/ui/endpoint-list/endpoint-list.module.scss`:
- Around line 13-14: Remove the empty line immediately before the text-transform
declaration in the .tagTitle style block, leaving the declaration and
surrounding formatting otherwise unchanged.

In `@src/entities/endpoint/ui/try-it-out-form/build-url.ts`:
- Around line 19-25: Update the path-parameter replacement loop in build-url.ts
to replace every occurrence of each `{${param.name}}` placeholder, not only the
first one. Preserve the existing encoded value from getFormStringValue and
ensure repeated placeholders such as `/orgs/{id}/nested/{id}` are all expanded
before constructing the URL.

In `@src/entities/endpoint/ui/try-it-out-form/try-it-out-form.module.scss`:
- Around line 48-74: Remove the empty lines between declarations inside the
.textArea style block, including before padding, font-size, outline, and color,
so declaration-empty-line-before passes without changing any CSS values or
behavior.

In `@src/entities/endpoint/ui/try-it-out-form/try-it-out-form.tsx`:
- Around line 117-126: Replace the hardcoded “Request failed. Please try
again.”, “Status:”, “Headers”, and “Body” strings in the try-it-out form with
the component’s existing next-intl translation function t, adding the
corresponding translation keys to the locale resources if needed. Preserve the
current error handling and result display behavior.

In `@src/features/schema-persistence/api/editor-schema.ts`:
- Around line 22-32: Предотвратите автосохранение схемы до завершения загрузки
сохранённых данных: добавьте в поток HomePage флаг isSchemaLoaded или
isHydrated, устанавливайте его только после завершения loadEditorSchema и
пропускайте первое сохранение до этого момента. Не добавляйте guard в
saveEditorSchema; после гидратации сохраните возможность намеренно очищать схему
пустой строкой.

In `@src/pages/home-page/ui/home-page.tsx`:
- Around line 17-63: Prevent the autosave effect in HomePage from running before
the initial schema load completes. Track the loading state for loadEditorSchema,
set it after the load attempt finishes (including errors), and make the
saveSchema effect return early while loading; preserve autosaving after
initialization for subsequent debouncedText changes.
- Around line 40-46: Update the parsedSchema useMemo flow to verify the parsed
object has the required OpenAPI shape, including info and paths, before casting
or passing it to SwaggerViewer. Keep returning null when rawText is absent or
validation is unavailable, and ensure stale isSchemaValid state cannot expose an
object lacking those fields.

In `@src/shared/api/supabase/get-current-user.ts`:
- Around line 5-15: Update getCurrentUser so it does not cast JWT claims
directly to User. Either fetch the full authenticated user through
supabase.auth.getUser() or map the claims payload into a User-compatible object
with the subject claim assigned to id and all required fields populated,
ensuring callers such as HomePage receive a valid user.id.

In `@src/shared/api/supabase/middleware.ts`:
- Around line 10-13: Update stripLocale to detect whether pathname has a locale
prefix before removing segments; when no locale is present, return the original
pathname unchanged, while preserving locale stripping for localized paths so
updateSession receives the correct route for isProtected and isAuthPage.

In `@src/shared/ui/accordion/accordion.module.scss`:
- Around line 79-95: Rename the `@keyframes` identifiers slideDown and slideUp in
accordion.module.scss to kebab-case names, and update every corresponding
animation reference to use the new names.

In `@src/shared/ui/input/input.module.scss`:
- Around line 51-62: Remove the empty line before min-height in the
.errorContainer rule, keeping the declarations otherwise unchanged and
conforming to the declaration-empty-line-before style rule.

In `@src/widgets/header/ui/header.tsx`:
- Around line 7-13: Remove the redundant getCurrentUser() call from Header and
obtain the existing authenticated user through AuthProvider context instead.
Preserve the current Header behavior while ensuring RootLayout remains the
single source that loads and passes the user.

In `@vitest.setup.ts`:
- Around line 12-32: Update the `@uiw/react-codemirror` mock’s handleChange
implementation so onUpdate receives a CodeMirror Text document for state.doc
instead of the raw textarea string. Use the existing CodeMirror document/text
utility and preserve the current editor value and onChange behavior.

---

Outside diff comments:
In `@src/entities/endpoint/ui/request-body/request-body.module.scss`:
- Around line 1-27: Добавьте в request-body.module.scss класс .description,
используемый свойством styles.description в request-body.tsx, и перенесите для
него соответствующие стили из аналогичного класса .description в
response-list.module.scss.

In `@src/pages/login/ui/login.tsx`:
- Around line 1-12: Remove the unused LoginPage wrapper from the login page
composition, or update the login route to reuse LoginPage so AuthForm with the
login variant has a single source of truth. Keep the existing styling and login
behavior unchanged, matching the route’s current composition.

In `@src/pages/register/ui/register.tsx`:
- Around line 1-12: Remove the unused RegisterPage wrapper from the registration
UI module and update its consumers so the route renders AuthForm with the
register variant directly, matching the existing app/[locale]/register/page.tsx
behavior. Apply the same cleanup to the analogous unused LoginPage wrapper if
present, preserving the shared AuthForm usage without empty intermediary page
components.

---

Nitpick comments:
In `@src/entities/endpoint/lib/generate-example.test.ts`:
- Around line 30-42: Добавьте в тесты generateExample отдельный сценарий для
объектной схемы с properties, но без явного type: 'object'. Используйте
уникальный символ generateExample и проверьте, что схема корректно распознаётся
как объект и возвращает пример со значениями свойств, аналогичный существующей
проверке.

In `@src/entities/endpoint/lib/group-endpoints.test.ts`:
- Around line 73-76: Добавьте в тестовый набор для groupEndpoints отдельный
тестовый случай с аргументом undefined и проверьте, что он возвращает пустой
массив. Разместите его рядом с тестом для пустого объекта, чтобы покрыть
защитную ветку функции groupEndpoints.

In `@src/entities/endpoint/ui/method-badge/method-badge.test.tsx`:
- Around line 6-15: Расширьте тест `should render standard methods correctly`
для проверки методов `put`, `patch`, `options` и `head` с ожидаемыми текстовыми
значениями. Добавьте отдельный тест для `MethodBadge` с неизвестным `type`,
который подтверждает поведение fallback-ветки.

In `@src/entities/endpoint/ui/try-it-out-form/try-it-out-form.test.tsx`:
- Around line 13-18: Измените настройку мока в try-it-out-form тестах так, чтобы
подменялся только navigator.clipboard.writeText, сохраняя остальные свойства
navigator. Добавьте восстановление исходного состояния после тестов через
соответствующий механизм Vitest.

In `@src/features/auth-form/ui/auth-form.tsx`:
- Around line 21-44: Validate the AuthForm typing with the project’s TypeScript
check, focusing on useForm<AuthFormValues>, zodResolver(schema), and the
register/error handling around the confirmPassword guard. If the union causes
resolver or field-key type errors, replace it with a single compatible
form-value shape and schema using optional confirmPassword, or split login and
registration into dedicated typed components while preserving both variants’
behavior.

In `@src/features/auth/model/action.ts`:
- Around line 14-28: Update mapAuthError to stop identifying userAlreadyExists
by matching the message text. Use the documented error code (and error name if
available through the existing caller’s error data) for this case, preserving
the current mappings and returning unknownError when no recognized structured
identifier is present.

In `@src/features/schema-persistence/api/editor-schema.ts`:
- Around line 1-33: Добавьте unit-тесты для loadEditorSchema и saveEditorSchema,
замокав createClient и Supabase-цепочки запросов. Покройте валидный результат,
null/некорректный content через isEditorSchema, проброс ошибок чтения и записи,
а также проверку параметров select/eq/maybeSingle и upsert.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 75f6df84-083b-4d47-a1a2-8e523abfec82

📥 Commits

Reviewing files that changed from the base of the PR and between 1132027 and 2bc940f.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (102)
  • .env.local.example
  • .github/workflows/checks.yml
  • .gitignore
  • app/[locale]/layout.tsx
  • app/[locale]/login/page.tsx
  • app/[locale]/register/page.tsx
  • app/api/proxy/getProxyHeaders.test.ts
  • app/api/proxy/getProxyHeaders.ts
  • app/api/proxy/route.test.ts
  • app/api/proxy/route.ts
  • app/app.module.scss
  • messages/en.json
  • messages/ru.json
  • package.json
  • proxy.ts
  • src/app/styles/abstract/_constants.scss
  • src/app/styles/style.scss
  • src/entities/.gitkeep
  • src/entities/endpoint/index.ts
  • src/entities/endpoint/lib/generate-example.test.ts
  • src/entities/endpoint/lib/generate-example.ts
  • src/entities/endpoint/lib/group-endpoints.test.ts
  • src/entities/endpoint/lib/group-endpoints.ts
  • src/entities/endpoint/types/http-types.ts
  • src/entities/endpoint/types/openapi-types.ts
  • src/entities/endpoint/ui/endpoint-list/endpoint-list.module.scss
  • src/entities/endpoint/ui/endpoint-list/endpoint-list.test.tsx
  • src/entities/endpoint/ui/endpoint-list/endpoint-list.tsx
  • src/entities/endpoint/ui/endpoint-parameters/endpoint-parameters.module.scss
  • src/entities/endpoint/ui/endpoint-parameters/endpoint-parameters.test.tsx
  • src/entities/endpoint/ui/endpoint-parameters/endpoint-parameters.tsx
  • src/entities/endpoint/ui/method-badge/method-badge.module.scss
  • src/entities/endpoint/ui/method-badge/method-badge.test.tsx
  • src/entities/endpoint/ui/method-badge/method-badge.tsx
  • src/entities/endpoint/ui/request-body/request-body.module.scss
  • src/entities/endpoint/ui/request-body/request-body.test.tsx
  • src/entities/endpoint/ui/request-body/request-body.tsx
  • src/entities/endpoint/ui/response-list/get-status-variant.ts
  • src/entities/endpoint/ui/response-list/response-list.module.scss
  • src/entities/endpoint/ui/response-list/response-list.test.tsx
  • src/entities/endpoint/ui/response-list/response-list.tsx
  • src/entities/endpoint/ui/try-it-out-form/build-headers.test.ts
  • src/entities/endpoint/ui/try-it-out-form/build-headers.ts
  • src/entities/endpoint/ui/try-it-out-form/build-url.test.ts
  • src/entities/endpoint/ui/try-it-out-form/build-url.ts
  • src/entities/endpoint/ui/try-it-out-form/format-response-body.test.ts
  • src/entities/endpoint/ui/try-it-out-form/format-response-body.ts
  • src/entities/endpoint/ui/try-it-out-form/generate-curl-command.test.ts
  • src/entities/endpoint/ui/try-it-out-form/generate-curl-command.ts
  • src/entities/endpoint/ui/try-it-out-form/get-form-string-value.test.ts
  • src/entities/endpoint/ui/try-it-out-form/get-form-string-value.ts
  • src/entities/endpoint/ui/try-it-out-form/get-parameter-field-name.test.ts
  • src/entities/endpoint/ui/try-it-out-form/get-parameter-field-name.ts
  • src/entities/endpoint/ui/try-it-out-form/try-it-out-form.module.scss
  • src/entities/endpoint/ui/try-it-out-form/try-it-out-form.test.tsx
  • src/entities/endpoint/ui/try-it-out-form/try-it-out-form.tsx
  • src/features/auth-form/index.ts
  • src/features/auth-form/model/schemas.ts
  • src/features/auth-form/ui/auth-form.module.scss
  • src/features/auth-form/ui/auth-form.tsx
  • src/features/auth/index.ts
  • src/features/auth/model/action.ts
  • src/features/auth/model/auth-provider.tsx
  • src/features/schema-persistence/api/editor-schema.ts
  • src/features/schema-validator/lib/codemirror-linter.test.ts
  • src/features/schema-validator/lib/codemirror-linter.ts
  • src/pages/home-page/ui/home-page.tsx
  • src/pages/login/index.ts
  • src/pages/login/ui/login.module.scss
  • src/pages/login/ui/login.tsx
  • src/pages/register/index.ts
  • src/pages/register/ui/register.module.scss
  • src/pages/register/ui/register.tsx
  • src/shared/api/proxy-client.test.ts
  • src/shared/api/proxy-client.ts
  • src/shared/api/supabase/client.ts
  • src/shared/api/supabase/get-current-user.ts
  • src/shared/api/supabase/index.ts
  • src/shared/api/supabase/middleware.ts
  • src/shared/api/supabase/server.ts
  • src/shared/api/utils/form.ts
  • src/shared/config/env.ts
  • src/shared/lib/auth/is-authenticated.ts
  • src/shared/ui/accordion/accordion.module.scss
  • src/shared/ui/accordion/accordion.tsx
  • src/shared/ui/accordion/index.ts
  • src/shared/ui/badge/badge.module.scss
  • src/shared/ui/badge/badge.tsx
  • src/shared/ui/badge/index.ts
  • src/shared/ui/button/button.module.scss
  • src/shared/ui/input/input.module.scss
  • src/shared/ui/input/input.tsx
  • src/widgets/header/ui/header.tsx
  • src/widgets/header/ui/private-navigation/private-navigation.tsx
  • src/widgets/swagger-editor/ui/swagger-editor.module.scss
  • src/widgets/swagger-editor/ui/swagger-editor.test.tsx
  • src/widgets/swagger-editor/ui/swagger-editor.tsx
  • src/widgets/swagger-viewer/index.ts
  • src/widgets/swagger-viewer/ui/swagger-viewer.module.scss
  • src/widgets/swagger-viewer/ui/swagger-viewer.test.tsx
  • src/widgets/swagger-viewer/ui/swagger-viewer.tsx
  • vitest.setup.ts
💤 Files with no reviewable changes (1)
  • src/shared/lib/auth/is-authenticated.ts

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

🛑 Comments failed to post (20)
.gitignore (1)

34-34: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Проверка полного содержимого .gitignore на наличие правил для .env* вариантов
cat -n .gitignore

Repository: FierceSloth/swagger-editor-app

Length of output: 951


Расширить правило для env-файлов

Сейчас игнорируются только .env.local и .env; файлы вроде .env.development.local, .env.production.local и .env.test.local снова могут попасть в коммит. Лучше вернуть шаблон для всех локальных env-файлов, например .env*.local.

🤖 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 @.gitignore at line 34, Расширьте правило игнорирования env-файлов в
.gitignore: замените отдельное правило .env.local шаблоном .env*.local, чтобы
также игнорировались .env.development.local, .env.production.local и
.env.test.local, сохранив существующее правило для .env.
app/[locale]/layout.tsx (1)

54-65: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Дублирующийся вызов getCurrentUser() в дереве компонентов.

RootLayout вызывает getCurrentUser() и передаёт результат в AuthProvider как initialUser, но Header (который рендерится внутри AuthProvider) снова вызывает getCurrentUser() самостоятельно. Без мемоизации на уровне запроса это приводит к двум отдельным вызовам supabase.auth.getClaims() на каждый рендер страницы.

Обёртка getCurrentUser в React.cache() устранила бы дублирование — подробности в консолидированном комментарии.

🤖 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 `@app/`[locale]/layout.tsx around lines 54 - 65, Обновите функцию
getCurrentUser, обернув её через React.cache(), чтобы вызовы из RootLayout и
Header переиспользовали результат в рамках одного рендера. Сохраните текущую
передачу пользователя через initialUser в AuthProvider и не изменяйте остальную
структуру компонентов.
app/[locale]/login/page.tsx (1)

1-10: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Files ==\n'
git ls-files 'app/[locale]/login/page.tsx' 'src/pages/login/**' 'src/features/auth-form/**' 'app/**/page.tsx' | sed 's#^`#-` #'

printf '\n== app/[locale]/login/page.tsx ==\n'
sed -n '1,120p' 'app/[locale]/login/page.tsx'

printf '\n== src/pages/login tree ==\n'
find 'src/pages/login' -maxdepth 3 -type f | sort | sed 's#^`#-` #'

printf '\n== src/pages/login relevant files ==\n'
for f in $(find 'src/pages/login' -maxdepth 3 -type f | sort); do
  echo "--- $f ---"
  sed -n '1,200p' "$f"
done

Repository: FierceSloth/swagger-editor-app

Length of output: 1608


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== app/[locale]/login/page.tsx references ==\n'
rg -n "AuthForm|pageWrapper|app.module.scss|login.module.scss|src/pages/login|/login" app src -g '!**/node_modules/**' || true

printf '\n== files named login.tsx or page.tsx near login ==\n'
fd -a 'login\.(tsx|ts)$|page\.tsx$' app src | sed 's#^`#-` #'

Repository: FierceSloth/swagger-editor-app

Length of output: 3932


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== app/[locale]/login/page.tsx ==\n'
sed -n '1,120p' 'app/[locale]/login/page.tsx'

printf '\n== src/pages/login ==\n'
find 'src/pages/login' -maxdepth 3 -type f | sort | while read -r f; do
  echo "--- $f ---"
  sed -n '1,200p' "$f"
done

printf '\n== references to auth-form and login wrappers ==\n'
rg -n "AuthForm|pageWrapper|app\.module\.scss|login\.module\.scss|src/pages/login" app src -g '!**/node_modules/**' || true

Repository: FierceSloth/swagger-editor-app

Length of output: 3662


Делегируйте app/[locale]/login/page.tsx на src/pages/login. Сейчас маршрут напрямую рендерит <AuthForm variant="login" /> под styles.main, хотя src/pages/login уже содержит LoginPage с собственной обёрткой. Лучше оставить app/**/page.tsx тонким и переиспользовать LoginPage, чтобы не поддерживать два расходящихся представления одной и той же страницы.

🤖 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 `@app/`[locale]/login/page.tsx around lines 1 - 10, Replace the direct AuthForm
rendering in the app route’s Page component with the existing LoginPage from
src/pages/login, delegating the route to that page component and removing the
redundant styles.main wrapper.
app/[locale]/register/page.tsx (1)

1-10: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Relevant files ==\n'
git ls-files | rg '(^app/\[locale\]/register/page\.tsx$|^src/pages/register/ui/register\.tsx$|^app/\[locale\]/login/page\.tsx$|^src/pages/login/ui/login\.tsx$|^src/features/auth-form/|app\.module\.scss|register\.module\.scss|login\.module\.scss)'

printf '\n== Outline: app/[locale]/register/page.tsx ==\n'
ast-grep outline app/[locale]/register/page.tsx --view expanded || true

printf '\n== Outline: src/pages/register/ui/register.tsx ==\n'
ast-grep outline src/pages/register/ui/register.tsx --view expanded || true

printf '\n== Outline: app/[locale]/login/page.tsx ==\n'
ast-grep outline app/[locale]/login/page.tsx --view expanded || true

printf '\n== Outline: src/pages/login/ui/login.tsx ==\n'
ast-grep outline src/pages/login/ui/login.tsx --view expanded || true

printf '\n== Read target files (line-numbered) ==\n'
for f in \
  app/[locale]/register/page.tsx \
  src/pages/register/ui/register.tsx \
  app/[locale]/login/page.tsx \
  src/pages/login/ui/login.tsx \
  src/features/auth-form/index.ts \
  src/features/auth-form/* \
  app/app.module.scss \
  src/pages/register/ui/register.module.scss \
  src/pages/login/ui/login.module.scss
do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    wc -l "$f"
    cat -n "$f" | sed -n '1,220p'
  fi
done

Repository: FierceSloth/swagger-editor-app

Length of output: 3910


Вынести общий wrapper для register-страницы
app/[locale]/register/page.tsx повторяет src/pages/register/ui/register.tsx: в обоих местах рендерится <AuthForm variant="register" />, отличается только обёртка. Лучше вынести общий компонент страницы и переиспользовать его из обоих роутов.

🤖 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 `@app/`[locale]/register/page.tsx around lines 1 - 10, Вынеси общий компонент
страницы регистрации из `app/[locale]/register/page.tsx` и
`src/pages/register/ui/register.tsx`, чтобы рендеринг `AuthForm` с
`variant="register"` был определён в одном месте. Переиспользуй этот компонент в
обоих маршрутах, сохранив необходимую обёртку `main` и стили без дублирования
разметки.
app/api/proxy/route.ts (2)

6-23: 🔒 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Проверим, защищён ли /api/proxy аутентификацией на уровне middleware,
# и есть ли где-либо в репозитории allow/deny-лист хостов для проксирования.
fd -a middleware.ts
rg -n -A10 "matcher" $(fd -a middleware.ts) 2>/dev/null
rg -n -i "169.254|127.0.0.1|private.*ip|ssrf|allowlist|denylist" --type ts

Repository: FierceSloth/swagger-editor-app

Length of output: 225


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## route file outline\n'
ast-grep outline app/api/proxy/route.ts --view expanded || true

printf '\n## route file with line numbers\n'
cat -n app/api/proxy/route.ts | sed -n '1,220p'

printf '\n## middleware files and matchers\n'
fd -a middleware.ts .
for f in $(fd -a middleware.ts .); do
  printf '\n### %s\n' "$f"
  cat -n "$f" | sed -n '1,220p'
done

printf '\n## search for proxy/auth-related code\n'
rg -n -i "api/proxy|proxyRequest|targetUrl|redirect:|allowlist|denylist|ssrf|middleware|matcher|authorization|auth" app src . --glob '!**/node_modules/**' --glob '!**/.git/**'

Repository: FierceSloth/swagger-editor-app

Length of output: 41213


Ограничь /api/proxy от SSRF

targetUrl сейчас проверяется только по протоколу, поэтому маршрут остаётся открытым для localhost, приватных диапазонов и metadata-IP. Нужны denylist/allowlist по хостам/IP (до и после DNS-resolve) и повторная проверка Location при редиректах; если прокси не должен быть публичным, добавь auth прямо в route.

🤖 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 `@app/api/proxy/route.ts` around lines 6 - 23, Усильте функцию proxyRequest для
предотвращения SSRF: добавьте проверку хоста и IP targetUrl по
denylist/allowlist до DNS-резолва и фактического адреса после него, блокируя
localhost, приватные, loopback, link-local и metadata-диапазоны. Настройте
проксирование без небезопасных автоматических редиректов либо повторяйте эти
проверки для каждого Location; если маршрут не предназначен для публичного
доступа, добавьте проверку аутентификации непосредственно в route.

33-39: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files 'app/api/proxy/route.ts' 'app/api/proxy/*' | cat
echo '---'
wc -l app/api/proxy/route.ts
echo '---'
cat -n app/api/proxy/route.ts | sed -n '1,220p'
echo '---'
rg -n "set-cookie|content-security-policy|headers.*new Headers|Response\\(|fetch\\(" app/api/proxy -S

Repository: FierceSloth/swagger-editor-app

Length of output: 3317


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- getProxyHeaders.ts ---'
cat -n app/api/proxy/getProxyHeaders.ts
echo '--- route.test.ts (1-220) ---'
cat -n app/api/proxy/route.test.ts | sed -n '1,220p'
echo '--- search for response-header handling in proxy code ---'
rg -n "headers\\.set|headers\\.append|new Response\\(|Response\\.json|getSetCookie|set-cookie|content-security-policy" app/api/proxy -S

Repository: FierceSloth/swagger-editor-app

Length of output: 7194


Отфильтруйте заголовки ответа в прокси
fetch(...) возвращается клиенту как есть, поэтому внешний targetUrl может выставить Set-Cookie для домена приложения через same-origin /api/proxy. Собирайте новый Response с allowlist заголовков и исключайте Set-Cookie и другие чувствительные заголовки.

🤖 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 `@app/api/proxy/route.ts` around lines 33 - 39, Update the proxy handler’s
fetch flow around parsedTargetUrl and controller to construct a new Response
instead of returning fetch(...) directly. Copy only an explicit allowlist of
safe response headers, excluding Set-Cookie and other sensitive headers, while
preserving the upstream response body, status, and status text.
app/app.module.scss (1)

3-20: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Убрать пустую строку перед декларацией (Stylelint).

Линтер сообщает об ошибке declaration-empty-line-before на строке 11 — пустая строка перед padding внутри .container нарушает правило.

🎨 Исправление
   flex-direction: column;
   flex: 1;
-
   padding: 0 3rem;
📝 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.

.container {
  max-width: 1920px;
  margin: 0 auto;
  width: 100%;
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 0 3rem;

  `@include` media-sm {
    padding: 0 2rem;
  }

  `@include` media-xs {
    padding: 0 1rem;
  }
}
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 11-11: Expected no empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 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 `@app/app.module.scss` around lines 3 - 20, Remove the empty line before the
padding declaration in the .container rule while preserving all existing styles
and responsive overrides.

Source: Linters/SAST tools

src/entities/endpoint/ui/endpoint-list/endpoint-list.module.scss (1)

13-14: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Убрать пустую строку перед объявлением (stylelint).

Стиллинт фиксирует declaration-empty-line-before на строке 14 из-за пустой строки перед text-transform: uppercase; внутри блока .tagTitle.

🔧 Предложенный фикс
   margin-bottom: 2rem;
   width: 100%;
-
   text-transform: uppercase;
📝 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.

  text-transform: uppercase;
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 14-14: Expected no empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 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/entities/endpoint/ui/endpoint-list/endpoint-list.module.scss` around
lines 13 - 14, Remove the empty line immediately before the text-transform
declaration in the .tagTitle style block, leaving the declaration and
surrounding formatting otherwise unchanged.

Source: Linters/SAST tools

src/entities/endpoint/ui/try-it-out-form/build-url.ts (1)

19-25: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

replace заменит только первое вхождение path-параметра.

Если один и тот же параметр встречается в шаблоне пути несколько раз (например /orgs/{id}/nested/{id}), второе вхождение {id} останется нераскрытым и попадёт в new URL(...) как буквальный текст.

🐛 Предлагаемый фикс
-      requestPath = requestPath.replace(`{${param.name}}`, encodeURIComponent(value));
+      requestPath = requestPath.replaceAll(`{${param.name}}`, encodeURIComponent(value));
📝 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.

  parameters
    .filter((param) => param.in === 'path')
    .forEach((param) => {
      const value = getFormStringValue(formData, getParameterFieldName(param));

      requestPath = requestPath.replaceAll(`{${param.name}}`, encodeURIComponent(value));
    });
🤖 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/entities/endpoint/ui/try-it-out-form/build-url.ts` around lines 19 - 25,
Update the path-parameter replacement loop in build-url.ts to replace every
occurrence of each `{${param.name}}` placeholder, not only the first one.
Preserve the existing encoded value from getFormStringValue and ensure repeated
placeholders such as `/orgs/{id}/nested/{id}` are all expanded before
constructing the URL.
src/entities/endpoint/ui/try-it-out-form/try-it-out-form.module.scss (1)

48-74: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Убрать пустые строки перед объявлениями (stylelint: declaration-empty-line-before).

Статический анализ (Stylelint) фиксирует ошибки на строках 54, 57, 61, 65 внутри блока .textArea.

🎨 Фикс форматирования
 .textArea {
   width: 100%;
   background: var(--bg-surface-2);
   border: 2px solid var(--bg-surface-3);
   border-radius: 1rem;
-
   padding: 0.75rem 1.25rem;
   margin-top: 8px;
-
   font-size: 14px;
   line-height: 1.5rem;
   font-family: var(--font-mono);
-
   outline: none;
   resize: vertical;
   transition: all 0.3s;
-
   color: var(--text-primary);
📝 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.

.textArea {
  width: 100%;
  background: var(--bg-surface-2);
  border: 2px solid var(--bg-surface-3);
  border-radius: 1rem;
  padding: 0.75rem 1.25rem;
  margin-top: 8px;
  font-size: 14px;
  line-height: 1.5rem;
  font-family: var(--font-mono);
  outline: none;
  resize: vertical;
  transition: all 0.3s;
  color: var(--text-primary);

  &::placeholder {
    color: `#98a4af`;
  }

  &:focus {
    border-color: var(--bg-surface-4);
  }
}
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 54-54: Expected no empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)


[error] 57-57: Expected no empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)


[error] 61-61: Expected no empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)


[error] 65-65: Expected no empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 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/entities/endpoint/ui/try-it-out-form/try-it-out-form.module.scss` around
lines 48 - 74, Remove the empty lines between declarations inside the .textArea
style block, including before padding, font-size, outline, and color, so
declaration-empty-line-before passes without changing any CSS values or
behavior.

Source: Linters/SAST tools

src/entities/endpoint/ui/try-it-out-form/try-it-out-form.tsx (1)

117-126: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Хардкод текста вместо локализации через next-intl.

Строки 'Request failed. Please try again.' (117-126), 'Status:', 'Headers', 'Body' (223-238) заданы напрямую на английском, хотя остальной UI компонента полностью локализован через t('...'). Это нарушает консистентность локализации приложения.

🌐 Предлагаемый фикс (добавить ключи перевода)
     } catch {
       setResult({
         status: 0,
         headers: {},
-        body: 'Request failed. Please try again.',
+        body: t('requestFailed'),
       });
     } finally {
           <div className={styles.titleBlock}>
             <h4 className={styles.resultTitle}>{t('response')}</h4>
-            <div>Status: {result.status}</div>
+            <div>{t('status', { status: result.status })}</div>
           </div>
           <div className={styles.block}>
-            <p className={styles.responseLabel}>Headers</p>
+            <p className={styles.responseLabel}>{t('headers')}</p>
             <CodeEditor value={JSON.stringify(result.headers, null, 2)} format="json" readonly transparent hideLines />
           </div>
           <div className={styles.block}>
-            <p className={styles.responseLabel}>Body</p>
+            <p className={styles.responseLabel}>{t('body')}</p>
             <CodeEditor value={result.body} format="json" readonly transparent hideLines />
           </div>

Also applies to: 223-238

🤖 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/entities/endpoint/ui/try-it-out-form/try-it-out-form.tsx` around lines
117 - 126, Replace the hardcoded “Request failed. Please try again.”, “Status:”,
“Headers”, and “Body” strings in the try-it-out form with the component’s
existing next-intl translation function t, adding the corresponding translation
keys to the locale resources if needed. Preserve the current error handling and
result display behavior.
src/features/schema-persistence/api/editor-schema.ts (1)

22-32: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== files ==\n'
git ls-files | rg '^(src/features/schema-persistence/api/editor-schema\.ts|src/.*home-page\.tsx|src/.*home-page\.ts)$'

printf '\n== usage of saveEditorSchema / loadEditorSchema ==\n'
rg -n "saveEditorSchema|loadEditorSchema|debouncedText|editor_schemas|useDebounce|autosave" src

printf '\n== editor-schema.ts outline ==\n'
ast-grep outline src/features/schema-persistence/api/editor-schema.ts --view expanded

printf '\n== home-page candidates ==\n'
fd -a 'home-page.tsx|home-page.ts' src

Repository: FierceSloth/swagger-editor-app

Length of output: 2571


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== home-page.tsx ==\n'
sed -n '1,140p' src/pages/home-page/ui/home-page.tsx | cat -n

printf '\n== use-debounce.ts ==\n'
sed -n '1,120p' src/shared/lib/hooks/use-debounce.ts | cat -n

printf '\n== editor-schema.ts ==\n'
sed -n '1,120p' src/features/schema-persistence/api/editor-schema.ts | cat -n

Repository: FierceSloth/swagger-editor-app

Length of output: 4651


Не автосохранять до завершения загрузки схемы
HomePage сейчас вызывает saveEditorSchema с debouncedText === '' сразу после появления user.id, ещё до того, как loadEditorSchema успевает подставить сохранённый текст. Это может затереть сохранённую схему пустой строкой после логина. Лучше добавить флаг isSchemaLoaded/isHydrated и пропускать первое сохранение до окончания loadEditorSchema — guard в saveEditorSchema не решает гонку и мешает осознанной очистке.

🤖 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/features/schema-persistence/api/editor-schema.ts` around lines 22 - 32,
Предотвратите автосохранение схемы до завершения загрузки сохранённых данных:
добавьте в поток HomePage флаг isSchemaLoaded или isHydrated, устанавливайте его
только после завершения loadEditorSchema и пропускайте первое сохранение до
этого момента. Не добавляйте guard в saveEditorSchema; после гидратации
сохраните возможность намеренно очищать схему пустой строкой.
src/pages/home-page/ui/home-page.tsx (2)

17-63: 🗄️ Data Integrity & Integration | 🔴 Critical | ⚡ Quick win

Гонка автосохранения может затирать сохранённую схему пустым содержимым при монтировании.

useDebounce инициализирует debouncedValue синхронно тем же значением, что и value: export function useDebounce(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState(value); Значит на монтировании debouncedText === rawText === ''.

Оба useEffect (строки 23-38 и 48-63) зависят от user?.id и запускаются одновременно, как только он появляется. Эффект сохранения (строки 48-63) не проверяет, что это первичное/незагруженное состояние, и немедленно вызывает saveEditorSchema({ userId, content: '' }). А saveEditorSchema делает upsert по user_id: export async function saveEditorSchema(params: { userId: string; content: string }) {
const { error } = await supabase.from('editor_schemas').upsert(
{
user_id: params.userId,
content: params.content,
},
{ onConflict: 'user_id' }
);

if (error) throw error;
}

Таким образом, ранее сохранённая схема пользователя рискует быть стёртой пустой строкой раньше, чем завершится параллельный loadEditorSchema, и восстановление содержимого зависит только от того, что debouncedText позже "самовосстановится" через 1 секунду после setRawText(savedSchema.content). Если пользователь закроет вкладку в этом окне — данные потеряны.

Предлагаю не запускать автосохранение до завершения первичной загрузки схемы:

🐛 Предлагаемое исправление
+  const [isSchemaLoaded, setIsSchemaLoaded] = useState(false);
+
   useEffect(() => {
     if (!user?.id) return;
+    setIsSchemaLoaded(false);

     const loadSchema = async () => {
       try {
         const savedSchema = await loadEditorSchema(user.id);
         if (savedSchema) {
           setRawText(savedSchema.content);
         }
       } catch (error) {
         console.error('Failed to load saved schema:', error);
+      } finally {
+        setIsSchemaLoaded(true);
       }
     };

     void loadSchema();
   }, [user?.id]);
@@
   useEffect(() => {
-    if (!user?.id) return;
+    if (!user?.id || !isSchemaLoaded) return;

     const saveSchema = async () => {
       try {
         await saveEditorSchema({
           userId: user.id,
           content: debouncedText,
         });
       } catch (error) {
         console.error('Failed to autosave schema:', error);
       }
     };

     void saveSchema();
-  }, [user?.id, debouncedText]);
+  }, [user?.id, debouncedText, isSchemaLoaded]);
🤖 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/pages/home-page/ui/home-page.tsx` around lines 17 - 63, Prevent the
autosave effect in HomePage from running before the initial schema load
completes. Track the loading state for loadEditorSchema, set it after the load
attempt finishes (including errors), and make the saveSchema effect return early
while loading; preserve autosaving after initialization for subsequent
debouncedText changes.

40-46: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

git ls-files | rg 'src/pages/home-page/ui/home-page\.tsx|src/.*/swagger-editor|src/.*/groupEndpoints|src/.*/parseToObject|src/.*/validation|src/.*/editor|src/.*/viewer'

echo '--- home-page.tsx ---'
sed -n '1,220p' src/pages/home-page/ui/home-page.tsx

echo '--- search isSchemaValid/rawText/onValidationChange ---'
rg -n "isSchemaValid|rawText|onValidationChange|parseToObject|groupEndpoints|SwaggerViewer|SwaggerEditor|delay" src -S

echo '--- candidate editor/viewer files (if any) ---'
for f in $(git ls-files | rg 'SwaggerEditor|SwaggerViewer|groupEndpoints|parseToObject'); do
  echo "### $f"
  wc -l "$f"
done

Repository: FierceSloth/swagger-editor-app

Length of output: 9065


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- swagger-editor.tsx ---'
sed -n '1,220p' src/widgets/swagger-editor/ui/swagger-editor.tsx

echo '--- parse-to-object.ts ---'
sed -n '1,200p' src/shared/lib/parse-to-object.ts

echo '--- swagger-viewer.tsx ---'
sed -n '1,220p' src/widgets/swagger-viewer/ui/swagger-viewer.tsx

echo '--- group-endpoints.ts ---'
sed -n '1,220p' src/entities/endpoint/lib/group-endpoints.ts

echo '--- debounce hook ---'
sed -n '1,120p' src/shared/lib/hooks/use-debounce.ts

Repository: FierceSloth/swagger-editor-app

Length of output: 7060


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- openapi-linter source ---'
rg -n "export .*openapiLinter|openapiLinter" src/features/schema-validator src -S

echo '--- schema-validator files ---'
for f in $(git ls-files | rg 'src/features/schema-validator/.+'); do
  echo "### $f"
  wc -l "$f"
done

echo '--- validation-status.tsx ---'
sed -n '1,220p' src/features/schema-validator/ui/validation-status/validation-status.tsx

echo '--- validation-feedback.tsx ---'
sed -n '1,220p' src/features/schema-validator/ui/validation-feedback/validation-feedback.tsx

Repository: FierceSloth/swagger-editor-app

Length of output: 4026


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- validate-schema.ts ---'
sed -n '1,220p' src/features/schema-validator/lib/validate-schema.ts

echo '--- codemirror-linter.ts ---'
sed -n '1,260p' src/features/schema-validator/lib/codemirror-linter.ts

echo '--- validate-schema.test.ts ---'
sed -n '1,220p' src/features/schema-validator/lib/validate-schema.test.ts

echo '--- codemirror-linter.test.ts ---'
sed -n '1,260p' src/features/schema-validator/lib/codemirror-linter.test.ts

Repository: FierceSloth/swagger-editor-app

Length of output: 6075


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- detect-format.ts ---'
sed -n '1,220p' src/features/format-converter/lib/detect-format.ts

echo '--- convert-format.ts ---'
sed -n '1,220p' src/features/format-converter/lib/convert-format.ts

echo '--- code editor component refs ---'
rg -n "onValidationChange|onUpdate|extensions=\\[openapiLinter\\]|delay" src/shared src/widgets src/features -S

Repository: FierceSloth/swagger-editor-app

Length of output: 2759


Синхронизируйте parsedSchema с текущим текстом

isSchemaValid может отставать от rawText из-за debounce/асинхронной линтер-валидации, поэтому parseToObject(rawText) as IOpenApiSchema иногда пропускает в SwaggerViewer объект без info/paths. Это может уронить рендер на schema.info.title или groupEndpoints(schema.paths). Добавь минимальную проверку формы перед кастом или связывай viewer с уже провалидированным объектом.

🤖 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/pages/home-page/ui/home-page.tsx` around lines 40 - 46, Update the
parsedSchema useMemo flow to verify the parsed object has the required OpenAPI
shape, including info and paths, before casting or passing it to SwaggerViewer.
Keep returning null when rawText is absent or validation is unavailable, and
ensure stale isSchemaValid state cannot expose an object lacking those fields.
src/shared/api/supabase/get-current-user.ts (1)

5-15: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does supabase auth getClaims() payload include an idfield matching the User type, or onlysub?

💡 Result:

The Supabase getClaims() method returns the raw JWT payload, which uses the standard sub claim to represent the user's unique ID [1][2]. It does not include an id field within the raw JWT payload [1][3]. While Supabase provides a normalized UserClaims type in its server-side libraries that maps sub to id for easier access, this is a computed or mapped view rather than the raw data contained in the JWT [1][4]. When working directly with the output of getClaims(), you should expect to use the sub field to identify the user [1][2]. If you require the full Supabase User object, you should use supabase.auth.getUser() instead, which performs a server-side lookup to return a complete, verified user record [1][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Files ==\n'
git ls-files 'src/**' | rg 'get-current-user|AuthProvider|PrivateNavigation|private-navigation|layout|header|auth' || true

printf '\n== getCurrentUser usages ==\n'
rg -n "getCurrentUser\(" src || true

printf '\n== user.id usages in src ==\n'
rg -n "\buser\.id\b" src || true

printf '\n== relevant auth consumers ==\n'
rg -n "useAuth|AuthProvider|PrivateNavigation|private navigation|current user|getClaims|getUser" src || true

Repository: FierceSloth/swagger-editor-app

Length of output: 5276


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== auth-provider ==\n'
sed -n '1,220p' src/features/auth/model/auth-provider.tsx | cat -n

printf '\n== get-current-user tests ==\n'
sed -n '1,220p' src/shared/api/supabase/get-current-user.test.ts | cat -n

printf '\n== home page ==\n'
sed -n '1,180p' src/pages/home-page/ui/home-page.tsx | cat -n

printf '\n== private navigation ==\n'
sed -n '1,220p' src/widgets/header/ui/private-navigation/private-navigation.tsx | cat -n

Repository: FierceSloth/swagger-editor-app

Length of output: 7292


Не приводить claims к User напрямую. getClaims() возвращает JWT claims, а не полный User: в payload нет id и других полей User, поэтому initialUser может прийти без user.id, и HomePage сразу выйдет по if (!user?.id) return;. Либо маппить sub -> id, либо получать пользователя через supabase.auth.getUser().

🤖 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/shared/api/supabase/get-current-user.ts` around lines 5 - 15, Update
getCurrentUser so it does not cast JWT claims directly to User. Either fetch the
full authenticated user through supabase.auth.getUser() or map the claims
payload into a User-compatible object with the subject claim assigned to id and
all required fields populated, ensuring callers such as HomePage receive a valid
user.id.
src/shared/api/supabase/middleware.ts (1)

10-13: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== files ==\n'
git ls-files | rg '(^|/)(proxy|middleware)\.(ts|js|mjs|cjs)$|src/shared/api/supabase/middleware\.ts|next-intl|i18n|intl|matcher'

printf '\n== outline middleware ==\n'
ast-grep outline src/shared/api/supabase/middleware.ts --view expanded || true

printf '\n== read middleware ==\n'
wc -l src/shared/api/supabase/middleware.ts
cat -n src/shared/api/supabase/middleware.ts

printf '\n== search matcher and handleI18nRouting/updateSession usage ==\n'
rg -n "handleI18nRouting|updateSession|matcher|stripLocale|isProtected|isAuthPage" .

Repository: FierceSloth/swagger-editor-app

Length of output: 5039


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' src/shared/api/supabase/middleware.ts
printf '\n---\n'
rg -n "matcher|handleI18nRouting|updateSession|isProtected|isAuthPage" src --glob '!**/node_modules/**'

Repository: FierceSloth/swagger-editor-app

Length of output: 3239


stripLocale ломает пути без префикса локали. proxy.ts пропускает обычные URL, поэтому /history и /login тоже доходят до updateSession; для них slice(2) даёт /, и isProtected/isAuthPage проверяют не тот маршрут. Нужен fallback на исходный pathname, если локали нет.

🤖 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/shared/api/supabase/middleware.ts` around lines 10 - 13, Update
stripLocale to detect whether pathname has a locale prefix before removing
segments; when no locale is present, return the original pathname unchanged,
while preserving locale stripping for localized paths so updateSession receives
the correct route for isProtected and isAuthPage.
src/shared/ui/accordion/accordion.module.scss (1)

79-95: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Имена keyframes не в kebab-case.

Stylelint требует kebab-case для имён @keyframes. Переименуйте slideDown/slideUp.

🛠️ Предлагаемый фикс
   &[data-state='open'] {
-    animation: slideDown 0.3s cubic-bezier(0.87, 0, 0.13, 1);
+    animation: slide-down 0.3s cubic-bezier(0.87, 0, 0.13, 1);
   }
   &[data-state='closed'] {
-    animation: slideUp 0.3s cubic-bezier(0.87, 0, 0.13, 1);
+    animation: slide-up 0.3s cubic-bezier(0.87, 0, 0.13, 1);
   }
 }

-@keyframes slideDown {
+@keyframes slide-down {
   from {
     height: 0;
   }
   to {
     height: var(--radix-accordion-content-height);
   }
 }

-@keyframes slideUp {
+@keyframes slide-up {
   from {
     height: var(--radix-accordion-content-height);
   }
   to {
     height: 0;
   }
 }
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 79-79: Expected keyframe name "slideDown" to be kebab-case (keyframes-name-pattern)

(keyframes-name-pattern)


[error] 88-88: Expected keyframe name "slideUp" to be kebab-case (keyframes-name-pattern)

(keyframes-name-pattern)

🤖 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/shared/ui/accordion/accordion.module.scss` around lines 79 - 95, Rename
the `@keyframes` identifiers slideDown and slideUp in accordion.module.scss to
kebab-case names, and update every corresponding animation reference to use the
new names.

Source: Linters/SAST tools

src/shared/ui/input/input.module.scss (1)

51-62: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Убрать пустую строку перед декларацией (Stylelint).

Аналогично app.module.scss — пустая строка перед min-height: 0 в .errorContainer нарушает правило declaration-empty-line-before.

🎨 Исправление
 .errorContainer {
   margin-top: 6px;
   display: flex;
   align-items: start;
   gap: 0.4rem;
-
   min-height: 0;
 }
📝 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.

.errorContainer {
  margin-top: 6px;
  display: flex;
  align-items: start;
  gap: 0.4rem;
  min-height: 0;
}

.withPlug {
  height: 13px;
}
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 57-57: Expected no empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 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/shared/ui/input/input.module.scss` around lines 51 - 62, Remove the empty
line before min-height in the .errorContainer rule, keeping the declarations
otherwise unchanged and conforming to the declaration-empty-line-before style
rule.

Source: Linters/SAST tools

src/widgets/header/ui/header.tsx (1)

7-13: 🚀 Performance & Scalability | 🟠 Major | ⚡ Quick win

Повторный вызов getCurrentUser() (см. консолидированный комментарий).

Header вызывает getCurrentUser() самостоятельно, хотя тот же пользователь уже загружается в RootLayout (app/[locale]/layout.tsx) и передаётся в AuthProvider. Без мемоизации это два отдельных вызова getClaims() на страницу.

🤖 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/widgets/header/ui/header.tsx` around lines 7 - 13, Remove the redundant
getCurrentUser() call from Header and obtain the existing authenticated user
through AuthProvider context instead. Preserve the current Header behavior while
ensuring RootLayout remains the single source that loads and passes the user.
vitest.setup.ts (1)

12-32: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Проверить, какие члены EditorView используются в коде помимо theme
rg -n 'EditorView\.' src/features/schema-validator src/widgets/swagger-editor
rg -n 'state\.doc' src/features/schema-validator src/widgets/swagger-editor

Repository: FierceSloth/swagger-editor-app

Length of output: 358


Мок должен передавать state.doc как Text, а не строку. codemirror-linter.ts вызывает view.state.doc.toString() и методы doc, поэтому текущий onUpdate({ state: { doc: e.target.value } }) может ломать код под тестами.

🤖 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 `@vitest.setup.ts` around lines 12 - 32, Update the `@uiw/react-codemirror`
mock’s handleChange implementation so onUpdate receives a CodeMirror Text
document for state.doc instead of the raw textarea string. Use the existing
CodeMirror document/text utility and preserve the current editor value and
onChange behavior.

@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.

Caution

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

⚠️ Outside diff range comments (1)
src/shared/ui/input/input.module.scss (1)

53-63: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Не ограничивайте контейнер ошибки фиксированной высотой.

withPlug добавляется в src/shared/ui/input/input.tsx даже при наличии error, поэтому height: 13px ограничивает и реальные сообщения об ошибках. Длинный текст будет выходить за пределы контейнера и может перекрываться следующим содержимым формы.

Используйте min-height: 13px для plug-режима и уберите фиксированный height с .errorContainer.

Предлагаемый вариант
 .errorContainer {
   margin-top: 6px;
-  height: 13px;
   display: flex;
   align-items: start;
   gap: 0.4rem;
 
   min-height: 0;
 }
 
 .withPlug {
-  height: 13px;
+  min-height: 13px;
 }
🤖 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/shared/ui/input/input.module.scss` around lines 53 - 63, Update the error
container styles around .errorContainer and .withPlug: remove the fixed height
from .errorContainer, and change .withPlug to use min-height: 13px so real error
messages can expand without overflow while preserving the plug-mode minimum
height.
🤖 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.

Outside diff comments:
In `@src/shared/ui/input/input.module.scss`:
- Around line 53-63: Update the error container styles around .errorContainer
and .withPlug: remove the fixed height from .errorContainer, and change
.withPlug to use min-height: 13px so real error messages can expand without
overflow while preserving the plug-mode minimum height.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: eb173d58-fbe5-43e1-a195-ebabef22f381

📥 Commits

Reviewing files that changed from the base of the PR and between 2bc940f and beba81b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • src/pages/home-page/ui/home-page.tsx
  • src/shared/ui/input/input.module.scss
  • vitest.setup.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/pages/home-page/ui/home-page.tsx
  • vitest.setup.ts

@FierceSloth
FierceSloth merged commit 9fe6bb2 into feature/videoAndTesting Jul 13, 2026
4 checks passed

This branch was successfully deployed

1 active deployment
Preview — beba81b0 Deployed Jul 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants