lazy load socket connection
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { redirect } from 'next/navigation';
|
||||
import { loginUser, getOpenToken } from '@/lib/api/server/auth';
|
||||
import { login } from '@/lib/auth/server';
|
||||
import { login, logout } from '@/lib/auth/server';
|
||||
|
||||
export type LoginResult = {
|
||||
success: boolean;
|
||||
@@ -43,5 +43,5 @@ export async function loginAction(prevState: LoginResult, formData: FormData) {
|
||||
}
|
||||
|
||||
export async function logoutAction() {
|
||||
redirect('/logout');
|
||||
logout();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { SessionData } from '@/lib/session/config';
|
||||
|
||||
const BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || 'http://localhost:8080';
|
||||
|
||||
export type ClientApiResponse<T> = {
|
||||
@@ -8,6 +10,17 @@ export type ClientApiResponse<T> = {
|
||||
message?: string;
|
||||
};
|
||||
|
||||
const getSession = async (): Promise<SessionData | null> => {
|
||||
const response = await fetch('/api/session');
|
||||
if (response.ok) {
|
||||
return await response.json();
|
||||
}
|
||||
return null;
|
||||
};
|
||||
const destroySession = async (): Promise<void> => {
|
||||
await fetch('/api/session', { method: 'DELETE' });
|
||||
};
|
||||
|
||||
export async function fetchClientAPI<T>(
|
||||
endpoint: string,
|
||||
method: string = 'GET',
|
||||
@@ -15,13 +28,11 @@ export async function fetchClientAPI<T>(
|
||||
customToken?: string
|
||||
): Promise<ClientApiResponse<T>> {
|
||||
let token = customToken;
|
||||
let session: SessionData | null = null;
|
||||
|
||||
if (!token) {
|
||||
const response = await fetch('/api/session');
|
||||
if (response.ok) {
|
||||
const session = await response.json();
|
||||
token = session.openToken;
|
||||
}
|
||||
session = await getSession();
|
||||
token = session?.openToken;
|
||||
|
||||
if (!token) {
|
||||
throw new Error('No authentication token available');
|
||||
@@ -41,7 +52,8 @@ export async function fetchClientAPI<T>(
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 401) {
|
||||
window.location.href = '/logout';
|
||||
await destroySession();
|
||||
window.location.href = '/login';
|
||||
return { error: 'unauthorized' };
|
||||
}
|
||||
throw new Error(`API Error: ${response.statusText} - ${method} - ${BASE_URL}${endpoint}`);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
const BASE_URL = process.env.API_BASE_URL || 'http://localhost:8080';
|
||||
|
||||
type ApiResponse<T> = {
|
||||
@@ -8,6 +6,10 @@ type ApiResponse<T> = {
|
||||
message?: string;
|
||||
};
|
||||
|
||||
const destroySession = async (): Promise<void> => {
|
||||
await fetch('/api/session', { method: 'DELETE' });
|
||||
};
|
||||
|
||||
export async function fetchServerAPI<T>(
|
||||
endpoint: string,
|
||||
token: string,
|
||||
@@ -28,7 +30,8 @@ export async function fetchServerAPI<T>(
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status == 401) {
|
||||
redirect('/logout');
|
||||
await destroySession();
|
||||
window.location.href = '/login';
|
||||
return { error: 'unauthorized' };
|
||||
}
|
||||
throw new Error(
|
||||
|
||||
@@ -8,11 +8,12 @@ export async function getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
export async function requireAuth() {
|
||||
export async function requireAuth(skipRedirect?: boolean) {
|
||||
const session = await getSession();
|
||||
|
||||
if (!session.token || !session.user) {
|
||||
redirect('/logout');
|
||||
if (!skipRedirect && (!session.token || !session.user)) {
|
||||
session.destroy();
|
||||
redirect('/login');
|
||||
}
|
||||
|
||||
return session;
|
||||
|
||||
7
src/lib/websocket/config.ts
Normal file
7
src/lib/websocket/config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export interface WebsocketOptions {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export const websocketOptions: WebsocketOptions = {
|
||||
url: process.env.NEXT_PUBLIC_WEBSOCKET_URL || 'ws://localhost:3000/ws'
|
||||
};
|
||||
@@ -1,7 +1,16 @@
|
||||
'use client';
|
||||
|
||||
import { createContext, useContext, useEffect, useState, ReactNode, useCallback } from 'react';
|
||||
import {
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useState,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useRef
|
||||
} from 'react';
|
||||
import { WebSocketClient, MessageHandler, ConnectionStatusHandler } from './client';
|
||||
import { websocketOptions } from './config';
|
||||
|
||||
interface WebSocketContextType {
|
||||
client: WebSocketClient | null;
|
||||
@@ -30,10 +39,10 @@ export function useWebSocket() {
|
||||
|
||||
interface WebSocketProviderProps {
|
||||
children: ReactNode;
|
||||
websocketURL: string;
|
||||
openToken: string;
|
||||
}
|
||||
|
||||
export function WebSocketProvider({ children, websocketURL }: WebSocketProviderProps) {
|
||||
export function WebSocketProvider({ children, openToken }: WebSocketProviderProps) {
|
||||
const [client, setClient] = useState<WebSocketClient | null>(null);
|
||||
const [isConnected, setIsConnected] = useState(false);
|
||||
const [connectionStatus, setConnectionStatus] = useState<
|
||||
@@ -51,7 +60,7 @@ export function WebSocketProvider({ children, websocketURL }: WebSocketProviderP
|
||||
client.disconnect();
|
||||
}
|
||||
|
||||
const newClient = new WebSocketClient(token, websocketURL);
|
||||
const newClient = new WebSocketClient(token, websocketOptions.url);
|
||||
|
||||
const statusHandler: ConnectionStatusHandler = (status, error) => {
|
||||
setConnectionStatus(status);
|
||||
@@ -82,7 +91,7 @@ export function WebSocketProvider({ children, websocketURL }: WebSocketProviderP
|
||||
}
|
||||
}, [client]);
|
||||
|
||||
const reconnect = async () => {
|
||||
const reconnect = useCallback(async () => {
|
||||
if (client) {
|
||||
try {
|
||||
await client.reconnect();
|
||||
@@ -91,37 +100,60 @@ export function WebSocketProvider({ children, websocketURL }: WebSocketProviderP
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
};
|
||||
}, [client]);
|
||||
const hasInitialized = useRef(false);
|
||||
|
||||
const associateWithServer = (serverId: string) => {
|
||||
if (client && isConnected) {
|
||||
client.associateWithServer(serverId);
|
||||
}
|
||||
};
|
||||
const associateWithServer = useCallback(
|
||||
(serverId: string) => {
|
||||
if (openToken && !isConnected && !hasInitialized.current) {
|
||||
hasInitialized.current = true;
|
||||
connect(openToken).catch((error) => {
|
||||
console.error('Failed to connect WebSocket:', error);
|
||||
hasInitialized.current = false;
|
||||
});
|
||||
}
|
||||
if (client && isConnected) {
|
||||
client.associateWithServer(serverId);
|
||||
}
|
||||
},
|
||||
[client, isConnected, connect]
|
||||
);
|
||||
|
||||
const addMessageHandler = (handler: MessageHandler) => {
|
||||
if (client) {
|
||||
client.addMessageHandler(handler);
|
||||
}
|
||||
};
|
||||
const addMessageHandler = useCallback(
|
||||
(handler: MessageHandler) => {
|
||||
if (client) {
|
||||
client.addMessageHandler(handler);
|
||||
}
|
||||
},
|
||||
[client]
|
||||
);
|
||||
|
||||
const removeMessageHandler = (handler: MessageHandler) => {
|
||||
if (client) {
|
||||
client.removeMessageHandler(handler);
|
||||
}
|
||||
};
|
||||
const removeMessageHandler = useCallback(
|
||||
(handler: MessageHandler) => {
|
||||
if (client) {
|
||||
client.removeMessageHandler(handler);
|
||||
}
|
||||
},
|
||||
[client]
|
||||
);
|
||||
|
||||
const addConnectionStatusHandler = (handler: ConnectionStatusHandler) => {
|
||||
if (client) {
|
||||
client.addConnectionStatusHandler(handler);
|
||||
}
|
||||
};
|
||||
const addConnectionStatusHandler = useCallback(
|
||||
(handler: ConnectionStatusHandler) => {
|
||||
if (client) {
|
||||
client.addConnectionStatusHandler(handler);
|
||||
}
|
||||
},
|
||||
[client]
|
||||
);
|
||||
|
||||
const removeConnectionStatusHandler = (handler: ConnectionStatusHandler) => {
|
||||
if (client) {
|
||||
client.removeConnectionStatusHandler(handler);
|
||||
}
|
||||
};
|
||||
const removeConnectionStatusHandler = useCallback(
|
||||
(handler: ConnectionStatusHandler) => {
|
||||
if (client) {
|
||||
client.removeConnectionStatusHandler(handler);
|
||||
}
|
||||
},
|
||||
[client]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
|
||||
Reference in New Issue
Block a user