`WebRTCStreamView` has existed since before this commit with no consumer: nothing rendered it, and the URL it would have used came from a `go2rtcStreamBase` in `nuxt.config.ts` defaulting to `http://localhost:1984`. That default was the real problem. A camera stream lives on a gateway box inside one farm's network, each farm has its own, and the gateway now reports its address to the backend when it connects. A compiled-in constant could only ever be correct for a single-farm install, and its localhost default pointed every player at the operator's own laptop. It is gone, replaced by `fetchPrinterStream`, which asks `GET /printers/:id/stream`. Absence is the normal case here, not an error: only Bambu's X1/H2 class publishes a camera URL a gateway can restream, so a P1 or A1 has a camera and nothing to connect to. The backend 404s for those, this resolves to null, and the card renders no player - offering one that can never load would be worse than offering nothing. The lookup also runs only for printers whose `cameraStream` the fleet list already reports, so a twenty-printer farm does not make twenty requests to learn that eighteen of them 404. `PrinterCard` takes the stream as a prop rather than fetching it, like `live` above it: `packages/ui` is plain Vue that knows nothing about the API or about Nuxt, and that is what lets these components render from a test or the desktop shell with no server behind them. Three things in `WebRTCStreamView` that would have bitten whoever first pointed it at a real printer: - The fetch status was never checked. go2rtc answers a request for a stream it does not have with an error page, and handing that to `setRemoteDescription` throws about SDP parsing - which sends you looking at the wrong layer entirely. - `connect()` is async inside a watcher with nothing catching it, so a failure left the badge on "connecting" forever and showed up only as an unhandled rejection in the console. - Two prop changes in quick succession raced: the slower request could finish last and apply its answer to a connection already replaced and closed, leaving a black video with a "connected" badge. No `iceServers`, deliberately and now commented: both ends are on the same LAN, so host candidates are enough. The same fact is the MVP's limitation - there is no relay, so this plays for someone on the printers' network and for nobody else. `nuxt typecheck` and `vue-tsc --noEmit` both clean.
54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
// https://nuxt.com/docs/api/configuration/nuxt-config
|
|
export default defineNuxtConfig({
|
|
compatibilityDate: "2026-01-01",
|
|
|
|
// Disabled so the exact same static bundle can be served from the browser
|
|
// and embedded verbatim into the Tauri desktop shell.
|
|
ssr: false,
|
|
|
|
devtools: { enabled: true },
|
|
|
|
modules: ["@nuxtjs/supabase", "@pinia/nuxt"],
|
|
|
|
supabase: {
|
|
redirect: true,
|
|
redirectOptions: {
|
|
login: "/login",
|
|
callback: "/confirm",
|
|
exclude: ["/login"],
|
|
},
|
|
},
|
|
|
|
runtimeConfig: {
|
|
public: {
|
|
apiBase: process.env.NUXT_PUBLIC_API_BASE || "http://localhost:3001",
|
|
wsBase: process.env.NUXT_PUBLIC_WS_BASE || "ws://localhost:3001",
|
|
// There is deliberately no go2rtcStreamBase here any more. A camera
|
|
// stream lives on a gateway inside a particular farm's network, each
|
|
// farm has its own, and the gateway tells the backend its address when
|
|
// it connects - so a build-time constant could only ever be right for a
|
|
// single-farm install, and its localhost:1984 default meant the UI
|
|
// quietly pointed every player at the operator's own machine. Asked for
|
|
// per printer instead: see `usePrinterStream`.
|
|
},
|
|
},
|
|
|
|
// apps/desktop's src-tauri config points at this static output directory.
|
|
nitro: {
|
|
output: {
|
|
publicDir: "../desktop/dist",
|
|
},
|
|
},
|
|
|
|
vite: {
|
|
// Tauri needs a fixed, predictable dev server port.
|
|
server: {
|
|
strictPort: true,
|
|
},
|
|
},
|
|
|
|
typescript: {
|
|
strict: true,
|
|
},
|
|
});
|