Refactor API configuration and improve WebSocket handling in frontend and backend

This commit is contained in:
M1ngdaXie
2026-02-03 17:25:11 -08:00
parent 35c4aa2580
commit 70a406c73c
14 changed files with 335 additions and 131 deletions

View File

@@ -1,4 +1,4 @@
const API_BASE_URL = import.meta.env.VITE_API_URL || "https://docnest-backend-mingda.fly.dev/api";
import { API_BASE_URL } from '../config';
export async function authFetch(url: string, options?: RequestInit): Promise<Response> {
const token = localStorage.getItem('auth_token');

View File

@@ -0,0 +1,24 @@
interface Config {
apiUrl: string;
wsUrl: string;
environment: 'development' | 'production';
}
function loadConfig(): Config {
const apiUrl = import.meta.env.VITE_API_URL || 'http://localhost:8080/api';
const wsUrl = import.meta.env.VITE_WS_URL || 'ws://localhost:8080/ws';
const environment = import.meta.env.MODE === 'production' ? 'production' : 'development';
return {
apiUrl,
wsUrl,
environment,
};
}
export const config = loadConfig();
// Convenience exports
export const API_BASE_URL = config.apiUrl;
export const WS_URL = config.wsUrl;
export const isProduction = config.environment === 'production';

View File

@@ -47,6 +47,13 @@ export const useYjsDocument = (documentId: string, shareToken?: string) => {
let currentProviders: YjsProviders | null = null;
const initializeDocument = async () => {
// Read port override from query param for testing multiple backends
const searchParams = new URLSearchParams(window.location.search);
const portOverride = searchParams.get('port');
const wsUrlOverride = portOverride
? `ws://localhost:${portOverride}/ws`
: undefined;
// For share token access, use placeholder user info
// Extract user data (handle both direct user object and nested structure for backwards compat)
const realUser = user || {
@@ -69,12 +76,16 @@ export const useYjsDocument = (documentId: string, shareToken?: string) => {
});
const authToken = token || "";
console.log("authToken is " + token);
if (wsUrlOverride) {
console.log(`🔧 Using WebSocket URL override: ${wsUrlOverride}`);
}
const yjsProviders = await createYjsDocument(
documentId,
{ id: currentId, name: currentName, avatar_url: currentAvatar },
authToken,
shareToken
shareToken,
wsUrlOverride
);
currentProviders = yjsProviders;

View File

@@ -3,8 +3,7 @@ import { Awareness } from "y-protocols/awareness";
import { WebsocketProvider } from "y-websocket";
import * as Y from "yjs";
import { documentsApi } from "../api/document";
const WS_URL = import.meta.env.VITE_WS_URL || "wss://docnest-backend-mingda.fly.dev/ws";
import { WS_URL } from "../config";
export interface YjsProviders {
ydoc: Y.Doc;
@@ -23,7 +22,8 @@ export const createYjsDocument = async (
documentId: string,
_user: YjsUser,
token: string,
shareToken?: string
shareToken?: string,
wsUrlOverride?: string
): Promise<YjsProviders> => {
// Create Yjs document
const ydoc = new Y.Doc();
@@ -46,8 +46,9 @@ export const createYjsDocument = async (
const wsParams: { [key: string]: string } = shareToken
? { share: shareToken }
: { token: token };
const wsUrl = wsUrlOverride || WS_URL;
const websocketProvider = new WebsocketProvider(
WS_URL,
wsUrl,
documentId,
ydoc,
{ params: wsParams }

View File

@@ -1,9 +1,8 @@
import FloatingGem from '../components/PixelSprites/FloatingGem';
import PixelIcon from '../components/PixelIcon/PixelIcon';
import { API_BASE_URL } from '../config';
import './LandingPage.css';
const API_BASE_URL = import.meta.env.VITE_API_URL || "https://docnest-backend-mingda.fly.dev/api";
function LandingPage() {
const handleGoogleLogin = () => {
window.location.href = `${API_BASE_URL}/auth/google`;

View File

@@ -1,10 +1,9 @@
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../contexts/AuthContext';
import { API_BASE_URL } from '../config';
import './LoginPage.css';
const API_BASE_URL = import.meta.env.VITE_API_URL || "https://docnest-backend-mingda.fly.dev/api";
function LoginPage() {
const { user, loading } = useAuth();
const navigate = useNavigate();