From 615eac37ad5239d1b2ca194859851b629a0c5fcf Mon Sep 17 00:00:00 2001 From: Nicole Rappe Date: Sun, 4 May 2025 21:49:07 -0600 Subject: [PATCH] Heavy Launch / Build Optimizations --- Launch-Borealis.ps1 => Borealis.ps1 | 76 +++++++++++++++++++---------- Launch-Borealis.sh => Borealis.sh | 0 Data/Server/WebUI/index.html | 2 +- Data/Server/WebUI/vite.config.mts | 39 +++++++++++++++ Data/Server/WebUI/vite.config.ts | 33 ------------- Data/Server/server.py | 26 ++++++++-- 6 files changed, 114 insertions(+), 62 deletions(-) rename Launch-Borealis.ps1 => Borealis.ps1 (77%) rename Launch-Borealis.sh => Borealis.sh (100%) create mode 100644 Data/Server/WebUI/vite.config.mts delete mode 100644 Data/Server/WebUI/vite.config.ts diff --git a/Launch-Borealis.ps1 b/Borealis.ps1 similarity index 77% rename from Launch-Borealis.ps1 rename to Borealis.ps1 index 8e3dbd2..096c77d 100644 --- a/Launch-Borealis.ps1 +++ b/Borealis.ps1 @@ -63,6 +63,10 @@ function Run-Step { } } +# ---------------------- Server Deployment / Operation Mode Variables ---------------------- +# Define the default operation mode: production | developer +[string]$borealis_operation_mode = 'production' + # ---------------------- Bundle Executables Setup ---------------------- $scriptDir = Split-Path $MyInvocation.MyCommand.Path -Parent $depsRoot = Join-Path $scriptDir 'Dependencies' @@ -85,19 +89,40 @@ Write-Host "Workflow Automation Tool" -ForegroundColor Blue Write-Host "====================================================================================" Write-Host " " Write-Host "Please choose which function you want to launch / (re)deploy:" -Write-Host "- Server (Web Dashboard) [1]" -Write-Host "- Agent (Local/Remote Client) [2]" -#Write-Host "- Desktop App (Electron) ((Run Step 1 Beforehand)) [3]" - -$choice = Read-Host "Enter 1 or 2" +Write-Host "1) Borealis Server" +Write-Host "2) Borealis Agent" +Write-Host "3) Build Electron App" +$choice = Read-Host "Type a number and press [ENTER]" switch ($choice) { "1" { - # Server Deployment (Web Dashboard) - Clear-Host - Write-Host "Deploying Borealis - Web Dashboard..." -ForegroundColor Blue - Write-Host "====================================================================================" + Write-Host " " + Write-Host "Configure Borealis Server Mode:" -ForegroundColor Yellow + Write-Host " 1) Build & Launch > [Static] Production Flask Server @ http://localhost:5000" + Write-Host " 2) Launch [Skip Build] > [Static] Production Flask Server @ http://localhost:5000" + Write-Host " 3) Launch [Skip Build] > [Hotload-Enabled] Vite Dev Server @ http://localhost:5173" + $modeChoice = Read-Host "Enter choice [1/2/3]" + + switch ($modeChoice) { + "1" { $borealis_operation_mode = "production" } + "2" { + Run-Step "Borealis: Launch Flask Server" { + Push-Location (Join-Path $scriptDir "Server") + & (Join-Path $scriptDir "Server\Scripts\python.exe") (Join-Path $scriptDir "Server\Borealis\server.py") + Pop-Location + } + Exit 0 + } + "3" { $borealis_operation_mode = "developer" } + default { + Write-Host "Invalid mode choice: $modeChoice" -ForegroundColor Red + Exit 1 + } + } + + # ───── Now run your deploy logic ───── + Write-Host "Deploying Borealis Server in '$borealis_operation_mode' mode" -ForegroundColor Blue $venvFolder = "Server" $dataSource = "Data" @@ -108,9 +133,8 @@ switch ($choice) { # Create Virtual Environment & Copy Server Assets Run-Step "Create Borealis Virtual Python Environment" { - if (-not (Test-Path "$venvFolder\Scripts\Activate")) { - & $pythonExe -m venv $venvFolder | Out-Null - } + # Leverage Bundled Python Dependency to Construct Virtual Python Environment + if (-not (Test-Path "$venvFolder\Scripts\Activate")) { & $pythonExe -m venv $venvFolder | Out-Null } if (Test-Path $dataSource) { Remove-Item $dataDestination -Recurse -Force -ErrorAction SilentlyContinue New-Item -Path $dataDestination -ItemType Directory -Force | Out-Null @@ -128,12 +152,14 @@ switch ($choice) { } } - # Copy Vite WebUI assets (no CRA) - Run-Step "Setup Vite WebUI assets" { + # Copy Vite WebUI Assets + Run-Step "Copy Borealis WebUI Files into: $webUIDestination" { if (Test-Path $webUIDestination) { - Remove-Item $webUIDestination -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item "$webUIDestination\public\*" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item "$webUIDestination\src\*" -Recurse -Force -ErrorAction SilentlyContinue + } else { + New-Item -Path $webUIDestination -ItemType Directory -Force | Out-Null } - New-Item -Path $webUIDestination -ItemType Directory -Force | Out-Null Copy-Item "$customUIPath\*" $webUIDestination -Recurse -Force } @@ -145,19 +171,19 @@ switch ($choice) { Pop-Location } - # ---------------------- Dev-mode Vite (HMR) ---------------------- - Run-Step "Vite Web Frontend: Start Dev Server" { + # Vite Operation Mode Control (build vs dev) + Run-Step "Vite Web Frontend: Start ($borealis_operation_mode)" { Push-Location $webUIDestination - # Launch Vite in watch/HMR mode in a new process - Start-Process -NoNewWindow -FilePath $npmCmd -ArgumentList @("run", "dev") + if ($borealis_operation_mode -eq "developer") { $viteSubCommand = "dev" } else { $viteSubCommand = "build" } + Start-Process -NoNewWindow -FilePath $npmCmd -ArgumentList @("run",$viteSubCommand) Pop-Location } # Launch Flask Server Run-Step "Borealis: Launch Flask Server" { - Push-Location (Join-Path $scriptDir 'Server') - $py = Join-Path $scriptDir 'Server\Scripts\python.exe' - $server_py = Join-Path $scriptDir 'Server\Borealis\server.py' + Push-Location (Join-Path $scriptDir "Server") + $py = Join-Path $scriptDir "Server\Scripts\python.exe" + $server_py = Join-Path $scriptDir "Server\Borealis\server.py" Write-Host "`nLaunching Borealis..." -ForegroundColor Green Write-Host "====================================================================================" @@ -166,13 +192,13 @@ switch ($choice) { & $py $server_py Pop-Location } + break } "2" { # Agent Deployment (Client / Data Collector) - Clear-Host + Write-Host " " Write-Host "Deploying Borealis Agent..." -ForegroundColor Blue - Write-Host "====================================================================================" $venvFolder = "Agent" $agentSourcePath = "Data\Agent\borealis-agent.py" diff --git a/Launch-Borealis.sh b/Borealis.sh similarity index 100% rename from Launch-Borealis.sh rename to Borealis.sh diff --git a/Data/Server/WebUI/index.html b/Data/Server/WebUI/index.html index 89071f6..e8ee569 100644 --- a/Data/Server/WebUI/index.html +++ b/Data/Server/WebUI/index.html @@ -7,7 +7,7 @@ - + Borealis diff --git a/Data/Server/WebUI/vite.config.mts b/Data/Server/WebUI/vite.config.mts new file mode 100644 index 0000000..025a5c1 --- /dev/null +++ b/Data/Server/WebUI/vite.config.mts @@ -0,0 +1,39 @@ +////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: /Data/Server/WebUI/vite.config.ts +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import path from 'path'; + +export default defineConfig({ + plugins: [react()], + server: { + open: true, + host: true, + strictPort: true, + allowedHosts: ['localhost','127.0.0.1','borealis.bunny-lab.io'], + proxy: { + '/api': 'http://localhost:5000', + '/socket.io': { target:'ws://localhost:5000', ws:true } + } + }, + build: { + outDir: 'build', + emptyOutDir: true, + chunkSizeWarningLimit: 1000, + rollupOptions: { + output: { + // split each npm package into its own chunk + manualChunks(id) { + if (id.includes('node_modules')) { + return id.toString() + .split('node_modules/')[1] + .split('/')[0]; + } + } + } + } + }, + resolve: { + alias: { '@': path.resolve(__dirname, 'src') }, + extensions: ['.js','.jsx','.ts','.tsx'] + } +}); diff --git a/Data/Server/WebUI/vite.config.ts b/Data/Server/WebUI/vite.config.ts deleted file mode 100644 index d46f4b8..0000000 --- a/Data/Server/WebUI/vite.config.ts +++ /dev/null @@ -1,33 +0,0 @@ -////////// PROJECT FILE SEPARATION LINE ////////// CODE AFTER THIS LINE ARE FROM: /Data/Server/WebUI/vite.config.ts -import { defineConfig } from 'vite'; -import react from '@vitejs/plugin-react'; -import path from 'path'; - -export default defineConfig({ - plugins: [react()], - server: { - open: true, - host: true, // <-- allows LAN access and shows LAN IP - strictPort: true, // <-- Ensures that the port number never changes (Good for Reverse Proxies) - allowedHosts: [ - 'localhost', - '127.0.0.1', - 'borealis.bunny-lab.io' - ], - proxy: { - '/api': 'http://localhost:5000', - '/socket.io': { - target: 'ws://localhost:5000', - ws: true - } - } - }, - build: { - outDir: 'build', - emptyOutDir: true - }, - resolve: { - alias: { '@': path.resolve(__dirname, 'src') }, - extensions: ['.js', '.jsx', '.ts', '.tsx'] - } -}); diff --git a/Data/Server/server.py b/Data/Server/server.py index b9226cf..e15defd 100644 --- a/Data/Server/server.py +++ b/Data/Server/server.py @@ -4,10 +4,11 @@ import eventlet # Monkey-patch stdlib for cooperative sockets eventlet.monkey_patch() -from flask import Flask, request, jsonify, Response +from flask import Flask, request, jsonify, Response, send_from_directory from flask_socketio import SocketIO, emit import time +import os # To Read Production ReactJS Server Folder # Borealis Python API Endpoints from Python_API_Endpoints.ocr_engines import run_ocr_on_base64 @@ -15,7 +16,12 @@ from Python_API_Endpoints.ocr_engines import run_ocr_on_base64 # --------------------------------------------- # Flask + WebSocket Server Configuration # --------------------------------------------- -app = Flask(__name__) +app = Flask( + __name__, + static_folder=os.path.join(os.path.dirname(__file__), '../web-interface/build'), + static_url_path='' +) + socketio = SocketIO( app, cors_allowed_origins="*", @@ -26,6 +32,20 @@ socketio = SocketIO( } ) +# --------------------------------------------- +# Serve ReactJS Production Vite Build from dist/ +# --------------------------------------------- +@app.route('/', defaults={'path': ''}) +@app.route('/') +def serve_dist(path): + full_path = os.path.join(app.static_folder, path) + if path and os.path.isfile(full_path): + return send_from_directory(app.static_folder, path) + else: + # SPA entry point + return send_from_directory(app.static_folder, 'index.html') + + # --------------------------------------------- # Health Check Endpoint # --------------------------------------------- @@ -203,7 +223,7 @@ def receive_screenshot(data): @socketio.on("disconnect") def on_disconnect(): - print("[WS] Agent disconnected") + print("[WebSocket] Connection Disconnected") # --------------------------------------------- # Server Launch