Enable every plugin recommended preset and replace Biome with ESLint formatting. Preserve API contracts and JSX whitespace; verify source, tests, builds and tooling.
21 KiB
WealthLedger frontend
React/Vite-клиент WealthLedger. Клиент получает данные только через typed API backend; прямые вызовы T-Bank из frontend не допускаются.
Быстрый старт
Требуется Node 24 (.nvmrc). Создайте .env из примера и установите
зависимости строго из lockfile:
cp .env.example .env
nvm use --silent
npm ci
npm run dev
VITE_API_BASE_URL по умолчанию указывает на http://localhost:3000.
Для commits установите Gitleaks
8.30.1 в PATH (macOS: brew install gitleaks). Pre-commit сначала проверяет
staged diff с полной редакцией секретов, затем запускает formatting и FSD checks.
Находка или отсутствие Gitleaks блокирует commit.
Проверка этого поведения: node --test scripts/test-pre-commit.mjs.
Контейнерный image
Dockerfile имеет targets development (Vite HMR и proxy /api/ во внутренний backend)
и production (nginx на 8080, SPA fallback и same-origin API proxy). Node соответствует .nvmrc.
Build context ограничен .dockerignore; .env, local DB и host node_modules
не попадают в image. Изменение packages/tokens или packages/ui требует rebuild development
image, если локальный запуск использует bind-mount только src/public.
docker build --target development -t wealthledger-frontend:development .
docker build --target production -t wealthledger-frontend:production .
Gitea image.yml запускается на защищённом release tag vX.Y.Z, проверяет
package/lock version и canonical gates. Runner ubuntu-latest должен иметь
Docker/buildx. Образы хранятся в Nexus:
nexus.personal.ksv741.ru/docker-hosted/wealthledger/frontend. Пользователь wealthledger-ci
задаётся Actions secrets NEXUS_USERNAME/NEXUS_PASSWORD; эта же учётная
запись используется сервером для загрузки образов. Docker endpoint и token realm должны использовать
HTTPS; в docker-hosted включается запрет redeploy. Прежние Gitea secrets
сохраняются на время перехода и не передаются в Nexus.
Публикуются semver tags, без latest; существующие release tags не перезаписываются. Production выбирает опубликованный version tag.
Compose topology принадлежит workspace, эксплуатационная последовательность —
документация,
страница architecture/deployment.md.
Проверка публикации требует настроенного registry/runner; локальный build
не доказывает package permissions.
Установка как приложение (PWA)
Production-сборка поддерживает установку WealthLedger в отдельное окно через
vite-plugin-pwa. Нужен HTTPS или localhost. В Chrome/Edge выберите «Установить
WealthLedger» в меню браузера или значок установки в адресной строке; на iPhone
и iPad — Safari → «Поделиться» → «На экран Домой». Доступность установки зависит
от браузера и ОС.
Service worker кеширует только статическую оболочку, включая страницы SPA. Вход, финансовые данные и сохранение изменений требуют сети: API, токены и ответы API не сохраняются в Cache Storage. Это не автономный финансовый клиент. Новая версия загружается в фоне и применяется после закрытия всех вкладок и окон WealthLedger и повторного открытия; открытые формы автоматически не перезагружаются.
Локальная проверка: nvm use --silent, npm run build, npm run preview.
В DevTools → Application проверьте Manifest, Service Workers и Cache Storage.
В режиме npm run dev и в Storybook service worker не включается.
Проверка
nvm use --silent
npm ci
npx --no-install playwright install chromium
npm run verify
Команда проверяет, что generated OpenAPI types соответствуют committed snapshot, затем запускает strict TypeScript, ESLint и проверку его конфигурации, один coverage-backed запуск Vitest, Knip, dependency rules приложения и stories, сборки приложения и Storybook.
npm run lint запускает ESLint с --max-warnings=0; npm run lint:fix
применяет автофиксы. Конфигурация подключает рекомендованные
наборы всех установленных плагинов: TypeScript, React, Hooks, Refresh, Query,
Unicorn, import-x, SonarJS, RegExp, Security, Perfectionist, Stylistic,
Vitest, Testing Library, jest-dom и Storybook. Правила React, тестов и stories
применяются к соответствующим файлам; generated/build artifacts исключены.
Stylistic отвечает за форматирование JS/TS/TSX, Perfectionist — за сортировку.
Сохраняются табы, двойные кавычки и точки с запятой. Biome удалён; Prettier
не используется. CSS, JSON и Markdown не форматируются через ESLint.
lint-staged исправляет JS/TS/TSX перед commit. lint:eslint сначала собирает
private packages, чтобы анализ типов использовал актуальные declarations.
npm run test:lint проверяет действующие presets и ошибочные примеры.
Точечные исключения в исходниках объясняют контракты и ограничения статического
анализа; изменение nullable API fields, query keys или порядка race-операций
ради линтера недопустимо. Архитектуру проверяет dependency-cruiser, поведение —
Vitest/MSW и Chromium. Линтеры не заменяют semantic/security review.
jsx-a11y без поддержки ESLint 10 остаётся отложенным в
workspace issue #18.
Vitest включает JSDOM-тесты и проверку геометрии секций позиций в headless
Chromium при ширинах 375 и 1280 px. Browser project не использует JSDOM setup
и его заглушки layout API. Только браузерная проверка:
npm run test:run -- --project='browser-*'. После обновления Playwright повторите
установку Chromium; CI устанавливает его с --with-deps для Linux.
Единый .gitea/workflows/verify.yml запускает commits → security → verify
последовательно на PR; на push в develop/main — security → verify.
Рабочие ветки проверяются после открытия PR, без дублирующего push-запуска.
Изменение заголовка PR тоже повторяет проверки Conventional Commits.
Новый запуск отменяет устаревший для того же PR/ветки и типа события
(требуется Gitea 1.26+). Ежедневно в 05:17 UTC выполняется только security.
Job security проверяет полную доступную историю Gitleaks 8.30.1 и выполняет
npm audit --include=dev --audit-level=low. Любой advisory блокирует security job;
исключений frontend нет. Локально можно выполнить те же команды:
gitleaks git --log-opts=--all --redact=100 --no-banner и
npm audit --include=dev --audit-level=low. Audit требует доступа к npm registry;
проверка секретов выполняется локально и не выводит их значения.
Имена jobs commits, security, verify сохранены, но Gitea включает имя
workflow в статус. При внедрении администратор должен заменить required checks
для защищённых веток на Frontend verify / commits (pull_request),
Frontend verify / security (pull_request) и
Frontend verify / verify (pull_request), удалив старые имена и push-статусы,
если они требовались. Все три PR-проверки должны оставаться обязательными.
Публикация образов по тегам остаётся в image.yml.
Последовательность jobs ограничивает один запуск; для ограничения нагрузки всего сервера настройте
runner.capacity: 1 у общего runner и учтите остальные зарегистрированные
runners. Конфигурация runner управляется вне этого репозитория.
TypeScript остаётся на 5.9.3: openapi-typescript@7.13.0 требует peer ^5.x.
Обновление до TypeScript 7 из Renovate dashboard откладывается до совместимого
релиза генератора; --force/--legacy-peer-deps для обхода этого ограничения
не используются.
Если backend-контракт изменился,
обновите src/shared/api/spec/openapi.json копированием backend OpenAPI
document и затем выполните npm run openapi:generate.
SonarQube
Проект wealthledger-frontend использует настройки из
sonar-project.properties. Анализируются исходники src; тесты учитываются
отдельно, а Storybook fixtures, test helpers, generated API types и OpenAPI
snapshot исключены. npm run test:coverage (также входит в npm run verify)
создаёт coverage/lcov.info для импорта покрытия.
Для первого анализа установите SonarScanner CLI, совместимый с версией сервера, и выполните из корня frontend:
nvm use --silent
npm ci
npm run test:coverage
# SONAR_TOKEN передайте через окружение; не сохраняйте токен в репозитории.
sonar-scanner
В Gitea откройте frontend → Settings → Actions → Secrets и добавьте
SONAR_TOKEN с токеном анализа проекта. Переименовывать основную ветку в
SonarQube не требуется; sonar.branch.name не задаётся.
Используется Community Edition 9.9.8: CI отправляет только
push в develop, после успешного verify, и ожидает результат Quality Gate.
PR и остальные ветки проходят обычные проверки без отправки в SonarQube.
Отрицательный Quality Gate или ошибка scanner завершает verify с ошибкой.
Runner должен поддерживать Docker actions и иметь HTTPS-доступ к
https://sonarqube.personal.ksv741.ru, GitHub и Docker Hub. Docker action
SonarSource закреплён на commit версии 2.3.0; scanner запускается отдельно от
Node 24, используемого для сборки. tsconfig.sonar.json содержит совместимые
со старым анализатором TS настройки; приложение проверяется штатным TypeScript
5.9 через npm run verify. После обновления сервера пересмотрите scanner и
возможность использовать основной tsconfig. Успешный локальный verify не
доказывает доступность сервера и успешность анализа в CI.
UI-каталог Storybook
После nvm use --silent выполните npm run dev:catalog; статическая сборка —
npm run build:catalog. Каталог использует общую тему приложения, вымышленные
данные и локальные действия без application API. Примеры не доказывают
восстановление реального запроса. Визуальные роли описаны в
UI convention.
Документация
- AGENTS: правила и источники
- Выбор owner/FSD
- UI, state, формы и компоненты
- Data/API/cache
- Testing
- UI-каталог Storybook
Checkout frontend содержит все входы сборки и проверок. Публичная схема API
поступает как отдельный artifact; команды frontend используют только её
локальную копию и не обращаются к исходникам или CI сервера. Доставка новой
схемы — явное обновление snapshot с review и npm run openapi:generate.
Runtime URL API задаётся окружением, а не расположением другого репозитория.
Разработка идёт напрямую по задаче пользователя; OpenSpec/SDD — по явному запросу.
Knip исключает conventional-changelog-conventionalcommits: release-it загружает
preset по имени из .release-it.json. Версия preset закреплена напрямую.
Релизы
Репозиторий выпускается независимо. develop — интеграция, main — принятые
релизы. Работа: codex/<task> от актуального develop, PR в develop.
Обычные PR допускают squash; release и обратная синхронизация сохраняют историю.
Commits и PR titles — Conventional Commits, включая spec:. Версии вручную не повышай.
- Получи
main,developи теги:git fetch origin --tags. Убедись, чтоdevelopсодержит последний релиз. Создайrelease/<name>от проверенногоdevelop;nvm use --silent,npm ci. Hotfix начинается отmainвrelease/hotfix-<name>и проходит тот же процесс. - На чистой ветке выполни
npm run release:preview, просмотри версию/changelog, затемnpm run release:prepare. Команда создаётchore(release): X.Y.Z, обновляет manifest/lockfile/CHANGELOG; тег и push не выполняет. Не обходи guards ветки, чистого дерева, отсутствующих тегов или уже подготовленной версии. - Проверь diff и штатные gates этого репозитория. Отправь только release-ветку,
открой PR в
mainс заголовкомchore(release): X.Y.Z. После зелёныхverify,security,commitsвыполни fast-forward-only merge. Еслиmainизменился, согласуй историю и повтори проверки кандидата. - Получи удалённый
main, сравни его HEAD с проверенным release SHA и версией manifest/lockfile. Создай аннотированныйvX.Y.Zименно на этом SHA:git tag -a vX.Y.Z <release-sha> -m "Release X.Y.Z", затем отправь толькоgit push origin refs/tags/vX.Y.Z. Не запускай release-it повторно наmain. - Верни release-коммит через PR
main → developбез squash/rebase; проверь, чтоdevelopсодержит тег. Опубликованные теги не перемещай. При сбое после merge создай отсутствующий тег без нового bump; до merge исправь и проверь существующий кандидат без повторного повышения версии.
feat: повышает minor, fix:/perf: и прочие разрешённые типы — patch;
!/BREAKING CHANGE: — major, включая версии до 1.0. chore(release):
исключён из рекомендации и changelog. Конфигурация — .release-it.json.
В Gitea для main/develop должны быть запрещены прямой/force push и обход
администратором, обязательны verify, security, commits; теги v* защищены.
Workflow сам не включает эти настройки. Отдельное review approval для одного
владельца не требуется. Npm publishing, deploy и Gitea Releases не включены.
Локальные пакеты
packages/tokens — private npm workspace с единственным export
@wealthledger/tokens/tokens.json. packages/ui экспортирует собранные
@wealthledger/ui/theme (JS + declarations) и @wealthledger/ui/styles.css.
Корневой export @wealthledger/ui содержит EntryCard, StateView и LoadingSkeleton;
Потребители импортируют компоненты напрямую из @wealthledger/ui.
CSS явно подключается после Mantine; providers остаются в приложении/Storybook.
Тема доступна через @wealthledger/ui/theme; compatibility re-exports удалены.
JSON не требует сборки. npm ci связывает workspaces, а существующие команды
разработки, проверок и сборки сначала выполняют npm run build:packages.
Library build использует отдельный Vite config без app plugins и TypeScript
для declarations. После изменения package sources перезапустите npm run dev
или npm run dev:catalog; отдельный watch-процесс пока не нужен.
Начальная версия manifest взята из приложения; отдельный release-процесс
и публикация не настроены.
Private @wealthledger/icons экспортирует AddIcon, EditIcon, DeleteIcon
и type IconProps. Единственный source рисунка — TSX в packages/icons/src/svg;
поставка содержит ESM/declarations, без raw SVG, CSS, Mantine и motion.
React — peer/external. Размер size по умолчанию 24, strokeWidth — 1.5;
цвет наследуется через currentColor, SVG props можно передать явно.
В action используйте декоративный <AddIcon size={20} strokeWidth={2} />,
доступное имя задавайте кнопке. Standalone пример:
<EditIcon aria-hidden={false} role="img" aria-label="Редактирование" />.
Поддерживается также стандартный aria-labelledby; подпись выбирает caller.
Card/Cards используют пакетные Add/Edit/Delete с прежними размерами/strokeWidth.
Restore/category SVG и предметный BankOperationIcon остаются в приложении.