// The single GatewayClient the app uses. In `mock` mode (pnpm start) it is the // in-memory fake; otherwise it is the real Connect/FlatBuffers transport. MODE is a // build-time constant, so a production build tree-shakes the mock away. import type { GatewayClient } from './client'; import { MockGateway } from './mock/client'; import { createTransport } from './transport'; import { reportOffline, reportOnline } from './connection.svelte'; import { clearMaintenance, maintenanceRecovered, reportMaintenance } from './maintenance.svelte'; const isMock = import.meta.env.MODE === 'mock'; export const gateway: GatewayClient = isMock ? new MockGateway() : createTransport(import.meta.env.VITE_GATEWAY_URL ?? ''); // Mock-mode test hook (tree-shaken from a production build, where MODE !== 'mock'): the mock // transport never exercises the connectivity indicator, so the Playwright e2e drives it directly. if (isMock && typeof window !== 'undefined') { (window as unknown as { __conn?: { offline(): void; online(): void } }).__conn = { offline: reportOffline, online: reportOnline, }; // The mock never produces a real 503, so the e2e drives the maintenance overlay directly // (the store's poll is inert in mock — no probe is registered — so `off` clears it). ( window as unknown as { __maint?: { on(retryAfterMs?: number): void; off(): void; recover(): void } } ).__maint = { on: (retryAfterMs = 15000) => reportMaintenance(retryAfterMs), off: clearMaintenance, recover: maintenanceRecovered, }; // Drive the auto-match opponent join deterministically from the e2e (the mock otherwise // attaches a robot on a timer). ( window as unknown as { __mock?: { joinOpponent(): void; joinOpponentSilently(): void; adminReply(): void; setGameLimit(v: boolean): void; clearEmail(): void; confirmEmailOutOfBand(email: string): void; }; } ).__mock = { joinOpponent: () => (gateway as MockGateway).joinPendingOpponent(), joinOpponentSilently: () => (gateway as MockGateway).joinPendingOpponentSilently(), adminReply: () => (gateway as MockGateway).mockAdminReply(), setGameLimit: (v: boolean) => (gateway as MockGateway).setGameLimit(v), clearEmail: () => (gateway as MockGateway).mockClearEmail(), confirmEmailOutOfBand: (email: string) => (gateway as MockGateway).mockConfirmEmailOutOfBand(email), }; }