feat(web): add OpenAPI TypeScript codegen and CI freshness check

Генерируем api.gen.ts из docs/openapi.yaml (openapi-typescript), добавляем scripts/check-openapi-gen.sh в CI. Закрываем решение по X-Tenant-Id как unimplemented; обновляем docs/README под React/ReUI и apps/web.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-07-31 12:19:02 +07:00
co-authored by Cursor
parent a0cfbcdab1
commit 13e3d21ce2
9 changed files with 6782 additions and 32 deletions
+10 -2
View File
@@ -150,15 +150,23 @@ jobs:
# ---------------------------------------------------------------------------
openapi:
needs: [changes]
if: needs.changes.outputs.openapi == 'true'
if: needs.changes.outputs.openapi == 'true' || needs.changes.outputs.web == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
node-version: "22"
- name: Enable pnpm via corepack
run: corepack enable
- name: Lint OpenAPI (Redocly)
run: npx --yes @redocly/cli@1 lint docs/openapi.yaml
- name: Check OpenAPI→TS codegen is fresh
run: |
set -euxo pipefail
pnpm install --frozen-lockfile
chmod +x scripts/check-openapi-gen.sh
sh scripts/check-openapi-gen.sh
# ---------------------------------------------------------------------------
web:
+7 -4
View File
@@ -9,7 +9,9 @@
"preview": "vite preview",
"typecheck": "tsr generate && tsc --noEmit",
"lint": "eslint .",
"test": "vitest run"
"test": "vitest run",
"openapi:gen": "openapi-typescript ../../docs/openapi.yaml -o src/types/api.gen.ts",
"openapi:check": "openapi-typescript ../../docs/openapi.yaml -o src/types/api.gen.check.ts && diff -q src/types/api.gen.ts src/types/api.gen.check.ts && rm -f src/types/api.gen.check.ts"
},
"dependencies": {
"@base-ui/react": "^1.0.0",
@@ -40,22 +42,23 @@
"zod": "^3.25.0"
},
"devDependencies": {
"@eslint/js": "^9.0.0",
"@tailwindcss/vite": "^4.1.0",
"@tanstack/router-plugin": "^1.130.0",
"@tanstack/router-cli": "^1.130.0",
"@tanstack/router-plugin": "^1.130.0",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.1",
"eslint": "^9.0.0",
"@eslint/js": "^9.0.0",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.0",
"globals": "^15.0.0",
"typescript-eslint": "^8.0.0",
"happy-dom": "^18.0.0",
"openapi-typescript": "^7.13.0",
"tailwindcss": "^4.1.0",
"tw-animate-css": "^1.0.0",
"typescript": "^5.9.2",
"typescript-eslint": "^8.0.0",
"vite": "^7.3.1",
"vitest": "^3.0.0"
}
File diff suppressed because it is too large Load Diff
+10
View File
@@ -1,3 +1,13 @@
/**
* Hand-written UI DTO aliases used by routes/queries.
* Machine SoT from OpenAPI: `./api.gen.ts` (regenerate: `pnpm --filter @evobgp/web run openapi:gen`).
* Prefer aligning new fields with schemas in docs/openapi.yaml + regenerating api.gen.ts.
*/
import type { components } from './api.gen'
/** Re-export generated OpenAPI components for gradual adoption. */
export type OpenAPISchemas = components['schemas']
// ---- Pagination ----
export type Page<T> = {
items: T[]
+4 -2
View File
@@ -7,7 +7,7 @@
- **ИИ-агент / ассистент в репозитории** — [../AGENTS.md](../AGENTS.md): с чего начать чтение, карта `internal/` и `cmd/`, что не тащить в контекст. **Инженерные правила:** [../.cursor/rules/engineering.mdc](../.cursor/rules/engineering.mdc) (общие), [../.cursor/rules/web-shadcn.mdc](../.cursor/rules/web-shadcn.mdc) (Web UI), [../.cursor/rules/networking-bird.mdc](../.cursor/rules/networking-bird.mdc) (BIRD2/BGP/IP).
- **Оператор / DevOps** — [quickstart.md](quickstart.md), [architecture.md](architecture.md), [access.md](access.md), [deploy/compose/docker-compose.yaml](../deploy/compose/docker-compose.yaml).
- **Разработчик бэкенда или интегратор API** — [api.md](api.md), [access.md](access.md), [openapi.yaml](openapi.yaml), исходники маршрутов в `internal/httpapi/`.
- **Разработчик фронтенда** — [quickstart.md](quickstart.md) (раздел про `web/` и CORS), [api.md](api.md), [../web/README.md](../web/README.md).
- **Разработчик фронтенда** — [quickstart.md](quickstart.md) (раздел про `apps/web/` и CORS), [api.md](api.md), [ui-design-contract.md](ui-design-contract.md), [../apps/web/](../apps/web/).
## Оглавление
@@ -22,6 +22,7 @@
| [access.md](access.md) | Выдача доступа: API-ключи, роли, нода, CORS |
| [remote-speakers.md](remote-speakers.md) | Удалённые BGP-реплики: Traefik, agent sync, compose |
| [releasing.md](releasing.md) | Автоматические релизы, Conventional Commits, CI |
| [ui-design-contract.md](ui-design-contract.md) | UI SoT: ReUI Frame, kit, KPI hybrid |
| [openapi.yaml](openapi.yaml) | Источник правды по контракту API |
| [OPENAPI-GITEA.md](OPENAPI-GITEA.md) | Как открыть HTML-документацию API (в т.ч. из Gitea) |
| [evobgp-api-sketches.md](evobgp-api-sketches.md) | Ранний черновик идей API (контекст, не замена OpenAPI) |
@@ -31,7 +32,8 @@
| Файл | Область |
|------|---------|
| [../.cursor/rules/engineering.mdc](../.cursor/rules/engineering.mdc) | Go, API, migrations, security, enforcement |
| [../.cursor/rules/web-shadcn.mdc](../.cursor/rules/web-shadcn.mdc) | SvelteKit, shadcn-svelte |
| [../.cursor/rules/web-shadcn.mdc](../.cursor/rules/web-shadcn.mdc) | React + TanStack + shadcn/ui + ReUI (`apps/web`, `packages/ui`) |
| [../.cursor/rules/reui-mcp.mdc](../.cursor/rules/reui-mcp.mdc) | ReUI PRO MCP workflow, surface `frame` |
| [../.cursor/rules/networking-bird.mdc](../.cursor/rules/networking-bird.mdc) | BIRD2, BGP policy, IP/CIDR |
| [../.cursor/rules/conventional-commits.mdc](../.cursor/rules/conventional-commits.mdc) | Conventional Commits (заголовок EN, тело RU) |
+4 -2
View File
@@ -168,9 +168,11 @@ http://localhost:5173,http://127.0.0.1:5173,https://ui.example.com
Разрешённые заголовки включают `Authorization`, `Content-Type`, `Idempotency-Key`, `Accept`, `X-Tenant-Id` (см. `internal/httpapi/cors.go`).
## Заголовок `X-Tenant-Id` (спецификация vs реализация)
## Заголовок `X-Tenant-Id` (решение: не реализован)
В [openapi.yaml](openapi.yaml) описано использование **`X-Tenant-Id`** для супер-ролей при работе от имени разных арендаторов. В **текущем коде** после аутентификации tenant берётся **только из записи API-ключа**; заголовок `X-Tenant-Id` **не переопределяет** tenant в обработчиках. До появления поддержки в коде не рассчитывайте на переключение tenant через этот заголовок.
**Решение (done):** заголовок **`X-Tenant-Id` не переключает tenant** в handlers и **не планируется** без отдельного ADR на супер-роли.
В [openapi.yaml](openapi.yaml) он помечен как reserved / unimplemented; tenant всегда из API-ключа, portal JWT claim или `EVOBGP_PORTAL_TENANT_ID`.
Клиенты **не должны** полагаться на `X-Tenant-Id`.
## Доступ к репозиторию и CI
+2 -1
View File
@@ -19,7 +19,8 @@ info:
**Роли API key** (матрица): `viewer`, `editor`, `operator`, `node`. Нода использует отдельные пути и ключ с ролью `node`.
JWT permissions мапятся на ту же лестницу (`:read`→viewer, `:write`→editor, `:admin`→operator).
Заголовок `X-Tenant-Id` допускается только для супер-ролей (явный tenant); иначе tenant берётся из API-ключа / portal tenant env.
Заголовок `X-Tenant-Id`: **не реализован в handlers** (документировано в docs/access.md).
Tenant всегда из API-ключа / portal JWT claim / `EVOBGP_PORTAL_TENANT_ID`. Спецификация сохраняет заголовок как reserved future; не полагаться на него в клиентах.
license:
name: Proprietary
identifier: LicenseRef-Proprietary
+151 -21
View File
@@ -150,6 +150,9 @@ importers:
happy-dom:
specifier: ^18.0.0
version: 18.0.1
openapi-typescript:
specifier: ^7.13.0
version: 7.13.0([email protected])
tailwindcss:
specifier: ^4.1.0
version: 4.3.2
@@ -941,6 +944,16 @@ packages:
'@types/react':
optional: true
'@redocly/[email protected]':
resolution: {integrity: sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==}
'@redocly/[email protected]':
resolution: {integrity: sha512-gAy93Ddo01Z3bHuVdPWfCwzgfaYgMdaZPcfL7JZ7hWJoK9V0lXDbigTWkhiPFAaLWzbOJ+kbUQG1+XwIm0KRGQ==}
'@redocly/[email protected]':
resolution: {integrity: sha512-UyKIm0wTPw5BcY7Z2PkbK1Ma260um96LSBWXHrdSMe+ZV0EPMyDfAcUcjjm3qEiGST9OK/1TriekdPCZkn4Q3A==}
engines: {node: '>=18.17.0', npm: '>=9.5.0'}
'@reduxjs/[email protected]':
resolution: {integrity: sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==}
peerDependencies:
@@ -1565,6 +1578,10 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
[email protected]:
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
engines: {node: '>= 14'}
[email protected]:
resolution: {integrity: sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==}
engines: {node: '>= 20'}
@@ -1583,6 +1600,10 @@ packages:
[email protected]:
resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==}
[email protected]:
resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
engines: {node: '>=6'}
[email protected]:
resolution: {integrity: sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==}
engines: {node: '>=18'}
@@ -1658,6 +1679,9 @@ packages:
[email protected]:
resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==}
[email protected]:
resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==}
[email protected]:
resolution: {integrity: sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==}
engines: {node: 18 || 20 || >=22}
@@ -1714,6 +1738,9 @@ packages:
resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
[email protected]:
resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==}
[email protected]:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
@@ -1780,6 +1807,9 @@ packages:
[email protected]:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
[email protected]:
resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==}
[email protected]:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
@@ -2364,6 +2394,10 @@ packages:
resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==}
engines: {node: '>=10.19.0'}
[email protected]:
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
engines: {node: '>= 14'}
[email protected]:
resolution: {integrity: sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==}
engines: {node: '>= 20'}
@@ -2510,6 +2544,10 @@ packages:
resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==}
hasBin: true
[email protected]:
resolution: {integrity: sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==}
engines: {node: '>=0.10.0'}
[email protected]:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -2797,6 +2835,10 @@ packages:
[email protected]:
resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==}
[email protected]:
resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==}
engines: {node: '>=10'}
[email protected]:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
@@ -2937,6 +2979,12 @@ packages:
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
engines: {node: '>=12'}
[email protected]:
resolution: {integrity: sha512-EFP392gcqXS7ntPvbhBzbF8TyBA+baIYEm791Hy5YkjDYKTnk/Tn5OQeKm5BIZvJihpp8Zzr4hzx0Irde1LNGQ==}
hasBin: true
peerDependencies:
typescript: ^5.x
[email protected]:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
@@ -3076,6 +3124,10 @@ packages:
resolution: {integrity: sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==}
engines: {node: '>=4'}
[email protected]:
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
engines: {node: '>=4'}
[email protected]:
resolution: {integrity: sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==}
engines: {node: ^10 || ^12 || >=14}
@@ -3433,6 +3485,10 @@ packages:
resolution: {integrity: sha512-WHkws2ZflZe41zj6AolvvmaTrWds/VuyeYr9iPVv/oQeaIoVxMKaushfFWpOGDT+GuBrM/sVqF8KUCYQlSSTdQ==}
engines: {node: '>=18'}
[email protected]:
resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==}
engines: {node: '>=18'}
[email protected]:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
@@ -3655,6 +3711,9 @@ packages:
peerDependencies:
browserslist: '>= 4.21.0'
[email protected]:
resolution: {integrity: sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==}
[email protected]:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@@ -3815,6 +3874,9 @@ packages:
[email protected]:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
[email protected]:
resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==}
[email protected]:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
@@ -3896,7 +3958,7 @@ snapshots:
'@babel/types': 7.29.7
'@jridgewell/remapping': 2.3.5
convert-source-map: 2.0.0
debug: 4.4.3
debug: 4.4.3([email protected])
gensync: 1.0.0-beta.2
json5: 2.2.3
semver: 6.3.1
@@ -3980,7 +4042,7 @@ snapshots:
'@babel/parser': 7.29.7
'@babel/template': 7.29.7
'@babel/types': 7.29.7
debug: 4.4.3
debug: 4.4.3([email protected])
transitivePeerDependencies:
- supports-color
@@ -4249,7 +4311,7 @@ snapshots:
'@eslint/[email protected]':
dependencies:
'@eslint/object-schema': 2.1.7
debug: 4.4.3
debug: 4.4.3([email protected])
minimatch: 3.1.5
transitivePeerDependencies:
- supports-color
@@ -4265,7 +4327,7 @@ snapshots:
'@eslint/[email protected]':
dependencies:
ajv: 6.15.0
debug: 4.4.3
debug: 4.4.3([email protected])
espree: 10.4.0
globals: 14.0.0
ignore: 5.3.2
@@ -4347,7 +4409,7 @@ snapshots:
dependencies:
'@semantic-release/error': 4.0.0
aggregate-error: 5.0.0
debug: 4.4.3
debug: 4.4.3([email protected])
dir-glob: 3.0.1
form-data: 4.0.6
fs-extra: 11.3.6
@@ -4577,6 +4639,29 @@ snapshots:
optionalDependencies:
'@types/react': 19.2.17
'@redocly/[email protected]':
dependencies:
fast-deep-equal: 3.1.3
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
uri-js-replace: 1.0.1
'@redocly/[email protected]': {}
'@redocly/[email protected]([email protected])':
dependencies:
'@redocly/ajv': 8.11.2
'@redocly/config': 0.22.0
colorette: 1.4.0
https-proxy-agent: 7.0.6([email protected])
js-levenshtein: 1.1.6
js-yaml: 4.3.0
minimatch: 5.1.9
pluralize: 8.0.0
yaml-ast-parser: 0.0.43
transitivePeerDependencies:
- supports-color
'@reduxjs/[email protected]([email protected](@types/[email protected])([email protected])([email protected]))([email protected])':
dependencies:
'@standard-schema/spec': 1.1.0
@@ -4682,7 +4767,7 @@ snapshots:
conventional-changelog-writer: 8.4.0
conventional-commits-filter: 5.0.0
conventional-commits-parser: 6.4.0
debug: 4.4.3
debug: 4.4.3([email protected])
import-from-esm: 2.0.0
lodash-es: 4.18.1
micromatch: 4.0.8
@@ -4698,7 +4783,7 @@ snapshots:
dependencies:
'@semantic-release/error': 4.0.0
aggregate-error: 3.1.0
debug: 4.4.3
debug: 4.4.3([email protected])
execa: 9.6.1
lodash-es: 4.18.1
parse-json: 8.3.0
@@ -4714,7 +4799,7 @@ snapshots:
'@octokit/plugin-throttling': 11.0.3(@octokit/[email protected])
'@semantic-release/error': 4.0.0
aggregate-error: 5.0.0
debug: 4.4.3
debug: 4.4.3([email protected])
dir-glob: 3.0.1
http-proxy-agent: 9.1.0
https-proxy-agent: 9.1.0
@@ -4755,7 +4840,7 @@ snapshots:
conventional-changelog-writer: 8.4.0
conventional-commits-filter: 5.0.0
conventional-commits-parser: 6.4.0
debug: 4.4.3
debug: 4.4.3([email protected])
import-from-esm: 2.0.0
lodash-es: 4.18.1
read-package-up: 11.0.0
@@ -5086,7 +5171,7 @@ snapshots:
'@typescript-eslint/types': 8.62.1
'@typescript-eslint/typescript-estree': 8.62.1([email protected])
'@typescript-eslint/visitor-keys': 8.62.1
debug: 4.4.3
debug: 4.4.3([email protected])
eslint: 9.39.4([email protected])
typescript: 5.9.3
transitivePeerDependencies:
@@ -5096,7 +5181,7 @@ snapshots:
dependencies:
'@typescript-eslint/tsconfig-utils': 8.62.1([email protected])
'@typescript-eslint/types': 8.62.1
debug: 4.4.3
debug: 4.4.3([email protected])
typescript: 5.9.3
transitivePeerDependencies:
- supports-color
@@ -5115,7 +5200,7 @@ snapshots:
'@typescript-eslint/types': 8.62.1
'@typescript-eslint/typescript-estree': 8.62.1([email protected])
'@typescript-eslint/utils': 8.62.1([email protected]([email protected]))([email protected])
debug: 4.4.3
debug: 4.4.3([email protected])
eslint: 9.39.4([email protected])
ts-api-utils: 2.5.0([email protected])
typescript: 5.9.3
@@ -5130,7 +5215,7 @@ snapshots:
'@typescript-eslint/tsconfig-utils': 8.62.1([email protected])
'@typescript-eslint/types': 8.62.1
'@typescript-eslint/visitor-keys': 8.62.1
debug: 4.4.3
debug: 4.4.3([email protected])
minimatch: 10.2.5
semver: 7.8.5
tinyglobby: 0.2.17
@@ -5220,6 +5305,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]:
@@ -5246,6 +5333,8 @@ snapshots:
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
[email protected]: {}
[email protected]:
dependencies:
environment: 1.1.0
@@ -5306,6 +5395,10 @@ snapshots:
balanced-match: 1.0.2
concat-map: 0.0.1
[email protected]:
dependencies:
balanced-match: 1.0.2
[email protected]:
dependencies:
balanced-match: 4.0.4
@@ -5368,6 +5461,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {}
@@ -5445,6 +5540,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
delayed-stream: 1.0.0
@@ -5575,9 +5672,11 @@ snapshots:
[email protected]: {}
[email protected]:
[email protected]([email protected]):
dependencies:
ms: 2.1.3
optionalDependencies:
supports-color: 10.2.2
[email protected]: {}
@@ -5735,7 +5834,7 @@ snapshots:
ajv: 6.15.0
chalk: 4.1.2
cross-spawn: 7.0.6
debug: 4.4.3
debug: 4.4.3([email protected])
escape-string-regexp: 4.0.0
eslint-scope: 8.4.0
eslint-visitor-keys: 4.2.1
@@ -6050,7 +6149,7 @@ snapshots:
[email protected]:
dependencies:
agent-base: 9.0.0
debug: 4.4.3
debug: 4.4.3([email protected])
proxy-agent-negotiate: 1.1.0
transitivePeerDependencies:
- kerberos
@@ -6061,10 +6160,17 @@ snapshots:
quick-lru: 5.1.1
resolve-alpn: 1.2.1
[email protected]([email protected]):
dependencies:
agent-base: 7.1.4
debug: 4.4.3([email protected])
transitivePeerDependencies:
- supports-color
[email protected]:
dependencies:
agent-base: 9.0.0
debug: 4.4.3
debug: 4.4.3([email protected])
proxy-agent-negotiate: 1.1.0
transitivePeerDependencies:
- kerberos
@@ -6089,7 +6195,7 @@ snapshots:
[email protected]:
dependencies:
debug: 4.4.3
debug: 4.4.3([email protected])
import-meta-resolve: 4.2.0
transitivePeerDependencies:
- supports-color
@@ -6165,6 +6271,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {}
@@ -6387,6 +6495,10 @@ snapshots:
dependencies:
brace-expansion: 1.1.15
[email protected]:
dependencies:
brace-expansion: 2.1.4
[email protected]: {}
[email protected]: {}
@@ -6452,6 +6564,16 @@ snapshots:
dependencies:
mimic-fn: 4.0.0
[email protected]([email protected]):
dependencies:
'@redocly/openapi-core': 1.34.18([email protected])
ansi-colors: 4.1.3
change-case: 5.4.4
parse-json: 8.3.0
supports-color: 10.2.2
typescript: 5.9.3
yargs-parser: 21.1.1
[email protected]:
dependencies:
deep-is: 0.1.4
@@ -6566,6 +6688,8 @@ snapshots:
find-up: 2.1.0
load-json-file: 4.0.0
[email protected]: {}
[email protected]:
dependencies:
nanoid: 3.3.15
@@ -6796,7 +6920,7 @@ snapshots:
'@semantic-release/release-notes-generator': 14.1.1([email protected]([email protected]))
aggregate-error: 5.0.0
cosmiconfig: 9.0.2([email protected])
debug: 4.4.3
debug: 4.4.3([email protected])
env-ci: 11.2.0
execa: 9.6.1
figures: 6.1.0
@@ -6940,6 +7064,8 @@ snapshots:
make-asynchronous: 1.1.0
time-span: 5.1.0
[email protected]: {}
[email protected]:
dependencies:
has-flag: 3.0.0
@@ -7094,6 +7220,8 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
[email protected]: {}
[email protected]:
dependencies:
punycode: 2.3.1
@@ -7146,7 +7274,7 @@ snapshots:
[email protected](@types/[email protected])([email protected])([email protected]):
dependencies:
cac: 6.7.14
debug: 4.4.3
debug: 4.4.3([email protected])
es-module-lexer: 1.7.0
pathe: 2.0.3
vite: 7.3.6(@types/[email protected])([email protected])([email protected])
@@ -7189,7 +7317,7 @@ snapshots:
'@vitest/spy': 3.2.6
'@vitest/utils': 3.2.6
chai: 5.3.3
debug: 4.4.3
debug: 4.4.3([email protected])
expect-type: 1.4.0
magic-string: 0.30.21
pathe: 2.0.3
@@ -7257,6 +7385,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {}
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# Fail if apps/web/src/types/api.gen.ts is stale vs docs/openapi.yaml.
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT/apps/web"
tmp="$(mktemp)"
trap 'rm -f "$tmp"' EXIT
pnpm exec openapi-typescript ../../docs/openapi.yaml -o "$tmp"
if ! diff -q src/types/api.gen.ts "$tmp" >/dev/null; then
echo "api.gen.ts is stale — run: pnpm --filter @evobgp/web run openapi:gen" >&2
diff -u src/types/api.gen.ts "$tmp" | head -n 80 >&2 || true
exit 1
fi
echo "api.gen.ts is up to date"