mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-18 05:52:51 +00:00
docs: prefix legacy V1 API paths in generated OpenAPI (#12491)
# Which Problems Are Solved
- Generated V1 API reference docs are missing their base path prefixes
(e.g. `/admin/v1`, `/auth/v1`, `/management/v1`, `/system/v1`).
- Endpoint pages show routes like `/healthz` instead of
`/admin/v1/healthz`.
This happens because V1 protos still define `base_path` via legacy
OpenAPI v2 swagger annotations, while docs generation uses
`protoc-gen-connect-openapi`, which ignores those annotations and emits
the bare `google.api.http` paths.
# How the Problems Are Solved
- After OpenAPI generation in
`apps/docs/scripts/generate-proto-docs.mjs`, apply a small hardcoded map
of the four legacy V1 services and prepend the correct prefix to each
path in the generated specs.
- The rewrite is idempotent (`startsWith(prefix)`), so already-prefixed
paths are left alone.
- Because the prefixes are written into the generated OpenAPI files,
Fumadocs MDX generation and runtime page rendering stay in sync.
# Additional Changes
- None.
# Additional Context
- V1 APIs are legacy and frozen; hardcoding the four known prefixes is
simpler and more reliable than dynamically scraping `.proto` files.
- Changing the protos or dual-generating with `openapiv2` would be much
more invasive for a docs-only issue.
- Verified locally for Admin, Auth, Management, and System pages (e.g.
`/admin/v1/healthz`, `/management/v1/users/{id}`).
---------
Co-authored-by: Livio Spring <[email protected]>
Co-authored-by: Cursor <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
This commit is contained in:
co-authored by
Livio Spring
Cursor
Copilot Autofix powered by AI
parent
ca6595f8c5
commit
87538f29e1
@@ -1,6 +1,6 @@
|
||||
import fs from 'fs';
|
||||
import { glob } from 'glob';
|
||||
import { join, dirname, resolve } from 'path';
|
||||
import { join, dirname, resolve, basename } from 'path';
|
||||
import { spawn, spawnSync } from 'child_process';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
@@ -13,6 +13,42 @@ const VERSIONS_FILE = join(ROOT_DIR, 'content/versions.json');
|
||||
const REPO_URL = 'https://github.com/zitadel/zitadel.git';
|
||||
const PNPM_COMMAND = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm';
|
||||
|
||||
// Legacy V1 APIs declare base_path via OpenAPI v2 swagger options that
|
||||
// protoc-gen-connect-openapi ignores. Prefix paths so fumadocs shows the real URLs.
|
||||
const V1_PATH_PREFIXES = {
|
||||
admin: '/admin/v1',
|
||||
auth: '/auth/v1',
|
||||
management: '/management/v1',
|
||||
system: '/system/v1',
|
||||
};
|
||||
|
||||
function applyV1PathPrefixes(outputPath) {
|
||||
for (const [service, prefix] of Object.entries(V1_PATH_PREFIXES)) {
|
||||
const files = glob.sync(`**/${service}.openapi.json`, { cwd: outputPath, absolute: true, nodir: true });
|
||||
for (const file of files) {
|
||||
try {
|
||||
const doc = JSON.parse(fs.readFileSync(file, 'utf8'));
|
||||
if (!doc.paths || Object.keys(doc.paths).length === 0) continue;
|
||||
|
||||
const newPaths = {};
|
||||
let changed = false;
|
||||
for (const [route, operations] of Object.entries(doc.paths)) {
|
||||
const newRoute = route.startsWith(prefix) ? route : `${prefix}${route}`;
|
||||
if (newRoute !== route) changed = true;
|
||||
newPaths[newRoute] = operations;
|
||||
}
|
||||
if (!changed) continue;
|
||||
|
||||
doc.paths = newPaths;
|
||||
fs.writeFileSync(file, JSON.stringify(doc, null, 2));
|
||||
console.log(`Applied ${prefix} to ${basename(file)}`);
|
||||
} catch (e) {
|
||||
console.warn(`Failed to apply ${prefix} to ${basename(file)}`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
if (!fs.existsSync(VERSIONS_FILE)) {
|
||||
console.error('versions.json not found. Run fetch-docs.mjs first.');
|
||||
@@ -182,7 +218,13 @@ async function run() {
|
||||
} catch (e) {
|
||||
console.warn(`Failed to clean up OpenAPI specs for ${label}`, e);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
applyV1PathPrefixes(outputPath);
|
||||
} catch (e) {
|
||||
console.warn(`Failed to apply V1 path prefixes for ${label}`, e);
|
||||
}
|
||||
|
||||
resolvePromise();
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user