feat(maestro): let vite dev proxy honor \$MAESTRO_REGISTRY
ci / rust (push) Successful in 1m27s

`web/vite.config.ts` was hard-coded to proxy `/api` at
`http://127.0.0.1:8080`, so pointing the dev UI at a remote registry meant
hand-editing the file. Read `MAESTRO_REGISTRY` from the environment via
`loadEnv` instead, with the local default preserved. Accept either the HTTP
base URL (`https://…`) or the daemon-facing URL (`wss://…/daemon`) — the
latter is rewritten to `https://…` and the `/daemon` suffix stripped, since
the proxy needs the HTTP origin. Flips `changeOrigin: true` for HTTPS
upstreams so the proxied Host matches the cert.

Documented under `web/README.md` § Dev.
This commit is contained in:
2026-05-25 15:35:57 +00:00
parent 476a414c6f
commit f0b01ae295
2 changed files with 50 additions and 20 deletions
+13 -4
View File
@@ -42,10 +42,19 @@ pnpm dev # http://localhost:5173, proxies /api → http://127.0.0.1:8080
pnpm build # → dist/, embedded into the registry binary at cargo build time
```
The Vite dev server proxies `/api` and the events WebSocket to a locally
running `maestro-registry` (default `127.0.0.1:8080`). Direct daemon WS
connections (for attach) bypass the proxy and use the URL returned by
`GET /api/sessions/:id/connect-info`.
The Vite dev server proxies `/api` and the events WebSocket to a
`maestro-registry`. Default is `http://127.0.0.1:8080`; point it elsewhere by
exporting `MAESTRO_REGISTRY` before `pnpm dev`:
```sh
MAESTRO_REGISTRY=https://maestro-registry.example.com pnpm dev
# Daemon-facing URL also works — `wss://...` is rewritten to `https://...`
# and a trailing `/daemon` is stripped.
MAESTRO_REGISTRY=wss://maestro-registry.example.com/daemon pnpm dev
```
Direct daemon WS connections (for attach) bypass the proxy and use the URL
returned by `GET /api/sessions/:id/connect-info`.
## Production
+37 -16
View File
@@ -1,20 +1,41 @@
import { defineConfig } from "vite";
import { defineConfig, loadEnv } from "vite";
export default defineConfig({
build: {
target: "es2022",
outDir: "dist",
emptyOutDir: true,
sourcemap: false,
},
server: {
port: 5173,
proxy: {
"/api": {
target: "http://127.0.0.1:8080",
changeOrigin: false,
ws: true,
// Where the dev proxy forwards `/api/*` (and the events WS) to. Default to a
// local `maestro-registry` on 127.0.0.1:8080. Override by exporting either:
// MAESTRO_REGISTRY=https://maestro-registry.example.com (preferred)
// MAESTRO_REGISTRY=wss://maestro-registry.example.com/daemon
// The second form (the daemon-facing URL) is normalised: ws/wss → http/https
// and any trailing `/daemon` is stripped, since the proxy needs the base URL.
function resolveProxyTarget(raw: string | undefined): string {
if (!raw) return "http://127.0.0.1:8080";
return raw
.replace(/^wss:\/\//, "https://")
.replace(/^ws:\/\//, "http://")
.replace(/\/daemon\/?$/, "")
.replace(/\/+$/, "");
}
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd(), "");
const target = resolveProxyTarget(env.MAESTRO_REGISTRY);
const secure = target.startsWith("https://");
return {
build: {
target: "es2022",
outDir: "dist",
emptyOutDir: true,
sourcemap: false,
},
server: {
port: 5173,
proxy: {
"/api": {
target,
changeOrigin: secure,
ws: true,
secure: false,
},
},
},
},
};
});