refactor: share realtime socket auth helpers
This commit is contained in:
parent
e1bb6e790e
commit
8f7d5358aa
@ -30,7 +30,7 @@ It assumes:
|
||||
- [x] Backend migrated into `backend/` and passing typecheck, build, test, and backend verification gates
|
||||
- [x] Web migrated into `web/` with shared runtime, shared kill-switch gate, shared telemetry bootstrap, and normalized backend URL resolution
|
||||
- [x] Mobile migrated into `mobile/` with product identity, shared runtime bootstrap, launch-time kill-switch gate, transitional Supabase auth, live backend polling plus websocket-backed updates, startup/error telemetry capture, secure session storage with invalidation handling, and explicit degraded/offline status surfacing
|
||||
- [-] DRY cleanup completed for runtime/config/bootstrap concerns and shared Supabase bootstrap, but not yet for all auth/session internals
|
||||
- [-] DRY cleanup completed for runtime/config/bootstrap concerns, shared Supabase bootstrap, and shared websocket auth helpers, but not yet for all auth/session internals
|
||||
- [!] Full common-platform auth replacement remains a follow-up for web and mobile; current implementation uses transitional Supabase-backed auth to stay compatible with the backend's current JWT boundary
|
||||
|
||||
## 3. Guiding Rules
|
||||
@ -261,7 +261,7 @@ Move the web dashboard onto the new repo and onto shared platform bootstrap patt
|
||||
- [x] Move runtime config to common conventions
|
||||
- [x] Define product config
|
||||
- [x] Define API client and websocket client
|
||||
- [ ] Standardize websocket token propagation
|
||||
- [x] Standardize websocket token propagation
|
||||
- [x] Integrate maintenance and kill-switch UX states
|
||||
- [x] Define shell-level maintenance and kill-switch behavior
|
||||
- [ ] Classify each current web tab as ship, defer, or redesign
|
||||
|
||||
@ -4,6 +4,7 @@ import { io, type Socket } from 'socket.io-client';
|
||||
import { mobileRuntime } from '@/lib/runtime';
|
||||
import { mobileTelemetry, trackMobileError } from '@/lib/telemetry';
|
||||
import { useMobileAuth } from '@/providers/MobileAuthProvider';
|
||||
import { buildTradingSocketOptions, isUnauthorizedSocketError } from '../../shared/realtime.js';
|
||||
|
||||
type HealthSnapshot = {
|
||||
tradingControl?: {
|
||||
@ -223,10 +224,7 @@ export function TradingDataProvider({ children }: { children: ReactNode }) {
|
||||
}));
|
||||
};
|
||||
|
||||
socket = io(tradingSocketUrl, {
|
||||
transports: ['polling', 'websocket'],
|
||||
auth: { token: accessToken },
|
||||
});
|
||||
socket = io(tradingSocketUrl, buildTradingSocketOptions(accessToken));
|
||||
|
||||
socket.on('connect', () => {
|
||||
setConnected(true);
|
||||
@ -242,7 +240,7 @@ export function TradingDataProvider({ children }: { children: ReactNode }) {
|
||||
socket.on('connect_error', (socketError) => {
|
||||
setError(socketError.message);
|
||||
trackMobileError('realtime', 'socket_connect_failed', socketError);
|
||||
if (socketError.message.toLowerCase().includes('unauthorized')) {
|
||||
if (isUnauthorizedSocketError(socketError.message)) {
|
||||
void invalidateSession(socketError.message);
|
||||
}
|
||||
});
|
||||
|
||||
12
shared/realtime.ts
Normal file
12
shared/realtime.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export function buildTradingSocketOptions(token: string, socketPath?: string) {
|
||||
return {
|
||||
transports: ['polling', 'websocket'] as ('polling' | 'websocket')[],
|
||||
auth: { token },
|
||||
...(socketPath ? { path: socketPath } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
export function isUnauthorizedSocketError(message: string) {
|
||||
const normalizedMessage = message.toLowerCase();
|
||||
return normalizedMessage.includes('unauthorized') || normalizedMessage.includes('invalid token');
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { io, Socket } from 'socket.io-client';
|
||||
import { buildTradingSocketOptions } from '../../../shared/realtime.js';
|
||||
import { supabase } from '../lib/supabaseClient';
|
||||
|
||||
export interface TradingControlSnapshot {
|
||||
@ -284,11 +285,7 @@ export const useWebSocket = (url: string) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const socketOptions = {
|
||||
transports: ['polling', 'websocket'] as ('polling' | 'websocket')[],
|
||||
auth: { token },
|
||||
...(import.meta.env.VITE_SOCKET_PATH ? { path: import.meta.env.VITE_SOCKET_PATH } : {})
|
||||
};
|
||||
const socketOptions = buildTradingSocketOptions(token, import.meta.env.VITE_SOCKET_PATH);
|
||||
|
||||
newSocket = io(url, socketOptions);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user