Repository navigation
test: RSS-SE-31 cover editor viewer with tests - #40
FierceSloth merged 29 commits into
Conversation
- 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
- install supabase
- 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
- add sign out
* 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
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughДобавлены API-прокси с фильтрацией заголовков и обработкой ошибок, интерактивный Swagger viewer с группировкой endpoint’ов, отображением OpenAPI-данных и выполнением запросов, новые типы, локализации, UI-компоненты и тестовое покрытие. ChangesОсновной функциональный контур
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
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 liftUnion-typed form values may fight
zodResolver/registertyping.
AuthFormValuesis a bare union (LoginFormValues | RegisterFormValues) rather than a single shape with an optionalconfirmPassword, andschemais likewise a runtime union of two different Zod schema instances passed intouseForm<AuthFormValues>({ resolver: zodResolver(schema) }). This is a known pain point in the react-hook-form + Zod v4 ecosystem — unionTFieldValues/schema combos have produced resolver type-mismatch errors in several tracked issues. The'confirmPassword' in errorsguard at line 99 suggests the union already causes friction forkeyof. Please confirm this compiles cleanly under the project'stsc --noEmit(or whatever the CI type-check step is), and consider a simpler alternative such as a single schema with an optionalconfirmPasswordfield, 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 valueFallback по тексту сообщения ошибки — хрупкий паттерн.
Ветка
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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (102)
.env.local.example.github/workflows/checks.yml.gitignoreapp/[locale]/layout.tsxapp/[locale]/login/page.tsxapp/[locale]/register/page.tsxapp/api/proxy/getProxyHeaders.test.tsapp/api/proxy/getProxyHeaders.tsapp/api/proxy/route.test.tsapp/api/proxy/route.tsapp/app.module.scssmessages/en.jsonmessages/ru.jsonpackage.jsonproxy.tssrc/app/styles/abstract/_constants.scsssrc/app/styles/style.scsssrc/entities/.gitkeepsrc/entities/endpoint/index.tssrc/entities/endpoint/lib/generate-example.test.tssrc/entities/endpoint/lib/generate-example.tssrc/entities/endpoint/lib/group-endpoints.test.tssrc/entities/endpoint/lib/group-endpoints.tssrc/entities/endpoint/types/http-types.tssrc/entities/endpoint/types/openapi-types.tssrc/entities/endpoint/ui/endpoint-list/endpoint-list.module.scsssrc/entities/endpoint/ui/endpoint-list/endpoint-list.test.tsxsrc/entities/endpoint/ui/endpoint-list/endpoint-list.tsxsrc/entities/endpoint/ui/endpoint-parameters/endpoint-parameters.module.scsssrc/entities/endpoint/ui/endpoint-parameters/endpoint-parameters.test.tsxsrc/entities/endpoint/ui/endpoint-parameters/endpoint-parameters.tsxsrc/entities/endpoint/ui/method-badge/method-badge.module.scsssrc/entities/endpoint/ui/method-badge/method-badge.test.tsxsrc/entities/endpoint/ui/method-badge/method-badge.tsxsrc/entities/endpoint/ui/request-body/request-body.module.scsssrc/entities/endpoint/ui/request-body/request-body.test.tsxsrc/entities/endpoint/ui/request-body/request-body.tsxsrc/entities/endpoint/ui/response-list/get-status-variant.tssrc/entities/endpoint/ui/response-list/response-list.module.scsssrc/entities/endpoint/ui/response-list/response-list.test.tsxsrc/entities/endpoint/ui/response-list/response-list.tsxsrc/entities/endpoint/ui/try-it-out-form/build-headers.test.tssrc/entities/endpoint/ui/try-it-out-form/build-headers.tssrc/entities/endpoint/ui/try-it-out-form/build-url.test.tssrc/entities/endpoint/ui/try-it-out-form/build-url.tssrc/entities/endpoint/ui/try-it-out-form/format-response-body.test.tssrc/entities/endpoint/ui/try-it-out-form/format-response-body.tssrc/entities/endpoint/ui/try-it-out-form/generate-curl-command.test.tssrc/entities/endpoint/ui/try-it-out-form/generate-curl-command.tssrc/entities/endpoint/ui/try-it-out-form/get-form-string-value.test.tssrc/entities/endpoint/ui/try-it-out-form/get-form-string-value.tssrc/entities/endpoint/ui/try-it-out-form/get-parameter-field-name.test.tssrc/entities/endpoint/ui/try-it-out-form/get-parameter-field-name.tssrc/entities/endpoint/ui/try-it-out-form/try-it-out-form.module.scsssrc/entities/endpoint/ui/try-it-out-form/try-it-out-form.test.tsxsrc/entities/endpoint/ui/try-it-out-form/try-it-out-form.tsxsrc/features/auth-form/index.tssrc/features/auth-form/model/schemas.tssrc/features/auth-form/ui/auth-form.module.scsssrc/features/auth-form/ui/auth-form.tsxsrc/features/auth/index.tssrc/features/auth/model/action.tssrc/features/auth/model/auth-provider.tsxsrc/features/schema-persistence/api/editor-schema.tssrc/features/schema-validator/lib/codemirror-linter.test.tssrc/features/schema-validator/lib/codemirror-linter.tssrc/pages/home-page/ui/home-page.tsxsrc/pages/login/index.tssrc/pages/login/ui/login.module.scsssrc/pages/login/ui/login.tsxsrc/pages/register/index.tssrc/pages/register/ui/register.module.scsssrc/pages/register/ui/register.tsxsrc/shared/api/proxy-client.test.tssrc/shared/api/proxy-client.tssrc/shared/api/supabase/client.tssrc/shared/api/supabase/get-current-user.tssrc/shared/api/supabase/index.tssrc/shared/api/supabase/middleware.tssrc/shared/api/supabase/server.tssrc/shared/api/utils/form.tssrc/shared/config/env.tssrc/shared/lib/auth/is-authenticated.tssrc/shared/ui/accordion/accordion.module.scsssrc/shared/ui/accordion/accordion.tsxsrc/shared/ui/accordion/index.tssrc/shared/ui/badge/badge.module.scsssrc/shared/ui/badge/badge.tsxsrc/shared/ui/badge/index.tssrc/shared/ui/button/button.module.scsssrc/shared/ui/input/input.module.scsssrc/shared/ui/input/input.tsxsrc/widgets/header/ui/header.tsxsrc/widgets/header/ui/private-navigation/private-navigation.tsxsrc/widgets/swagger-editor/ui/swagger-editor.module.scsssrc/widgets/swagger-editor/ui/swagger-editor.test.tsxsrc/widgets/swagger-editor/ui/swagger-editor.tsxsrc/widgets/swagger-viewer/index.tssrc/widgets/swagger-viewer/ui/swagger-viewer.module.scsssrc/widgets/swagger-viewer/ui/swagger-viewer.test.tsxsrc/widgets/swagger-viewer/ui/swagger-viewer.tsxvitest.setup.ts
💤 Files with no reviewable changes (1)
- src/shared/lib/auth/is-authenticated.ts
There was a problem hiding this comment.
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 .gitignoreRepository: 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" doneRepository: 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/**' || trueRepository: 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 doneRepository: 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 tsRepository: 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 -SRepository: 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 -SRepository: 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' srcRepository: 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 -nRepository: 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" doneRepository: 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.tsRepository: 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.tsxRepository: 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.tsRepository: 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 -SRepository: 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 anidfield matching the User type, or onlysub?💡 Result:
The Supabase
getClaims()method returns the raw JWT payload, which uses the standardsubclaim to represent the user's unique ID [1][2]. It does not include anidfield within the raw JWT payload [1][3]. While Supabase provides a normalizedUserClaimstype in its server-side libraries that mapssubtoidfor 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 ofgetClaims(), you should expect to use thesubfield to identify the user [1][2]. If you require the full SupabaseUserobject, you should usesupabase.auth.getUser()instead, which performs a server-side lookup to return a complete, verified user record [1][5].Citations:
- 1: https://supabase.com/docs/reference/server/types-jwtclaims
- 2: https://www.answeroverflow.com/m/1398351288370073722
- 3: supabase/supabase-js#1802
- 4: https://supabase.com/docs/reference/server/types-userclaims
- 5: https://supabase.com/docs/guides/auth/server-side/creating-a-client?environment=client-component
🏁 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 || trueRepository: 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 -nRepository: 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-editorRepository: 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.
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (3)
src/pages/home-page/ui/home-page.tsxsrc/shared/ui/input/input.module.scssvitest.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
📋 Trello Task ID
⚡️ Summary
🛠 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
Новые возможности
Тесты