chore(api): rely on sibling backend or committed OpenAPI for codegen

Drop live Swagger fetch so clients stay aligned through backend OpenAPI sync PRs.
This commit is contained in:
alisaza 2026-09-07 14:17:33 +03:30
parent 8721190502
commit 15beeb5897
3 changed files with 54 additions and 24 deletions

View File

@ -11,4 +11,12 @@ pnpm dev
The development server uses port **3009**.
API client generation:
```bash
pnpm generate:api
```
Uses sibling `../ghabilee-backend` when present, otherwise the committed `openapi.json`. Cross-repo sync is handled by the backend `sync-openapi-clients` workflow.
This admin application is intentionally excluded from search-engine indexing and does not include Microsoft Clarity. Deployment secrets and environment-specific credentials will be added later by the repository owner.

View File

@ -3,8 +3,7 @@ import { defineConfig } from 'orval'
export default defineConfig({
api: {
input: {
// Committed mirror of backend/openapi.json so ghabilee-frontend
// (satellite) can generate without a Nest sibling.
// Sibling backend export or committed mirror (kept in sync by backend OpenAPI PRs).
target: './openapi.json',
},
output: {

View File

@ -2,23 +2,29 @@
/**
* Generate Orval client into api/generated/.
*
* Monorepo: refresh OpenAPI from Nest when ../backend exists, then orval.
* Satellite (ghabilee-frontend): orval only from committed ./openapi.json.
* OpenAPI source priority:
* 1. Sibling Nest package (`../ghabilee-backend` or `../backend`) via `generate:openapi`
* 2. Committed `./openapi.json` (CI, satellite clones, OpenAPI sync PRs)
*
* Live Swagger fetch is intentionally not used clients stay in sync via
* ghabilee-backend's `sync-openapi-clients` workflow.
*/
import { spawnSync } from 'node:child_process'
import { copyFileSync, existsSync } from 'node:fs'
import { dirname, join } from 'node:path'
import { fileURLToPath } from 'node:url'
const frontendRoot = join(dirname(fileURLToPath(import.meta.url)), '..')
const backendOpenapi = join(frontendRoot, '../backend/openapi.json')
const localOpenapi = join(frontendRoot, 'openapi.json')
const backendDir = join(frontendRoot, '../backend')
const projectRoot = join(dirname(fileURLToPath(import.meta.url)), '..')
const localOpenapi = join(projectRoot, 'openapi.json')
const siblingBackendDirs = [
join(projectRoot, '../ghabilee-backend'),
join(projectRoot, '../backend'),
]
function run(command, args, opts = {}) {
const result = spawnSync(command, args, {
stdio: 'inherit',
cwd: frontendRoot,
cwd: projectRoot,
shell: process.platform === 'win32',
...opts,
})
@ -27,23 +33,40 @@ function run(command, args, opts = {}) {
}
}
if (existsSync(backendDir) && existsSync(join(backendDir, 'package.json'))) {
console.log('==> Exporting OpenAPI from backend...')
function trySiblingBackend() {
for (const backendDir of siblingBackendDirs) {
if (!existsSync(backendDir) || !existsSync(join(backendDir, 'package.json'))) {
continue
}
const backendOpenapi = join(backendDir, 'openapi.json')
console.log(`==> Exporting OpenAPI from sibling backend (${backendDir})...`)
run('pnpm', ['--dir', backendDir, 'generate:openapi'])
if (!existsSync(backendOpenapi)) {
console.error(`Missing ${backendOpenapi} after export`)
process.exit(1)
}
copyFileSync(backendOpenapi, localOpenapi)
console.log('==> Copied backend/openapi.json → frontend/openapi.json')
} else if (!existsSync(localOpenapi)) {
console.log('==> Copied sibling openapi.json → ./openapi.json')
return true
}
return false
}
if (!trySiblingBackend()) {
if (!existsSync(localOpenapi)) {
console.error(
'No ../backend and no ./openapi.json — cannot generate API client.\n' +
'In the satellite repo, openapi.json must be committed; re-sync from the monorepo.',
[
'No ../ghabilee-backend (or ../backend) and no ./openapi.json — cannot generate API client.',
'Place ghabilee-backend next to this repo, or wait for an OpenAPI sync PR / commit openapi.json.',
].join('\n'),
)
process.exit(1)
} else {
console.log('==> No backend sibling — using committed ./openapi.json')
}
console.log('==> Using committed ./openapi.json')
}
console.log('==> Running orval...')