- js/config.js: connection config with URL param + env var override - WS URL, auth token, mock mode toggle - Computed isLive and wsUrlWithAuth getters - Resolves #7 (config.js) - Resolves #11 (Phase 1 shared-secret auth via query param) - js/websocket.js: refactored to use Config for live/mock switching - Live mode: real WS with reconnection + exponential backoff - Auth token appended as ?token= on WS connect - agent_joined handler dispatches to addAgent() for hot-add - sendMessage() public API for UI → backend communication - js/agents.js: dynamic agent hot-add and removal - addAgent(def): spawns 3D avatar at runtime without reload - autoPlace(): finds unoccupied circular slot (radius 8+) - removeAgent(id): clean dispose + connection line rebuild - Connection distance threshold 8→14 for larger agent rings - Resolves #12 (dynamic agent hot-add)
69 lines
2.0 KiB
JavaScript
69 lines
2.0 KiB
JavaScript
/**
|
|
* config.js — Connection configuration for The Matrix.
|
|
*
|
|
* Override at deploy time via URL query params:
|
|
* ?ws=ws://tower:8080/ws/world-state — WebSocket endpoint
|
|
* ?token=my-secret — Auth token (Phase 1 shared secret)
|
|
* ?mock=true — Force mock mode (no real WS)
|
|
*
|
|
* Or via Vite env vars:
|
|
* VITE_WS_URL — WebSocket endpoint
|
|
* VITE_WS_TOKEN — Auth token
|
|
* VITE_MOCK_MODE — 'true' to force mock mode
|
|
*
|
|
* Priority: URL params > env vars > defaults.
|
|
*
|
|
* Resolves Issue #7 — js/config.js
|
|
* Resolves Issue #11 — WS authentication strategy (Phase 1: shared secret)
|
|
*/
|
|
|
|
const params = new URLSearchParams(window.location.search);
|
|
|
|
function param(name, envKey, fallback) {
|
|
return params.get(name)
|
|
?? (import.meta.env[envKey] || null)
|
|
?? fallback;
|
|
}
|
|
|
|
export const Config = Object.freeze({
|
|
/** WebSocket endpoint. Empty string = no live connection (mock mode). */
|
|
wsUrl: param('ws', 'VITE_WS_URL', ''),
|
|
|
|
/** Auth token appended as ?token= query param on WS connect (Issue #11). */
|
|
wsToken: param('token', 'VITE_WS_TOKEN', ''),
|
|
|
|
/** Force mock mode even if wsUrl is set. Useful for local dev. */
|
|
mockMode: param('mock', 'VITE_MOCK_MODE', 'false') === 'true',
|
|
|
|
/** Reconnection timing */
|
|
reconnectBaseMs: 2000,
|
|
reconnectMaxMs: 30000,
|
|
|
|
/** Heartbeat / zombie detection */
|
|
heartbeatIntervalMs: 30000,
|
|
heartbeatTimeoutMs: 5000,
|
|
|
|
/**
|
|
* Computed: should we use the real WebSocket client?
|
|
* True when wsUrl is non-empty AND mockMode is false.
|
|
*/
|
|
get isLive() {
|
|
return this.wsUrl !== '' && !this.mockMode;
|
|
},
|
|
|
|
/**
|
|
* Build the final WS URL with auth token appended as a query param.
|
|
* Returns null if not in live mode.
|
|
*
|
|
* Result: ws://tower:8080/ws/world-state?token=my-secret
|
|
*/
|
|
get wsUrlWithAuth() {
|
|
if (!this.isLive) return null;
|
|
const url = new URL(this.wsUrl);
|
|
if (this.wsToken) {
|
|
url.searchParams.set('token', this.wsToken);
|
|
}
|
|
return url.toString();
|
|
},
|
|
});
|