From 2d1e2f2eeceea5957b81602fc4d67027ee00b4af Mon Sep 17 00:00:00 2001 From: "Luis Gustavo S. Barreto" Date: Thu, 28 May 2026 14:25:37 -0300 Subject: [PATCH] fix(ui-react): generate client from combined spec for npm run generate `npm run generate` defaulted to `http://openapi:8080/openapi/openapi.json`, which the openapi container serves filtered by the active edition (community / enterprise / cloud). Running it on a community instance produced a client missing enterprise and cloud schemas, breaking lint and type-check on any code that referenced those types. The dev entrypoint sidestepped this by bundling `/openapi/spec/openapi.yaml` directly, but a manual `npm run generate` after that overwrote the client with the edition-filtered version. Extract the bundle + generate steps into `scripts/generate-client.sh` and wire the npm script to it, so both the dev entrypoint and manual runs use the combined spec. The script honors a pre-set `OPENAPI_SPEC_PATH` so the production Dockerfile builder stage (which bundles in an earlier stage) keeps working. Remove the HTTP fallback in `openapi-ts.config.ts`: it was the source of the bug, and the new script always sets the env var. Add a chokidar watcher in the dev entrypoint that re-runs the script whenever `openapi/spec/**/*.yaml` changes, so editing the spec no longer requires recreating the container; Vite HMR picks up the fresh `types.gen.ts`. Fixes: shellhub-io/shellhub#6386 --- ui-react/apps/console/openapi-ts.config.ts | 12 ++++++++++-- ui-react/apps/console/package.json | 2 +- ui-react/scripts/entrypoint-dev.sh | 12 +++++++----- ui-react/scripts/generate-client.sh | 14 ++++++++++++++ 4 files changed, 32 insertions(+), 8 deletions(-) create mode 100755 ui-react/scripts/generate-client.sh diff --git a/ui-react/apps/console/openapi-ts.config.ts b/ui-react/apps/console/openapi-ts.config.ts index 07018bf4d97..8a3557e06de 100644 --- a/ui-react/apps/console/openapi-ts.config.ts +++ b/ui-react/apps/console/openapi-ts.config.ts @@ -1,8 +1,16 @@ import { defineConfig } from "@hey-api/openapi-ts"; +const input = process.env.OPENAPI_SPEC_PATH; +if (!input) { + // The openapi container only serves the spec for the active edition, so + // generating from its URL produces a client missing the other editions' + // schemas. Use `npm run generate -w @shellhub/console`, which bundles the + // combined spec before invoking openapi-ts. + throw new Error("OPENAPI_SPEC_PATH is not set; run `npm run generate -w @shellhub/console`."); +} + export default defineConfig({ - input: - process.env.OPENAPI_SPEC_PATH || "http://openapi:8080/openapi/openapi.json", + input, output: "src/client", plugins: [ "@hey-api/typescript", diff --git a/ui-react/apps/console/package.json b/ui-react/apps/console/package.json index 0ee5769e0ea..976c3f86fd0 100644 --- a/ui-react/apps/console/package.json +++ b/ui-react/apps/console/package.json @@ -10,7 +10,7 @@ "lint": "eslint src", "test": "vitest run", "test:watch": "vitest", - "generate": "openapi-ts" + "generate": "../../scripts/generate-client.sh" }, "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.6.0", diff --git a/ui-react/scripts/entrypoint-dev.sh b/ui-react/scripts/entrypoint-dev.sh index d8779525c37..72359b44f33 100755 --- a/ui-react/scripts/entrypoint-dev.sh +++ b/ui-react/scripts/entrypoint-dev.sh @@ -9,10 +9,12 @@ SCRIPTS_DIR="$(dirname "$(readlink -f "$0")")" mkdir -p apps/console/public "$SCRIPTS_DIR/gen-config.sh" apps/console/public/config.json -# Generate OpenAPI client from the combined spec (all editions) -echo "Bundling OpenAPI spec..." -npx @redocly/cli@1.0.0-beta.100 bundle /openapi/spec/openapi.yaml -o /tmp/openapi.json --force -echo "Generating OpenAPI client..." -OPENAPI_SPEC_PATH=/tmp/openapi.json npx -w @shellhub/console openapi-ts +# Generate the OpenAPI client from the combined spec, then keep regenerating +# it whenever any spec file changes so Vite HMR picks up the new types +# without needing to recreate the container. +npm run generate -w @shellhub/console +# chokidar-cli shells out to $SHELL, which isn't set in this alpine image. +SHELL=/bin/sh npx -y chokidar-cli@3.0.0 '/openapi/spec/**/*.yaml' --debounce 500 \ + -c 'npm run generate -w @shellhub/console' & npm run dev:console diff --git a/ui-react/scripts/generate-client.sh b/ui-react/scripts/generate-client.sh new file mode 100755 index 00000000000..71f84e80eb0 --- /dev/null +++ b/ui-react/scripts/generate-client.sh @@ -0,0 +1,14 @@ +#!/bin/sh +set -e + +# Bundle the combined OpenAPI spec (all editions) and generate the typed +# client. The Dockerfile builder stage sets OPENAPI_SPEC_PATH to a spec +# it bundled in an earlier stage; skip the bundle step in that case. +if [ -z "$OPENAPI_SPEC_PATH" ]; then + npx @redocly/cli@1.0.0-beta.100 bundle /openapi/spec/openapi.yaml -o /tmp/openapi.json --force + OPENAPI_SPEC_PATH=/tmp/openapi.json + export OPENAPI_SPEC_PATH +fi + +cd "$(dirname "$0")/../apps/console" +exec npx openapi-ts