velxio/frontend/src/utils/uuid.ts

30 lines
1.3 KiB
TypeScript
Raw Normal View History

fix(frontend): polyfill crypto.randomUUID for non-secure contexts crypto.randomUUID() is only exposed on secure contexts (HTTPS, localhost, 127.0.0.1, ::1). When Velxio is self-hosted and accessed via a LAN IP over plain HTTP (e.g. http://192.168.31.139:3080/), crypto.randomUUID is undefined and any code path that calls it throws TypeError. This silently broke ESP32 simulation start for self-hosters: the frontend generates a UUID for the WS client_id when Run is clicked; the throw rejected the promise before reaching the WS connect, so the backend never got the start request — no worker spawned, logs empty, simulation "didn't start" with no visible error. Same root cause would also break the multi-file editor (createFile, createFileGroup) on the same LAN-HTTP self-host setup, just less observably. Add a single generateUUID() helper that: 1. Uses crypto.randomUUID() when available (secure context fast path). 2. Falls back to crypto.getRandomValues() — which IS available in non-secure contexts — to build a v4 UUID by hand. 3. Final fallback to Math.random() if even that is missing (defensive — Web Crypto getRandomValues has been universal for years). Replace all 6 crypto.randomUUID() call sites: - frontend/src/simulation/Esp32Bridge.ts (2 sites — getTabSessionId) - frontend/src/store/useEditorStore.ts (4 sites — file IDs) Reported by a self-hoster on OrangePi 5B accessing Velxio via LAN IP. DevTools console showed: TypeError: crypto.randomUUID is not a function at Ph (...) at wh.connect (...) at startBoard (...) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 23:41:30 +07:00
/**
* UUID v4 generator with a polyfill for non-secure contexts.
*
* `crypto.randomUUID()` is only exposed on secure contexts (HTTPS, localhost,
* 127.0.0.1, ::1). When Velxio is self-hosted and accessed via a LAN IP over
* plain HTTP (e.g. `http://192.168.31.139:3080/`), `crypto.randomUUID` is
* `undefined` and any code path that calls it throws `TypeError`. That bug
* silently broke ESP32 simulation start for self-hosters — frontend never sent
* the start request because the UUID call rejected before reaching the WS
* connection.
*
* `crypto.getRandomValues()` IS available in non-secure contexts, so we
* fall back to building a v4 UUID by hand.
*/
export function generateUUID(): string {
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
const bytes = new Uint8Array(16);
if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {
crypto.getRandomValues(bytes);
} else {
for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256);
}
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}