feat: RSS-CORE-00 swagger editor app release - #46
FierceSloth wants to merge 66 commits into
Conversation
- Setup App Router structure with locale-based routing - Integrate next-intl for i18n support - Add localized routes for Home, About, Login, Register, and History pages - Configure i18n routing, navigation, middleware, and request config - Add translation messages for English and Russian - Add redirect from root pages to localized Home page
- Configured global SCSS architecture (variables, mixins, fonts). - Installed radix-ui dependency. - Implemented reusable UI components (Button, StatusBadge, Input, ArcBackground, GlassCard). - Added unit tests for UI components.
- Setup global SCSS architecture (variables, mixins, fonts) - Implement reusable UI components (Button, StatusBadge, Input, ArcBackground) - Setup basic routing with next-intl (en/ru) - Configure vitest coverage
- 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
- Added @uiw/react-codemirror with JSON/YAML support - Created reusable CodeEditor in shared/ui with readonly and transparent props - Applied custom dark theme and syntax highlighting via SCSS and JS - Integrated CodeEditor into SwaggerEditor widget
- add auth-provider, get-current-user - add AuthProvider to layout - add checks in middleware
- Create format-converter feature to detect and convert between JSON and YAML - Implement FormatToggle UI component with unknown state handling - Integrate format converter logic and toggle into SwaggerEditor widget - Add i18n support for the format converter UI
- Integrate `@stoplight/spectral-core` to parse and validate OpenAPI schemas in both JSON and YAML formats. - Add `CodeMirror Linter` adapter to display validation errors directly in the editor with inline tooltips. - Customize the Spectral `oas` ruleset to ignore annoying stylistic rules and focus only on structural errors. - Add comprehensive unit tests for the schema validation utility.
- Implemented `ValidationStatus` and `ValidationFeedback` UI components to visualize schema validity and error counts. - Added `next-intl` localization support for all new validation UI elements. - Integrated CodeMirror's `onUpdate` listener to efficiently extract real-time lint diagnostics without causing redundant validation runs. - Created a responsive split-view layout for the `HomePage` using Flexbox and aspect-ratio media queries. - Assembled the main page by integrating the `SwaggerEditor` into the primary pane and adding a placeholder stub for the `SwaggerViewer`.
- Refactor SwaggerEditor to operate as a fully controlled component by removing its internal local state. - Implement a custom useDebounce hook to optimize performance during user input. - Lift state management up to the HomePage to track raw text and validation status.
- Create header and footer. - Add conditional rendering for auth buttons: Sign In / Sign Up vs History / Sign Out. - Add links to the About page. - Integrate the language switcher (i18n) into the Header.
- implement next.js route handler for proxying requests - add client utility to perform requests via proxy - add tests for proxy client utility
- Replace 'unknown' magic string with null in DetectedFormat type - Extract parseToObject helper to shared/lib to eliminate duplicated yaml parsing - Replace nested ternary with getStatus function in ValidationFeedback - Split validation object state into separate errorsCount/warningsCount states - Derive currentFormat via useMemo with debounce instead of useState + useEffect - Sync package-lock.json
* Integrate code editor for OpenAPI/Swagger specifications * Implement auto-detection for JSON and YAML formats * Add seamless JSON ↔ YAML format conversion * Add real-time OpenAPI schema validation with UI feedback * Create responsive split view (horizontal/vertical) for Editor and Viewer * Synchronize parsed schema state between Editor and Viewer
- 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
- implemented and styled the About page
- A request history page has been added that displays the HTTP method, status, URL, duration, and payload sizes for each request. - For failed requests, detailed error information is shown when available. - The history is sorted from newest to oldest. - When there are no records, an informative empty-state message is displayed.
- Added a request history and analytics page. - History entries display URL, method, status, duration, timestamp, and payload sizes. - Request errors are shown directly in the history cards. - For an empty history, an explanatory message and a shortcut back to the editor are provided. - Requests are now automatically saved to history together with their execution parameters.
- Added a request history page with data about status, duration, execution time, and request/response sizes. - Implemented logging of both successful and failed proxy requests into the history. - Non-authorized users are redirected to the main page. - Updated Russian and English texts for the history page and its UI elements. - Added empty history states and a shortcut to navigate back to the editor.
- Implemented Supabase-backed authenticated request history and analytics for Try-It-Out requests. - Added detailed per-request metrics (method, status, URL, duration, timestamp, payload sizes). - Logged successful and failed proxy requests with inline error details in history. - Protected SSR history route with redirect for unauthorized users to the main page. - Added informative empty states with localized texts and shortcuts back to the editor.
…tional dependencies
- add about page
- Creating Toast and Spinner components (shared UI) - Configuring ToastProvider with the useToast() hook - Error Boundary (error.tsx) with toast notifications - Adding loading.tsx with the Spinner to all pages - Add favicon
- Write unit and integration tests for authentication flow and form validation - Implement tests for application header and navigation components - Cover Swagger Editor and schema parsing logic with tests - Add comprehensive tests for Swagger Viewer and endpoint rendering - Cover proxy server functionality and SSR History page with tests - Achieve total code coverage exceeding 95% across the application
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Team Run ID: 📝 WalkthroughWalkthroughPR добавляет полноценное Next.js-приложение: инфраструктуру и CI, Supabase-аутентификацию, прокси API с историей, OpenAPI-редактор и просмотрщик, общие UI-компоненты, i18n, а также страницы home, about, history, login и register. ChangesОсновные функциональные потоки
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 11
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (27)
src/entities/endpoint/ui/try-it-out-form/try-it-out-form.module.scss-48-74 (1)
48-74: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winОдинаковое нарушение Stylelint
declaration-empty-line-beforeв двух SCSS-файлах. Причина одна — пустые строки используются для визуального разделения групп CSS-объявлений, что конфликтует с текущей конфигурацией Stylelint.
src/entities/endpoint/ui/try-it-out-form/try-it-out-form.module.scss#L48-L74: убрать пустые строки передpadding(после строки 52),font-size(после строки 55),outline(после строки 59) иcolor(после строки 63) в блоке.textArea.app/app.module.scss#L9-L11: убрать пустую строку передpadding: 0 3rem;(послеflex: 1;) в блоке.container.🤖 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 declaration-separating empty lines that violate Stylelint: in .textArea, delete the blank lines before padding, font-size, outline, and color. Also remove the blank line before padding in .container within app/app.module.scss; make no other styling changes.Source: Linters/SAST tools
src/features/schema-validator/ui/validation-feedback/validation-feedback.module.scss-1-9 (1)
1-9: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winУбрать пустую строку перед объявлением (stylelint).
Stylelint фиксирует лишнюю пустую строку перед
display: flexвнутри одного блока объявлений.Исправление
.wrapper { padding: 0.75rem 1.5rem; background-color: var(--bg-surface-1); border-top: 1px solid var(--bg-surface-2); - display: flex; align-items: center; gap: 0.75rem; }🤖 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-validator/ui/validation-feedback/validation-feedback.module.scss` around lines 1 - 9, Remove the blank line within the .wrapper declaration block so display: flex follows the preceding border-top declaration directly, preserving all existing styles.Source: Linters/SAST tools
src/features/auth-form/ui/auth-form.module.scss-6-6 (1)
6-6: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winИсправьте ошибки Stylelint перед слиянием.
Удалите пустые строки перед декларациями
displayна строках 6, 45 и 59: правилоdeclaration-empty-line-beforeсейчас нарушено.Предлагаемое исправление
gap: 24px; - display: flex;padding-bottom: 0.875rem; - display: flex;line-height: 1.25rem; - display: flex;Also applies to: 45-45, 59-59
🤖 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.module.scss` at line 6, Remove the empty lines immediately before the display declarations in the stylesheet, including the declarations at the referenced positions, so they comply with Stylelint’s declaration-empty-line-before rule.Source: Linters/SAST tools
src/shared/ui/spinner/spinner.module.scss-22-35 (1)
22-35: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winДобавьте поддержку
prefers-reduced-motion.Три бесконечные анимации будут продолжать работать для пользователей, запросивших уменьшение движения. Отключите их в media query:
Предлагаемое исправление
+@media (prefers-reduced-motion: reduce) { + .phaseRing.ringA, + .phaseRing.ringB, + .phaseRing.ringC, + .phaseCore { + animation: none; + } +}Also applies to: 63-83
🤖 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/spinner/spinner.module.scss` around lines 22 - 35, Добавьте media query для prefers-reduced-motion: reduce в стилях, содержащих анимацию .phaseRing и остальные три бесконечные анимации, и отключите их выполнение для пользователей, запросивших уменьшение движения.src/shared/api/supabase/get-current-user.ts-5-18 (1)
5-18: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winСогласовать Supabase Auth API между кодом и тестом.
getCurrentUser()вызываетsupabase.auth.getUser(), а тесты мокают толькоgetClaims(), поэтому они не проходят по текущему сценарию. Либо перевести тесты наgetUser()/data: { user }, либо, если это действительно задумано, заменить реализацию на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/shared/api/supabase/get-current-user.ts` around lines 5 - 18, Согласуйте API Supabase между реализацией и тестами: в src/shared/api/supabase/get-current-user.ts (строки 5-18) сохраните выбранный вызов auth.getUser() и структуру data.user либо замените его на auth.getClaims(), если это требуемый контракт; в src/shared/api/supabase/get-current-user.test.ts (строки 1-55) обновите моки и ожидаемые данные под тот же API. Убедитесь, что getCurrentUser возвращает пользователя при успешном ответе и null при ошибке или отсутствии пользователя.src/shared/api/proxy-client.ts-4-6 (1)
4-6: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winКодируйте нормализованный URL.
Сейчас
trim()используется только для проверки, а вtargetUrlпопадает исходная строка. Для URL с пробелами это может привести к ошибке разбора или изменению адреса назначения.Предлагаемое исправление
export function fetchViaProxy(url: string, options?: RequestInit): Promise<Response> { - if (!url.trim()) throw new Error('URL is required'); + const normalizedUrl = url.trim(); + if (!normalizedUrl) throw new Error('URL is required'); - const proxyUrl = `/api/proxy?targetUrl=${encodeURIComponent(url)}`; + const proxyUrl = `/api/proxy?targetUrl=${encodeURIComponent(normalizedUrl)}`;🤖 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/proxy-client.ts` around lines 4 - 6, Normalize the input URL once in the proxy-client flow by trimming it after validating it, then pass that normalized value to encodeURIComponent when constructing proxyUrl. Ensure targetUrl never uses the original untrimmed url while preserving the existing required-URL error behavior.src/features/auth/model/action.ts-14-28 (1)
14-28: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winНе сопоставлять ошибки Supabase по тексту сообщения.
ВmapAuthErrorветкаdefaultиспользуетmessage.toLowerCase().includes('already registered'); для Supabase нужно опираться наerror.code/error.name, потому чтоerror.messageне является стабильным контрактом и может меняться.🤖 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 remove the message-based “already registered” fallback and rely only on stable Supabase error identifiers such as code or name. Preserve the existing mappings for invalid_credentials, user_already_exists, and over_request_rate_limit, while returning unknownError when no recognized identifier is present.src/shared/ui/input/input.module.scss-4-4 (1)
4-4: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winИсправить ошибки Stylelint
declaration-empty-line-before.Правило
declaration-empty-line-beforeтребует убрать пустые строки перед декларациями на этих строках — иначе линт-проверка в CI не пройдёт.🎨 Предложенное исправление
.input { width: 100%; - background: var(--bg-surface-2); border: 2px solid var(--bg-surface-3); border-radius: 1rem; - padding: 0.75rem 3.5rem 0.75rem 1.25rem; margin-top: 8px; - font-size: 1rem; line-height: 1.5rem; - outline: none; transition: all 0.3s; - color: var(--text-primary);и аналогично для строк 53-58 (
.errorContainer).Also applies to: 8-8, 11-11, 14-14, 17-17, 54-54, 58-58
🤖 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` at line 4, Уберите пустые строки перед декларациями в стилях input.module.scss, включая декларации в основном блоке и секции .errorContainer. Примените это также к указанным повторяющимся местам, чтобы все декларации соответствовали правилу Stylelint declaration-empty-line-before.Source: Linters/SAST tools
src/shared/lib/parse-to-object.ts-6-7 (1)
6-7: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winОбе проверки принимают массивы за объектные документы.
src/shared/lib/parse-to-object.ts#L6-L7: добавьте!Array.isArray(parsed)перед возвратомRecord<string, unknown>.src/features/format-converter/lib/detect-format.ts#L8-L10: примените ту же проверку при распознавании JSON.🤖 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/lib/parse-to-object.ts` around lines 6 - 7, Массивы ошибочно принимаются за объектные документы в обеих проверках. В src/shared/lib/parse-to-object.ts:6-7 обновите условие вокруг parseToObject, добавив исключение Array.isArray(parsed) перед возвратом Record<string, unknown>; в src/features/format-converter/lib/detect-format.ts:8-10 примените такую же проверку при распознавании JSON.src/pages/home-page/ui/home-page.module.scss-44-45 (1)
44-45: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winУдалите пустую строку перед
opacity.Stylelint сообщает о нарушении
declaration-empty-line-beforeна Line 45.Предлагаемое исправление
justify-content: center; - opacity: 0.5;🤖 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.module.scss` around lines 44 - 45, Remove the empty line immediately before the opacity declaration in the affected style rule so the declaration-empty-line-before lint violation is resolved.Source: Linters/SAST tools
src/widgets/swagger-editor/ui/swagger-editor.module.scss-9-20 (1)
9-20: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winДублирующиеся CSS-свойства в
.toolbar.
displayиalign-itemsобъявлены два раза (строки 10-11 и 16-17) — похоже на артефакт слияния. Второй блок также нарушает правилоdeclaration-empty-line-before(пустая строка передdisplayна строке 16).🧹 Предлагаемое исправление
.toolbar { display: flex; align-items: center; padding: 0.75rem 1.5rem; background-color: var(--bg-surface-1); border-bottom: 1px solid var(--bg-surface-2); - - display: flex; - align-items: center; justify-content: space-between; gap: 0.75rem; }🤖 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/swagger-editor/ui/swagger-editor.module.scss` around lines 9 - 20, Remove the duplicate display and align-items declarations from .toolbar, preserving each property once along with justify-content, gap, and the existing styling; eliminate the unnecessary empty line before the remaining declarations.Source: Linters/SAST tools
src/features/schema-validator/lib/codemirror-linter.ts-22-30 (1)
22-30: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick winОграничь
characterпоLine.to
from/toсейчас ограничиваются только номером строки, ноcharacterможет вывести позицию за пределы строки и сломать применение диагностики.🛡️ Предлагаемое исправление
const startLine = doc.line(Math.min(startLinePos.line + 1, doc.lines)); const endLine = doc.line(Math.min(endLinePos.line + 1, doc.lines)); - const from = startLine.from + startLinePos.character; - const to = endLine.from + endLinePos.character; + const from = Math.min(startLine.from + startLinePos.character, startLine.to); + const to = Math.min(endLine.from + endLinePos.character, endLine.to);🤖 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-validator/lib/codemirror-linter.ts` around lines 22 - 30, Ограничьте значения character при вычислении from и to соответствующими границами строк через Line.to, чтобы позиции диагностики никогда не выходили за пределы строки. Обновите расчёты в текущем обработчике, сохранив существующее ограничение номеров строк и поведение для корректных позиций.src/pages/history-page/ui/history-requst-card/history-request-card.tsx-39-41 (1)
39-41: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winЗахардкоженные строки не локализованы.
Строки
Req:,Res:иError:вшиты напрямую, хотя в этом же PRRequestBodyиспользуетuseTranslationsизnext-intl. Приложение заявляет поддержку en/ru — эти строки не переведутся на русский.♻️ Пример исправления
+import { useTranslations } from 'next-intl'; ... + const t = useTranslations('HistoryRequestCard'); ... - <span className={styles.metaItem}> - Req: {formatSize(item.request_size)} - <span className={styles.separator}>|</span> - Res: {formatSize(item.response_size)} - </span> + <span className={styles.metaItem}> + {t('requestSize', { size: formatSize(item.request_size) })} + <span className={styles.separator}>|</span> + {t('responseSize', { size: formatSize(item.response_size) })} + </span> ... - <span className={styles.errorLabel}>Error:</span> + <span className={styles.errorLabel}>{t('error')}</span>Also applies to: 49-49
🤖 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/history-page/ui/history-requst-card/history-request-card.tsx` around lines 39 - 41, Localize the hardcoded “Req:”, “Res:”, and “Error:” labels in the history request card. Reuse the existing next-intl useTranslations setup from RequestBody or the surrounding component, add the corresponding en/ru translation keys, and render translated labels in place of the literals.src/pages/history-page/ui/empty-history-message/empty-history-message.tsx-19-23 (1)
19-23: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winЛокализуйте все пользовательские строки пустого состояния.
SCANNING_STREAMиSYSTEM.STUB // NO_RECORDS_FOUNDостаются на английском, поэтому русская версия страницы будет частично отображать английский текст. Добавьте эти строки вmessages/en.jsonиmessages/ru.json, затем получайте их через namespaceHistory.🤖 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/history-page/ui/empty-history-message/empty-history-message.tsx` around lines 19 - 23, Локализуйте пользовательские строки SCANNING_STREAM и SYSTEM.STUB // NO_RECORDS_FOUND из компонента empty-history-message: добавьте соответствующие ключи в messages/en.json и messages/ru.json, затем получайте их через namespace History вместо жестко заданного текста, сохранив текущую разметку scanLabel и Badge.src/entities/endpoint/lib/generate-example.ts-34-40 (1)
34-40: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winНесогласованная обработка массивов без явного
type: 'array'.Для объектов есть fallback
schema.type === 'object' || schema.properties(строка 24), а для массивов аналогичного fallback наschema.itemsнет. Схема сitems, но без"type": "array", провалится вswitchи вернётnullвместо примера массива.🐛 Предлагаемый фикс
- if (schema.type === 'array') { + if (schema.type === 'array' || schema.items) { if (!schema.items) { return []; } return [generateExample(schema.items)]; }🤖 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.ts` around lines 34 - 40, Update the array handling in generateExample to recognize schemas with items even when schema.type is not explicitly 'array'. Reuse the existing schema.items validation and return an array containing generateExample(schema.items), while preserving the current empty-array behavior when items is absent.src/pages/history-page/ui/empty-history-message/empty-history-message.module.scss-28-34 (1)
28-34: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winПереименовать keyframe в kebab-case.
Линтер требует kebab-case для имён
@keyframes. Нужно переименоватьspinReverse→spin-reverseи обновить ссылку в.ringInner.🎨 Предлагаемое исправление
.ringInner { position: absolute; inset: 16px; border-radius: 50%; border: 1px dashed var(--bg-surface-4); - animation: spinReverse 12s linear infinite; + animation: spin-reverse 12s linear infinite; } ... -@keyframes spinReverse { +@keyframes spin-reverse { from { transform: rotate(360deg); } to { transform: rotate(0deg); } }Also applies to: 64-71
🤖 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/history-page/ui/empty-history-message/empty-history-message.module.scss` around lines 28 - 34, Rename the spinReverse keyframe identifier to spin-reverse and update the animation reference in .ringInner accordingly, including the corresponding occurrence in the additional affected section.Source: Linters/SAST tools
src/pages/about-page/ui/about-hero-section/about-hero-section.module.scss-83-87 (1)
83-87: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winИсправить регистр ключевого слова CSS согласно правилу линтера.
Stylelint требует lowercase для значений-ключевых слов:
currentColor→currentcolor.🎨 Предлагаемое исправление
.arrow { width: 10px; aspect-ratio: 1/1; - color: currentColor; + color: currentcolor; }🤖 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/about-page/ui/about-hero-section/about-hero-section.module.scss` around lines 83 - 87, Update the color keyword in the .arrow style rule from currentColor to lowercase currentcolor to satisfy the Stylelint casing requirement.Source: Linters/SAST tools
src/features/schema-validator/ui/validation-status/validation-status.module.scss-7-7 (1)
7-7: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winУберите пустую строку перед декларацией.
Stylelint завершает проверку с ошибкой
declaration-empty-line-before; удалите пустую строку междуjustify-contentиgap.Предлагаемое исправление
justify-content: center; - gap: 0.3rem;🤖 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-validator/ui/validation-status/validation-status.module.scss` at line 7, Remove the empty line before the display declaration in the validation-status styles, specifically between justify-content and gap, so adjacent declarations satisfy the declaration-empty-line-before Stylelint rule.Source: Linters/SAST tools
.github/workflows/checks.yml-1-1 (1)
1-1: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winИсправьте окончания строк в YAML.
yamllintсообщает, что файл использует CRLF вместо ожидаемых LF; приведите.github/workflows/checks.ymlк LF, иначе YAML-проверка остаётся красной.🤖 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 @.github/workflows/checks.yml at line 1, Convert the line endings in the GitHub Actions workflow identified by the name “CI Check” from CRLF to LF throughout the file, without changing its YAML content.Source: Linters/SAST tools
src/app/styles/abstract/_constants.scss-18-19 (1)
18-19: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winИсправьте fallback для моноширинного шрифта.
При недоступности
--font-jetbrains-monoтекущий fallbacksans-serifбудет отображать код пропорциональным шрифтом. Используйтеmonospaceи задайте fallback внутриvar(...).Предлагаемое исправление
- --font-mono: var(--font-jetbrains-mono), sans-serif; + --font-mono: var(--font-jetbrains-mono, monospace);🤖 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/app/styles/abstract/_constants.scss` around lines 18 - 19, Update the --font-mono declaration to use monospace as the fallback when --font-jetbrains-mono is unavailable, placing that fallback inside var(...). Leave the --font-ui declaration unchanged.src/shared/ui/button-link/button-link.module.scss-6-7 (1)
6-7: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winУбрать пустые строки перед объявлениями (Stylelint: declaration-empty-line-before).
Строки 6-7 и 13-14 нарушают правило
declaration-empty-line-before.🛠️ Исправление пустых строк
.button { display: inline-flex; align-items: center; justify-content: center; gap: 12px; - font-size: 0.875rem; line-height: 1.25rem; font-weight: 600; text-decoration: none; cursor: pointer; transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94); - border-radius: var(--radius-card); padding: 8px 24px; border: none; background: transparent; margin: 0; box-sizing: border-box;Also applies to: 13-14
🤖 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/button-link/button-link.module.scss` around lines 6 - 7, Remove the empty lines immediately before the declarations around font-size and the corresponding declarations at the second reported location in the button-link styles, so the SCSS complies with Stylelint’s declaration-empty-line-before rule.Source: Linters/SAST tools
src/pages/about-page/ui/card/card.module.scss-35-39 (1)
35-39: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winАналогичная проблема с
transitionтолько на:hover.
.githubLink:hover .githubIconзадаётtransition: 1.5s;только для состояния наведения — обратный переход (color/transform) не будет анимирован при уходе курсора. Тот же паттерн, что и в.cardвыше.🤖 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/about-page/ui/card/card.module.scss` around lines 35 - 39, Move the transition declaration from the `.githubLink:hover .githubIcon` rule to the base `.githubIcon` rule, while keeping the hover color and transform changes unchanged so both entering and leaving hover are animated.src/pages/about-page/ui/card/card.module.scss-1-14 (1)
1-14: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
transitionобъявлен только в:hover, обратный переход не анимируется.
transition: 1s;иtransformзаданы только внутри.card:hover. При наведении переход плавный, но при снятии курсора свойства применяются мгновенно, так как у базового.cardнетtransition.🎨 Предлагаемое исправление
.card { display: flex; flex-direction: column; gap: 20px; border-radius: 25px; padding: 20px; border: 1px solid transparent; + transition: border-color 1s, transform 1s; &:hover { border: 1px solid rgba(255, 255, 255, 0.5); - transition: 1s; transform: translateY(-3px); } }🤖 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/about-page/ui/card/card.module.scss` around lines 1 - 14, Move the transition declaration from .card:hover to the base .card rule so both hover and hover-exit transitions are animated; keep the existing hover border and transform behavior unchanged.src/entities/endpoint/ui/endpoint-list/endpoint-list.module.scss-13-14 (1)
13-14: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winУберите пустую строку перед
text-transform.Stylelint сообщает об ошибке
declaration-empty-line-beforeна Line 14; в текущем виде проверка стилей может завершиться ошибкой. Это замечание основано на предоставленном отчёте Stylelint.Предлагаемое исправление
font-weight: 600; - text-transform: uppercase;🤖 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 affected style rule, preserving all other declarations and formatting.Source: Linters/SAST tools
src/app/styles/base/_base.scss-63-71 (1)
63-71: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winStylelint: пустая строка перед объявлением.
Statiс-анализ (
declaration-empty-line-before) указывает на лишнюю пустую строку передposition: relative;внутри блока#root.🎨 Предлагаемое исправление
`#root` { width: 100%; min-height: 100dvh; display: flex; flex-direction: column; - position: relative; z-index: var(--z-base); }🤖 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/app/styles/base/_base.scss` around lines 63 - 71, Remove the extra empty line before position in the `#root` style block, keeping the declaration sequence and all existing values unchanged.Source: Linters/SAST tools
src/shared/ui/accordion/accordion.module.scss-43-45 (1)
43-45: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winИмена keyframes не в kebab-case (нарушение stylelint).
slideDown/slideUpнарушают правилоkeyframes-name-pattern, что может ломать линт-проверку в CI.♻️ Предлагаемое исправление
&[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; } }Also applies to: 64-64, 67-67, 79-95
🤖 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 43 - 45, Переименуйте keyframes slideDown и slideUp в имена в kebab-case согласно правилу keyframes-name-pattern и обновите все ссылки на них в стилях accordion, включая отмеченные блоки 64, 67 и 79–95. Сохраните текущую анимацию и поведение состояний open/closed.Source: Linters/SAST tools
src/shared/ui/arc-background/arc-background.module.scss-21-29 (1)
21-29: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winПустые строки перед объявлениями внутри блоков (stylelint
declaration-empty-line-before).Во всех отмеченных местах (
.arc,.arc::before,.arc::after) пустая строка стоит перед объявлением свойства, следующим за другим объявлением в том же блоке — линтер требует убрать такие пустые строки. Это может фейлить lint-проверку в CI.♻️ Предлагаемое исправление (пример для `.arc`)
top: 50%; left: 0; - transform: translate(-70%, -50%); background: `#000`; - opacity: 0.8; - box-shadow: 0 0 150px 30px rgba(var(--fringe-rgb), 0.1); - animation: breathe 8s ease-in-out infinite alternate;Аналогично нужно убрать пустые строки перед
border,filter,box-shadowв блоках.arc::beforeи.arc::after.Also applies to: 38-41, 43-53, 61-62, 64-70
🤖 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/arc-background/arc-background.module.scss` around lines 21 - 29, Remove the empty lines between consecutive declarations in the .arc, .arc::before, and .arc::after style blocks, including before the flagged properties such as opacity, border, filter, and box-shadow, so they comply with stylelint declaration-empty-line-before.Source: Linters/SAST tools
🧹 Nitpick comments (22)
app/api/proxy/getProxyHeaders.ts (1)
3-3: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winСтоит дополнить список hop-by-hop заголовками.
Список исключений корректно защищает от утечки cookie/authorization на внешний хост, но не включает hop-by-hop заголовки (
connection,keep-alive,transfer-encoding,upgrade,proxy-authenticate,proxy-authorization), которые по спецификации не должны пересылаться прокси и иногда вызывают ошибки в fetch/undici при передаче третьей стороне.♻️ Предлагаемое исправление
-const EXCLUDED_REQUEST_HEADERS = ['host', 'origin', 'referer', 'cookie', 'content-length', 'authorization']; +const EXCLUDED_REQUEST_HEADERS = [ + 'host', + 'origin', + 'referer', + 'cookie', + 'content-length', + 'authorization', + 'connection', + 'keep-alive', + 'transfer-encoding', + 'upgrade', + 'proxy-authenticate', + 'proxy-authorization', +];🤖 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/getProxyHeaders.ts` at line 3, Расширьте константу EXCLUDED_REQUEST_HEADERS, добавив все указанные hop-by-hop заголовки: connection, keep-alive, transfer-encoding, upgrade, proxy-authenticate и proxy-authorization, сохранив существующие исключения без изменений.src/shared/ui/code-editor/ui/code-editor.tsx (1)
30-36: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winМемоизировать
allExtensions.
@uiw/react-codemirrorпересобирает конфигурацию при смене ссылки наextensions, поэтому новый массив на каждом рендере будет вызывать лишний reconfigure.useMemoздесь уместен.🤖 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/code-editor/ui/code-editor.tsx` around lines 30 - 36, Мемоизируйте массив `allExtensions` через `useMemo`, используя `extensions`, `format`, `editorTheme`, `syntaxTheme` и `readonly` как зависимости. Сохраните текущий порядок объединения пользовательских и базовых расширений, чтобы ссылка на массив не менялась без изменения этих значений.src/entities/endpoint/ui/try-it-out-form/try-it-out-form.tsx (1)
233-236: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueФормат тела ответа всегда указан как
json, независимо от реальногоContent-Type.
CodeEditorрендерится сformat="json"даже если ответ — HTML/XML/текст. Логичнее определять формат изresult.headers['content-type'], чтобы избежать некорректной подсветки синтаксиса.🤖 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 233 - 236, Update the CodeEditor usage in the response body section to derive its format from result.headers['content-type'] instead of always passing "json". Preserve the existing body rendering and ensure the selected format reflects the response Content-Type, including non-JSON responses.src/shared/ui/input/input.tsx (1)
21-36: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winДобавить ARIA-атрибуты для ошибок валидации.
<input>не получаетaria-invalidиaria-describedby, указывающий наerrorMessage. Скринридер не узнает о наличии ошибки — только визуальные пользователи увидят иконку/текст.♻️ Предлагаемое исправление
<input className={clsx(styles.input, error && styles.inputError)} id={inputId} ref={ref} {...rest} /> + <input + className={clsx(styles.input, error && styles.inputError)} + id={inputId} + ref={ref} + aria-invalid={!!error} + aria-describedby={error ? `${inputId}-error` : undefined} + {...rest} + /> {(error || withErrorPlug) && ( <div className={clsx(styles.errorContainer, withErrorPlug && styles.withPlug)}> {error && ( <> <AlertIcon className={styles.errorIcon} /> - <span className={styles.errorMessage}>{error}</span> + <span id={`${inputId}-error`} className={styles.errorMessage}> + {error} + </span> </> )} </div> )}🤖 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.tsx` around lines 21 - 36, Добавьте в компоненте Input доступные атрибуты для состояния ошибки: устанавливайте aria-invalid на input при наличии error и aria-describedby со ссылкой на сообщение ошибки. Присвойте span с классом styles.errorMessage стабильный идентификатор, связанный с inputId, и используйте его только когда текст ошибки отображается. Сохраните текущее поведение withErrorPlug и визуального отображения ошибки.src/pages/history-page/ui/history-page.test.tsx (1)
14-20: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winМок
Linkне проверяет локализованный URL.Мок на Lines 14–20 заменяет локализованный компонент обычным
<a>, поэтому проверки/homeна Lines 51–57 не обнаружат потерю/enили/ru. Добавьте в мок преобразование locale либо отдельно протестируйте реальный компонент навигации.Also applies to: 51-57
🤖 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/history-page/ui/history-page.test.tsx` around lines 14 - 20, Обновите мок Link в тесте history-page, чтобы он сохранял локаль при формировании href, используя текущий locale из тестового контекста или ожидаемый локализованный префикс. Убедитесь, что проверки ссылок в тесте подтверждают URL с /en или /ru, чтобы потеря локали обнаруживалась.src/features/auth/model/action.ts (1)
30-72: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick winОтсутствует серверная валидация входных данных перед вызовом Supabase.
signInWithPassword/signUpчитаютpasswordнапрямую изFormDataбез валидации формата/длины перед вызовом Supabase API. Поскольку server actions доступны как публичные эндпоинты, клиентская валидация (вauth-form) может быть обойдена прямым запросом. В проекте уже есть zod-схемы (src/features/auth-form/model/schemas.ts), которые можно повторно использовать здесь для defence-in-depth.🤖 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 30 - 72, Добавьте серверную валидацию входных данных в signInWithPassword и signUp перед вызовом Supabase, повторно используя zod-схемы из auth-form/model/schemas.ts. Обрабатывайте невалидные или отсутствующие email/password через существующий AuthActionResult и не вызывайте Supabase при ошибке валидации; сохраните текущую логику успешной аутентификации и mapAuthError для ошибок Supabase.app/[locale]/layout.tsx (1)
43-46: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
metadataне локализован.Title/description захардкожены на английском, хотя приложение явно поддерживает en/ru-роутинг. Для полноценной локализации имеет смысл заменить статичный
metadataнаgenerateMetadataсgetTranslations({locale}).🤖 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 43 - 46, Replace the static metadata export with an async generateMetadata function that receives the route locale and uses getTranslations({ locale }) to produce localized title and description values. Preserve the Metadata return shape and existing localized routing behavior.src/pages/history-page/lib/format-history.ts (2)
24-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winРучное форматирование даты без учёта локали.
formatTimestampвручную собирает строкуYYYY-MM-DD HH:mm, игнорируя локаль пользователя (en/ru). Можно заменить наIntl.DateTimeFormat(locale, {...})для консистентности с остальной локализацией приложения.🤖 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/history-page/lib/format-history.ts` around lines 24 - 32, Update formatTimestamp to use Intl.DateTimeFormat with the application’s locale and equivalent date/time options instead of manually assembling year, month, day, hour, and minute. Preserve the existing YYYY-MM-DD HH:mm-style output where required by the localized formatter and keep the timestamp parsing behavior unchanged.
3-11: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win3xx-статусы помечаются как ошибка.
Диапазон 300–399 (редиректы) не является ошибкой, но
getStatusLabel/getStatusColorпомечают любой статус вне 2xx как"ERR"/red. Для истории запросов это может быть некорректно/вводить в заблуждение пользователя.🛠️ Пример правки
export function getStatusLabel(status: number): string { if (status >= 200 && status < 300) return `${status} OK`; + if (status >= 300 && status < 400) return `${status} REDIRECT`; return `${status} ERR`; } export function getStatusColor(status: number): BadgeColor { if (status >= 200 && status < 300) return 'green'; + if (status >= 300 && status < 400) return 'gray'; return 'red'; }🤖 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/history-page/lib/format-history.ts` around lines 3 - 11, Update getStatusLabel and getStatusColor to treat HTTP statuses from 300 through 399 as successful/non-error outcomes alongside 2xx statuses. Preserve the existing “OK”/green behavior for 2xx and apply the same behavior to 3xx, while retaining “ERR”/red for all other statuses.src/features/schema-validator/lib/codemirror-linter.ts (1)
16-20: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winОтсутствует обработка ошибок вызова
validateSchema.Если асинхронная валидация схемы выбросит исключение, промис
runOpenapiLinterреджектится без обработки, и линтер CodeMirror не получит диагностики штатным образом. Стоит обернуть вызов в try/catch и возвращать пустой массив при ошибке.♻️ Предлагаемый рефакторинг
export const runOpenapiLinter = async (view: EditorView) => { const text = view.state.doc.toString(); - const results = await validateSchema(text); + let results; + try { + results = await validateSchema(text); + } catch { + return []; + }🤖 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-validator/lib/codemirror-linter.ts` around lines 16 - 20, Update runOpenapiLinter to wrap the asynchronous validateSchema call in try/catch; when validation throws, handle the error and return an empty diagnostics array while preserving the existing successful validation result.src/entities/endpoint/ui/request-body/request-body.test.tsx (1)
22-36: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winНе покрыт fallback-путь генерации примера.
Тесты проверяют только случай с явным
mediaType.example. ВеткаgenerateExample(mediaType.schema)(когдаexampleне передан) не покрыта тестом.🤖 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.test.tsx` around lines 22 - 36, Extend the RequestBody test coverage to exercise the fallback example-generation path by providing a media type with a schema but no explicit example, then assert that the rendered request body uses the generated example. Keep the existing explicit-example assertions unchanged and target the RequestBody rendering behavior around generateExample(mediaType.schema).src/shared/ui/button/button.tsx (1)
13-19: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winНет дефолтного
typeдля кнопки внутри форм.
{...rest}не задаётtypeпо умолчанию, поэтому внутри<form>кнопка неявно получитtype="submit"от браузера, если вызывающий код забудет явно указатьtype="button". Учитывая, что компонент используется как общий UI-кит в формах авторизации/регистрации, стоит явно задать безопасный дефолт.♻️ Предлагаемый фикс
-export function Button({ children, className, variant = 'primary', ...rest }: IProps): ReactNode { +export function Button({ children, className, variant = 'primary', type = 'button', ...rest }: IProps): ReactNode { return ( - <button className={clsx(styles.button, styles[variant], className)} {...rest}> + <button type={type} className={clsx(styles.button, styles[variant], className)} {...rest}> {children} </button> ); }🤖 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/button/button.tsx` around lines 13 - 19, Update the Button component’s rendered button element to default its type to "button" while preserving any explicit type supplied through rest props. Keep the existing variant, className, children, and other prop behavior unchanged.src/widgets/header/ui/header.tsx (1)
11-14: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winПараллелизуйте независимые запросы
getTranslationsиgetCurrentUser.Оба вызова не зависят друг от друга, но выполняются последовательно в компоненте, который рендерится на каждой странице.
Promise.allсократит суммарную задержку рендеринга хедера.Предложение
export async function Header() { - const t = await getTranslations('Header'); - const user = await getCurrentUser(); + const [t, user] = await Promise.all([getTranslations('Header'), getCurrentUser()]);🤖 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 11 - 14, Обновите компонент Header, чтобы независимые вызовы getTranslations и getCurrentUser выполнялись параллельно через Promise.all, сохранив их результаты в переменных t и user для последующего рендеринга.src/widgets/header/ui/logo/logo.tsx (1)
7-18: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueРассмотрите
priorityдля логотипа в хедере.Логотип рендерится на каждой странице в хедере и потенциально виден при первой загрузке. Можно добавить
priorityкnext/image, чтобы избежать lazy-loading для элемента, который всегда виден сразу.Предложение
- <Image src="/logo.png" alt="AURA Editor" width={40} height={40} /> + <Image src="/logo.png" alt="AURA Editor" width={40} height={40} priority />🤖 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/logo/logo.tsx` around lines 7 - 18, Update the Image component in Logo to use priority loading for the header logo, ensuring it is fetched immediately rather than lazy-loaded while preserving the existing source, dimensions, and alt text.package.json (1)
24-30: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winРасширьте проверки за пределы
src.Команды форматирования и ESLint не проверяют
app,pages,proxy.ts, конфигурационные файлы и локализации. В результате ошибки в release-критичных маршрутах и API могут пройти CI незамеченными. Используйте явные globs или запускайте проверки для всех исходных каталогов приложения.🤖 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 `@package.json` around lines 24 - 30, Расширьте команды format, ci:format, lint и lint:fix в package.json, чтобы они проверяли не только src, но также app, pages, proxy.ts, конфигурационные файлы и локализации через явные globs или полный набор исходных каталогов приложения. Обновите validate так, чтобы он использовал расширенные проверки.src/shared/ui/badge/badge.tsx (1)
8-16: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueНесоответствие имени интерфейса и компонента.
Интерфейс называется
StatusBadgeProps, а компонент —Badge. Для консистентности лучше переименовать вBadgeProps.🤖 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/badge/badge.tsx` around lines 8 - 16, Rename the StatusBadgeProps interface to BadgeProps and update the Badge component’s parameter type reference accordingly, preserving all existing props and behavior.src/shared/ui/badge/badge.module.scss (1)
1-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueУбрать пустые строки перед декларациями (Stylelint).
Правило
declaration-empty-line-beforeтребует отсутствия пустой строки перед декларацией внутри блока — сработало на строках 7, 12, 16.🔧 Предлагаемое исправление
.statusBadge { display: inline-flex; align-items: center; justify-content: center; gap: 0.8rem; - border-radius: 4px; border: 1px solid var(--badge-border-color); background-color: var(--badge-color); padding: 4px 12px; - font-family: var(--font-ui), monospace; white-space: nowrap; transition: color 0.3s ease; - font-size: 12px; color: var(--badge-text-color); }🤖 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/badge/badge.module.scss` around lines 1 - 18, Remove the blank lines between declaration groups in the .statusBadge rule so every declaration directly follows the previous declaration, satisfying the declaration-empty-line-before Stylelint rule.Source: Linters/SAST tools
src/widgets/footer/ui/footer.tsx (1)
23-30: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueЗахардкоженный год и нелокализованная строка "RS School 2026".
В отличие от остального текста, отрендеренного через
t(...), эта строка не локализована, а год2026со временем устареет.🤖 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/footer/ui/footer.tsx` around lines 23 - 30, Update the footer school link text in the component containing the styles.schoolName anchor to use the existing localization mechanism via t(...) and generate the displayed year dynamically instead of hardcoding 2026, preserving the current link attributes and styling.src/shared/api/supabase/middleware.ts (1)
38-39: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value
startsWithбез учёта границы сегмента пути.
PROTECTED_PATHS/AUTH_PATHSматчатся черезpathname.startsWith(path), поэтому гипотетический маршрут вроде/history-exportтоже будет считаться защищённым/auth-страницей. Сейчас конфликтующих маршрутов нет, но стоит матчить по границе сегмента (===илиstartsWith(path + '/')).🤖 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 38 - 39, Update the path checks in the isProtected and isAuthPage calculations to match only exact paths or descendants at a segment boundary, using equality or a path prefix followed by "/". Preserve matching for the configured route itself and nested routes while preventing similarly prefixed routes such as "/history-export" from matching.src/shared/ui/toast/toast.tsx (1)
76-99: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winОтсутствует доступность для скринридеров.
Контейнер тостов не имеет
role="status"/aria-live, поэтому появление уведомлений не будет анонсироваться пользователям скринридеров. Кнопка закрытия (Line 93-95) — иконка безaria-label, поэтому у неё нет доступного имени.♿️ Предлагаемое исправление
- <div className={styles.container}> + <div className={styles.container} role="status" aria-live="polite"> {toasts.map((toast) => { ... - <button type="button" className={styles.closeButton} onClick={() => closeToast(toast.id)}> + <button + type="button" + className={styles.closeButton} + aria-label="Close" + onClick={() => closeToast(toast.id)} + > <CloseIcon className={styles.closeIcon} /> </button>🤖 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/toast/toast.tsx` around lines 76 - 99, Update the toast container in the component rendering the `toasts.map` list with an appropriate live-region role and `aria-live` setting so newly added notifications are announced to screen readers. Add an accessible name to the close button containing `CloseIcon`, while preserving its existing `closeToast(toast.id)` behavior.src/shared/ui/toast/toast.module.scss (1)
5-5: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueЗахардкоженный
z-index: 7777вместо переменной.В остальной части стилей (например,
#root { z-index: var(--z-base); }в_base.scss) z-index управляется через CSS-переменные. Магическое число7777здесь ломает эту конвенцию и усложняет управление слоями в будущем.🤖 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/toast/toast.module.scss` at line 5, Replace the hardcoded z-index value in the toast styles with the established CSS z-index variable convention, reusing the appropriate layer variable such as --z-base instead of introducing a new magic number.src/entities/endpoint/ui/try-it-out-form/try-it-out-form.test.tsx (1)
13-18: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winПолная замена
navigatorбез очистки и сохранения остальных свойств.
vi.stubGlobal('navigator', { clipboard: { writeText: mockWriteText } })подменяет весь объектnavigatorцеликом, теряя остальные свойства (userAgentи т.д.), которые могут использоваться React/jsdom/другими зависимостями. Стаб выполняется на уровне модуля и не откатывается черезvi.unstubAllGlobals()вafterEach/afterAll.♻️ Предлагаемое исправление
-const mockWriteText = vi.fn(); -vi.stubGlobal('navigator', { - clipboard: { - writeText: mockWriteText, - }, -}); +const mockWriteText = vi.fn(); + +beforeEach(() => { + vi.stubGlobal('navigator', { + ...navigator, + clipboard: { writeText: mockWriteText }, + }); +}); + +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, Update the module-level navigator mock around mockWriteText to preserve the existing navigator properties while overriding only clipboard.writeText, and add lifecycle cleanup that restores the global stub after tests via the appropriate Vitest unstub mechanism. Ensure each test starts with the original navigator state intact.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@README.md`:
- Around line 87-95: Update the fenced directory-tree block in README so it
declares the text language identifier, keeping the existing tree content
unchanged. Locate the markdown fence around the src/ directory listing and
change only the opening fence to use the same block with text specified, which
satisfies the markdownlint MD040 requirement.
- Around line 165-167: Обновите раздел Prerequisites в README: замените
минимальную версию Node.js с v18+ на v20.9+, оставив требование npm без
изменений.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| ``` | ||
| src/ | ||
| ├── app/ → Global styles (SCSS variables, mixins, constants, base reset) | ||
| ├── pages/ → Page-level compositions (Home, About, History, Login, Register) | ||
| ├── widgets/ → Complex UI blocks (Header, Footer, SwaggerEditor, SwaggerViewer) | ||
| ├── features/ → Business logic slices (Auth, FormatConverter, SchemaValidator, History, etc.) | ||
| ├── entities/ → Domain models (Endpoint — types, grouping, method badge, parameter display) | ||
| └── shared/ → Reusable UI kit, Supabase clients, i18n config, hooks, types | ||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Укажите язык для блока с деревом каталогов.
Fenced code block на Line 87 не содержит идентификатор языка. markdownlint сообщает MD040. Добавьте text.
Предлагаемое исправление
-```
+```text
src/
├── app/
...
└── shared/</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **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.
```suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.23.2)
[warning] 87-87: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 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 `@README.md` around lines 87 - 95, Update the fenced directory-tree block in
README so it declares the text language identifier, keeping the existing tree
content unchanged. Locate the markdown fence around the src/ directory listing
and change only the opening fence to use the same block with text specified,
which satisfies the markdownlint MD040 requirement.
Source: Linters/SAST tools
| ### Prerequisites | ||
|
|
||
| - **Node.js** v18+ and **npm** v9+ |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate files =="
fd -a '^(README\.md|package\.json|package-lock\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb)$' . | sed 's#^\./##'
echo
echo "== README prerequisites section =="
if [ -f README.md ]; then
nl -ba README.md | sed -n '150,200p'
fi
echo
echo "== package manifests with next =="
for f in package.json; do
[ -f "$f" ] || continue
echo "--- $f ---"
python3 - <<'PY'
import json, pathlib
for p in pathlib.Path('.').rglob('package.json'):
try:
data=json.loads(p.read_text())
except Exception as e:
continue
deps={}
for k in ('dependencies','devDependencies','peerDependencies'):
deps.update(data.get(k,{}) or {})
if 'next' in deps:
print(p, deps['next'])
PY
done
echo
echo "== lockfile next versions =="
for f in package-lock.json pnpm-lock.yaml yarn.lock bun.lockb; do
[ -f "$f" ] && echo "--- $f ---" && rg -n '"?next"?|next@|next:|node_modules/next|/next@' "$f" | head -80 || true
done
echo
echo "== repository next config mentioning webpack (if any) =="
rg -n "webpack|reactWebpack|compiler|experimental|nextVersion|engines|nodejs|Node\.js" package.json README.md . 2>/dev/null | head -200 || trueRepository: FierceSloth/swagger-editor-app
Length of output: 365
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== README around prerequisites =="
awk 'NR>=150 && NR<=200 { printf "%d\t%s\n", NR, $0 }' README.md
echo
echo "== package.json next scripts/engines/next =="
python3 - <<'PY'
import json
from pathlib import Path
for path in [Path('package.json')]:
data=json.loads(path.read_text())
print("name:", data.get('name'))
print("engines:", data.get('engines'))
props=('scripts','dependencies','devDependencies','peerDependencies')
next_found=False
for prop in props:
val=data.get(prop,{}) or {}
for k,v in val.items():
if k.lower() in ('next','node') or k=='node':
next_found=True
if k=='next':
print(f"{prop}.next={v}")
if 'scripts' in data:
for k,v in data['scripts'].items():
if any(x in v.split() for x in ('node','.next','next','webpack')):
print(f"scripts.{k}={v}")
PY
echo
echo "== lockfile next package entries =="
python3 - <<'PY'
import json
from pathlib import Path
p=Path('package-lock.json')
if p.exists():
data=json.loads(p.read_text())
root=pkg=data.get('packages',{}).get('',{})
print("root next version:", pkg.get('dependencies',{}).get('next') or pkg.get('devDependencies',{}).get('next') or pkg.get('peerDependencies',{}).get('next'))
pkgs=data.get('packages',{})
for k,v in pkgs.items():
if k.endswith('node_modules/next') or k == 'node_modules/next':
print("package",k, "version", v.get('version'), "resolved", v.get('resolved'))
PY
echo
echo "== files with next/nextjs/webpack references =="
rg -n -i "next(\.js|@|js|) v?16|nextjs 16|webpack|requires|requires node|node\.js v18|node\.js v20|engines|nodejs|supported" README.md package.json package-lock.json 2>/dev/null || trueRepository: FierceSloth/swagger-editor-app
Length of output: 25993
🌐 Web query:
Next.js 16 Node.js 20.9 minimum version Node.js support
💡 Result:
Next.js 16 requires a minimum Node.js version of 20.9.0 or higher [1][2]. This change was implemented because Node.js v18 reached its End-of-Life (EOL), prompting the move to the first Long Term Support (LTS) version of Node.js 20 [3][4]. Support for Node.js 18 has been removed in Next.js 16 [1][5].
Citations:
- 1: https://nextjs.org/blog/next-16
- 2: https://rc.nextjs.org/docs/app/guides/upgrading/version-16
- 3: vercel/next.js@11762a7
- 4: [Breaking] Bump minimum Node.js version to
>=20.9.0vercel/next.js#83113 - 5: https://nextjs.org/docs/app/guides/upgrading/version-16
Исправьте минимальную версию Node.js.
README указывает Node.js v18+, но package.json использует next 16.2.9. Next.js 16 требует Node.js 20.9+; Node.js 18 больше не поддерживается. Значит, установщик с Node.js 18 получит ошибку до запуска проекта. Укажите Node.js v20.9+.
🤖 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 `@README.md` around lines 165 - 167, Обновите раздел Prerequisites в README:
замените минимальную версию Node.js с v18+ на v20.9+, оставив требование npm без
изменений.
Important
🔑 Required Environment Variables for Local Running
To run the application locally (enabling authorization, history logging, and CORS proxying), you must configure the Supabase keys. Without them, the local server will throw a
Missing environment variableerror..env(or.env.local) file in the root directory of the project.📋 Trello Task ID
⚡️ Summary
Merge the
developbranch intomainfor the final release of the Swagger/OpenAPI UI application. This PR encompasses the complete implementation of the REST client and API specification editor according to the project requirements.13.07.2026/ Deadline:13.07.2026🏆 Evaluation Criteria (550 max)
Feature 1: App Header (60/60)
Feature 2: Sign In / Sign Up (50/50)
Feature 3: Swagger Editor (120/120)
Feature 4: Swagger Viewer (120/120)
Feature 5: History and Analytics (70/70)
Feature 6: About Page (25/25)
Feature 7: General Requirements (55/55)
Feature 8: YouTube Video (50/50)
⛔ Penalties (0 points applied)
@ts-ignoreor code-smells present.Summary by CodeRabbit
Новые возможности
Документация
Тесты