Refactor API configuration and improve WebSocket handling in frontend and backend
This commit is contained in:
@@ -1,10 +1,15 @@
|
||||
# Frontend Environment Variables
|
||||
# Copy this file to .env.local for local development
|
||||
|
||||
# API Configuration
|
||||
# Backend API base URL (must include /api path)
|
||||
# ===================
|
||||
# API CONFIGURATION
|
||||
# ===================
|
||||
|
||||
# Backend API URL (must include /api path)
|
||||
# Default for development: http://localhost:8080/api
|
||||
VITE_API_URL=http://localhost:8080/api
|
||||
|
||||
# WebSocket Configuration
|
||||
# WebSocket server URL for real-time collaboration (must include /ws path)
|
||||
# WebSocket URL (must include /ws path)
|
||||
# Default for development: ws://localhost:8080/ws
|
||||
# Use wss:// for production (secure WebSocket)
|
||||
VITE_WS_URL=ws://localhost:8080/ws
|
||||
|
||||
@@ -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');
|
||||
|
||||
24
frontend/src/config/index.ts
Normal file
24
frontend/src/config/index.ts
Normal 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';
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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`;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user