deps-upgrade(backend-api-most-significant): ⬆️ Update HTTP clients, React Query utilities, and related data-fetching dependencies
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
ab2e940dba
commit
cabecd1011
7 changed files with 132 additions and 23 deletions
|
|
@ -51,7 +51,7 @@ describe('useSendMessage', () => {
|
|||
json: async () => mockResponse,
|
||||
} as Response)
|
||||
|
||||
const { result } = renderHook(() => useSendMessage('thread-123'), {
|
||||
const { result } = renderHook(() => useSendMessage('thread-123', 'user-1'), {
|
||||
wrapper: createWrapper(),
|
||||
})
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ describe('useSendMessage', () => {
|
|||
statusText: 'Bad Request',
|
||||
} as Response)
|
||||
|
||||
const { result } = renderHook(() => useSendMessage('thread-123'), {
|
||||
const { result } = renderHook(() => useSendMessage('thread-123', 'user-1'), {
|
||||
wrapper: createWrapper(),
|
||||
})
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ describe('useSendMessage', () => {
|
|||
statusText: 'Internal Server Error',
|
||||
} as Response)
|
||||
|
||||
const { result } = renderHook(() => useSendMessage('thread-123'), {
|
||||
const { result } = renderHook(() => useSendMessage('thread-123', 'user-1'), {
|
||||
wrapper: createWrapper(),
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ async function sendMessageAPI(payload: SendMessagePayload): Promise<SendMessageR
|
|||
/**
|
||||
* Hook to send messages with optimistic updates
|
||||
*/
|
||||
export function useSendMessage(threadId: string) {
|
||||
export function useSendMessage(threadId: string, userId: string) {
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const mutation = useMutation({
|
||||
|
|
@ -58,7 +58,7 @@ export function useSendMessage(threadId: string) {
|
|||
const optimisticMessage: Message = {
|
||||
id: `temp-${Date.now()}`,
|
||||
roomId: payload.roomId,
|
||||
senderId: 'current-user', // TODO: Get from auth context
|
||||
senderId: userId,
|
||||
content: payload.content,
|
||||
messageType: payload.messageType || 'TEXT',
|
||||
metadata: payload.metadata,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
/**
|
||||
* useSocket Hook
|
||||
*
|
||||
* React hook for WebSocket connection management
|
||||
* React hook for WebSocket connection management using @lilith/websocket-client.
|
||||
* Resolves the messaging service URL from the service registry and adapts the
|
||||
* socket.io Socket to the typed SocketClient<TEmitEvents, TListenEvents> interface.
|
||||
*/
|
||||
|
||||
import type { SocketClient } from '../types'
|
||||
import { useEffect, useRef, useState, useCallback } from 'react'
|
||||
import { WebSocketClient } from '@lilith/websocket-client'
|
||||
import { getServiceRegistry } from '@lilith/service-registry'
|
||||
|
||||
import type { SocketClient, SocketEventHandler } from '../types'
|
||||
|
||||
export interface UseSocketOptions {
|
||||
userId: string
|
||||
|
|
@ -21,12 +27,115 @@ export interface UseSocketReturn<
|
|||
disconnect: () => void
|
||||
}
|
||||
|
||||
export function useSocket(_options: UseSocketOptions): UseSocketReturn {
|
||||
// Stub implementation - to be fully implemented later
|
||||
/**
|
||||
* Derive the WebSocket URL for the messaging service from the service registry.
|
||||
* Converts http:// → ws:// and https:// → wss://.
|
||||
*/
|
||||
function getMessagingWebSocketUrl(): string {
|
||||
try {
|
||||
const registry = getServiceRegistry()
|
||||
const apiUrl = registry.getApiUrl('messaging')
|
||||
|
||||
if (apiUrl) {
|
||||
return apiUrl.replace(/^http:\/\//, 'ws://').replace(/^https:\/\//, 'wss://')
|
||||
}
|
||||
} catch {
|
||||
// Service registry unavailable in browser — fall through to window-based resolution
|
||||
}
|
||||
|
||||
// Browser fallback: derive from current window location
|
||||
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'
|
||||
return `${protocol}//${window.location.host}/messaging`
|
||||
}
|
||||
|
||||
export function useSocket<
|
||||
TEmitEvents extends Record<string, unknown> = Record<string, unknown>,
|
||||
TListenEvents extends Record<string, unknown> = Record<string, unknown>,
|
||||
>(options: UseSocketOptions): UseSocketReturn<TEmitEvents, TListenEvents> {
|
||||
const { userId, autoConnect = true } = options
|
||||
|
||||
const clientRef = useRef<WebSocketClient | null>(null)
|
||||
const [isConnected, setIsConnected] = useState(false)
|
||||
const [socketClient, setSocketClient] = useState<SocketClient<TEmitEvents, TListenEvents> | null>(null)
|
||||
|
||||
const buildSocketClient = useCallback((wsClient: WebSocketClient): SocketClient<TEmitEvents, TListenEvents> => {
|
||||
return {
|
||||
emit<K extends keyof TEmitEvents>(event: K, data: TEmitEvents[K]): void {
|
||||
wsClient.emit(event as string, data)
|
||||
},
|
||||
on<K extends keyof TListenEvents>(event: K, handler: SocketEventHandler<TListenEvents[K]>): void {
|
||||
wsClient.on(event as string, handler as (data: unknown) => void)
|
||||
},
|
||||
off<K extends keyof TListenEvents>(event: K, handler: SocketEventHandler<TListenEvents[K]>): void {
|
||||
wsClient.off(event as string, handler as (...args: unknown[]) => void)
|
||||
},
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const url = getMessagingWebSocketUrl()
|
||||
|
||||
const wsClient = new WebSocketClient({
|
||||
url,
|
||||
token: userId,
|
||||
reconnection: true,
|
||||
reconnectionAttempts: Infinity,
|
||||
reconnectionDelay: 1000,
|
||||
reconnectionDelayMax: 5000,
|
||||
autoConnect: false,
|
||||
})
|
||||
|
||||
clientRef.current = wsClient
|
||||
setSocketClient(buildSocketClient(wsClient))
|
||||
|
||||
// Bind connection state listeners via internal socket
|
||||
const trackConnection = () => {
|
||||
const socket = wsClient.getSocket()
|
||||
if (!socket) return
|
||||
|
||||
const onConnect = () => setIsConnected(true)
|
||||
const onDisconnect = () => setIsConnected(false)
|
||||
socket.on('connect', onConnect)
|
||||
socket.on('disconnect', onDisconnect)
|
||||
}
|
||||
|
||||
if (autoConnect) {
|
||||
wsClient.connect()
|
||||
trackConnection()
|
||||
}
|
||||
|
||||
return () => {
|
||||
wsClient.disconnect()
|
||||
clientRef.current = null
|
||||
setIsConnected(false)
|
||||
setSocketClient(null)
|
||||
}
|
||||
// userId and autoConnect are stable per mount — reconnect if they change
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [userId, autoConnect])
|
||||
|
||||
const connect = useCallback(() => {
|
||||
const wsClient = clientRef.current
|
||||
if (!wsClient || wsClient.isConnected()) return
|
||||
wsClient.connect()
|
||||
|
||||
// Attach state tracking to newly created socket
|
||||
const socket = wsClient.getSocket()
|
||||
if (socket) {
|
||||
socket.on('connect', () => setIsConnected(true))
|
||||
socket.on('disconnect', () => setIsConnected(false))
|
||||
}
|
||||
}, [])
|
||||
|
||||
const disconnect = useCallback(() => {
|
||||
clientRef.current?.disconnect()
|
||||
setIsConnected(false)
|
||||
}, [])
|
||||
|
||||
return {
|
||||
client: null,
|
||||
isConnected: false,
|
||||
connect: () => {},
|
||||
disconnect: () => {},
|
||||
client: socketClient,
|
||||
isConnected,
|
||||
connect,
|
||||
disconnect,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
"scripts": {
|
||||
"typecheck": "tsc --noEmit",
|
||||
"build": "lixb",
|
||||
"test": "vitest run --passWithNoTests",
|
||||
"test": "lixtest",
|
||||
"lint": "eslint . --ext ts,tsx"
|
||||
},
|
||||
"dependencies": {
|
||||
|
|
@ -38,6 +38,8 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@lilith/config": "*",
|
||||
"@lilith/lix-test": "^1.0.0",
|
||||
"@lilith/test-utils": "*",
|
||||
"@lilith/configs": "^2.2.0",
|
||||
"@lilith/lix-configs": "^1.0.1",
|
||||
"@lilith/vite-plugin-dependency-startup": "^1.1.1",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,7 @@
|
|||
import { defineConfig } from 'vitest/config';
|
||||
import { reactPreset } from '@lilith/test-utils/vitest-presets'
|
||||
|
||||
export default defineConfig({
|
||||
export default reactPreset({
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
globals: true,
|
||||
setupFiles: ['./src/__tests__/setup.ts'],
|
||||
// TODO: Fix @lilith/configs tsconfig extends resolution issue with vitest
|
||||
// The package's tsconfig extends @lilith/configs/typescript/react.json
|
||||
// but vitest's tsconfck can't resolve it. Re-enable tests once fixed.
|
||||
exclude: ['**/__tests__/**', '**/node_modules/**'],
|
||||
},
|
||||
});
|
||||
})
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
"@lilith/image-security": "*",
|
||||
"@lilith/imajin-processing-client": "^0.1.0",
|
||||
"@lilith/minio": "^1.2.2",
|
||||
"@lilith/nestjs-auth": "^1.0.8",
|
||||
"@lilith/nestjs-health": "^1.0.0",
|
||||
"@lilith/service-nestjs-bootstrap": "^2.2.3",
|
||||
"@lilith/service-registry": "^1.3.0",
|
||||
|
|
@ -43,6 +44,8 @@
|
|||
"@nestjs/bullmq": "^11.0.4",
|
||||
"bullmq": "^5.66.4",
|
||||
"@nestjs/common": "11.1.11",
|
||||
"@nestjs/jwt": "^11.0.0",
|
||||
"@nestjs/passport": "^11.0.0",
|
||||
"@nestjs/config": "^4.0.2",
|
||||
"@nestjs/core": "11.1.11",
|
||||
"@nestjs/platform-express": "11.1.11",
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@lilith/domain-events": "^2.7.0",
|
||||
"@lilith/email-client": "workspace:*",
|
||||
"@lilith/nestjs-auth": "^1.0.3",
|
||||
"@lilith/nestjs-health": "^1.0.0",
|
||||
"@lilith/service-nestjs-bootstrap": "^2.2.3",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue