# Конфигурация проекта prescriptions-frontend

Документ описывает способы конфигурирования микрофронтенда `prescriptions-frontend` (Module Federation `srx_prescriptions`, экспонирует `./PrescriptionsPage`), его переменные сборки/CI и параметры деплоя.

## Способы конфигурирования

В отличие от backend-сервисов, у фронтенда **нет рантайм-конфигурации через `.env`**: собранный бандл — статические файлы, которые раздаёт nginx. Всё поведение задаётся **на этапе сборки** одной переменной — `BUILD_ENV`.

- `env.js` читает `process.env.BUILD_ENV` и валидирует его против списка `local`/`stage`/`prod`/`contour`/`preprod` (иначе — ошибка сборки `set BUILD_ENV one of ...`);
- `webpack.config.js` через `DefinePlugin` внедряет глобальные константы `BUILD_ENV` и `STORYBOOK` в бандл;
- `build.config.js` по `BUILD_ENV` выбирает режим сборки (`mode`/`devtool`);
- `module/api/hosts.ts` и `module/api/module-hosts.ts` содержат карты хостов по окружениям; SDK (`@sarex-team/sdk-js`) на рантайме выбирает нужный хост по глобальной константе `BUILD_ENV` (по умолчанию `prod`).

Отдельного конфиг-файла (yaml/toml) у приложения нет.

### Значения `BUILD_ENV`

| `BUILD_ENV` | `mode` | `devtool` | Назначение |
| --- | --- | --- | --- |
| `local` | `development` | `eval-source-map` | Локальная разработка (dev-server, storybook), `httpService` → `original` |
| `stage` | `development` | `eval-source-map` | Стенд stage |
| `preprod` | `production` | `source-map` | Предпрод |
| `prod` | `production` | `source-map` | Прод |
| `contour` | `production` | `source-map` | Изолированный контур (относительные пути хостов) |

## Переменные сборки и CI

| Переменная | Где используется | Назначение |
| --- | --- | --- |
| `BUILD_ENV` | `env.js`, `webpack.config.js`, `Dockerfile` (ARG), `.gitlab-ci.yml` (`--build-arg`) | Целевое окружение сборки. Обязательна |
| `NPM_TOKEN` | `.npmrc`, `Dockerfile` (ARG), `.gitlab-ci.yml` (`--build-arg`) | Токен доступа к приватному npm-реестру `nexus.infra.sarex.io` |
| `STORYBOOK` | `webpack.config.js` (`DefinePlugin`), `module/pages/index.tsx` | Флаг сборки под Storybook (`"true"`/`"false"`) |

Cypress-тесты берут учётные данные из `cypress.env.json` (пример — `cypress.env-example.json`): `SRX_LOGIN`, `SRX_PASSWORD`.

Версия Node для разработки — `v20.16.0` (`.nvmrc`).

## Хосты по окружениям

Базовые API-хосты подставляются из `module/api/hosts.ts` по `BUILD_ENV` (детальная разбивка по сервисам — в `ENDPOINTS.md`):

| Окружение | Базовый API | Пример (`documentations`) |
| --- | --- | --- |
| `local` / `stage` | `https://stage-api.sarex.io` | `https://stage-api.sarex.io/documentations/api/v1` |
| `preprod` | `https://api.preprod.sarex.io` | `https://api.preprod.sarex.io/documentations/api/v1` |
| `prod` | `https://api.sarex.io` | `https://api.sarex.io/documentations/api/v1` |
| `contour` | относительные пути | `/documentations/api/v1` |

Удалённый модуль (Module Federation) `documentations` подключается по `module/api/module-hosts.ts` (`remoteEntry.js`).

## Запуск и скрипты (`package.json`)

| Команда | Назначение |
| --- | --- |
| `npm run serve-module` | Dev-server (`webpack.dev.js`, порт `9001`, https, proxy `/api`, `/admin` на `appUrl`), `BUILD_ENV=local` |
| `npm run storybook` | Storybook (порт `9000`, https), `BUILD_ENV=local` |
| `npm run start` / `test:dev` | Параллельный запуск serve-module + storybook (+ cypress в `test:dev`) |
| `npm run build-module` | Продакшн-сборка модуля (`webpack --config webpack.config.js`) |
| `npm run build-storybook` | Сборка статики Storybook |
| `npm run cypress:open` | Запуск e2e-тестов Cypress |
| `npm run lint` / `lint:ts` | Prettier / проверка типов `tsc --noEmit` |

## Сборка образа (`Dockerfile`)

Двухстадийная сборка:

1. `node:15` — установка зависимостей (`npm i --legacy-peer-deps` с `NPM_TOKEN`), `npm run lint`, `BUILD_ENV=$BUILD_ENV npm run build-module` → `/app/dist`;
2. `nginx:mainline-alpine-otel` — копирование `dist` в `/dist` и конфига `nginx/nginx.conf`.

Build-args: `BUILD_ENV`, `NPM_TOKEN`.

nginx (`nginx/nginx.conf`) раздаёт статику из `/dist`, отдаёт `/ping` → `{"result": "ok"}` (healthcheck) и запрещает кеширование `/module/remoteEntry.js` (`Cache-Control: no-store`).

## CI/CD (`.gitlab-ci.yml`)

Пайплайн подключает общие шаблоны `generic/common-ci` (`common-security-scan.yaml`, `universal-pipeline.yaml`, ref `apps-business`). `SERVICE_NAME=prescriptions-frontend`. Окружение переключается по ветке/тегу (`workflow.rules`):

| Условие | STAND | NAMESPACE | BUILD_ENV | CHART_VERSION |
| --- | --- | --- | --- | --- |
| ветка `stage` | `stage` | `proc` | `stage` | `1.0.0-stage` |
| ветка `master` | `preprod` | `prescriptions-preprod` | `preprod` | `1.0.0-preprod` |
| тег (`CI_COMMIT_TAG`) | `production` | `prescriptions-prod` | `prod` | `1.0.0-prod` |
| merge request | — | — | — | сборка образа отключена (`ENABLE_BUILD_IMAGE=false`) |

Деплой параметризуется через `HELM_SET_ARGS` (образ, `global.env`, `commitSha`, `gitlabUri`, `gitlabJobUrl`, `owner`).

## Helm-чарт проекта (`.helm`)

`Chart.yaml`: зависимость `universal-chart` (`oci://cr.yandex/.../charts`, версия `0.1.7`).

`values.yaml` (`universal-chart.services.frontend`):

- `deployment.name = prescription-frontend`, `replicaCount = 1`, `port = 80`, `revisionHistoryLimit = 10` (prod — `15`);
- `image.name = cr.yandex/crp3ccidau046kdj8g9q/prescription-frontend`, `pullPolicy = IfNotPresent`;
- `service.name = prescriptions-frontend-service`, `type = ClusterIP`, `port/targetPort = 80`;
- `imagePullSecrets = dockerhub`;
- probes (`liveness`/`readiness`) на `/ping:80` заданы, но **выключены** (`enabled: false`);
- `envs: []`, `secretEnvs: []` — переменных окружения контейнеру не передаётся;
- ресурсы: `requests` `memory 100Mi`, `cpu 100m`.

## Инфраструктура (`iac/apps/prescriptions`)

Разворачивается через Kustomize. Состав каталога:

| Путь | Назначение |
| --- | --- |
| `base/namespace.yaml` | Namespace `prescriptions` с `istio-injection: enabled` |
| `base/deployment.yaml` | Deployment `frontend`, образ `cr.yandex/.../prescriptions-frontend:production_...`, порт `80`, `requests` `cpu 25m`/`memory 100Mi`, `imagePullSecrets: regcred` |
| `base/service.yaml` | Service `frontend-service`, `ClusterIP`, порт `80` |
| `base/kustomization.yaml` | Сборка base (namespace + deployment + service) |
| `yc-k8s-test/` | Оверлей поверх `../base` (патч `replicas.yaml` закомментирован) |
| `brusnika-prod/`, `brusnika-stage/` | Оверлеи (см. замечание ниже) |

## Замечания и потенциальные проблемы

- **Оверлеи `brusnika-prod` / `brusnika-stage`** сейчас содержат `HelmRelease` бэкенда `measurements` (namespace `measurements`, образ `documentations`), не относящийся к prescriptions — похоже на копипаст-заготовку, которую нужно заменить на конфигурацию prescriptions-frontend либо удалить.
- **Два способа описания деплоя**: helm-чарт в репозитории фронтенда (`.helm`, `universal-chart`) и Kustomize-манифесты в инфраструктуре (`iac/apps/prescriptions`) описывают один и тот же сервис по-разному — стоит зафиксировать единый источник истины.
- **Несогласованные имена**: `SERVICE_NAME=prescriptions-frontend` (мн. ч.), а `deployment.name`/`image.name` в `.helm` — `prescription-frontend` (ед. ч.). В инфра-манифестах deployment называется просто `frontend`.
- **Версии Node расходятся**: разработка — `v20.16.0` (`.nvmrc`), сборка образа — `node:15` (`Dockerfile`).
- **Мёртвая конфигурация**: экспорт `hosts` в `networking.config.js` (внедрение `__<service>_host`) и `module/Env` (`IEnv`, `process.env as IEnv`) в коде модуля не используются; `dotenv-webpack` присутствует в devDependencies, но не подключён в `webpack.config.js`. `networking.config.js` реально используется только в `webpack.dev.js` (прокси dev-сервера).

## Минимальный набор для сборки

- `BUILD_ENV` — одно из `local`/`stage`/`preprod`/`prod`/`contour` (обязательно);
- `NPM_TOKEN` — для установки приватных пакетов `@sarex-team/*` из nexus;
- (опционально) `STORYBOOK=true` — при сборке/запуске Storybook;
- (для e2e) `SRX_LOGIN`, `SRX_PASSWORD` в `cypress.env.json`.
