Docs / Validate documentation (push) Canceled after 0s
Docs / Deploy GitHub Pages (push) Canceled after 0s
CI Final Summary (AI) / AI Final Summary (push) Canceled after 0s
CI Final Summary (AI) / Push/PR event feed (push) Canceled after 0s
CI / CI Integrity and Change Classification (push) Canceled after 0s
CI / Code Quality & Tests (push) Canceled after 0s
Dependency Lock & Migration Safety / Dependency drift (lock vs pyproject) (push) Canceled after 0s
Dependency Lock & Migration Safety / Migration safety (fail-loud + version postconditions) (push) Canceled after 0s
JS Tests / Frontend JS Unit Tests (push) Canceled after 0s
Security / CodeQL Analysis (push) Canceled after 0s
Security / Trivy Vulnerability Scan (push) Canceled after 0s
Tests (OS Matrix) / Py Tests (macos-latest) (push) Canceled after 0s
Tests (OS Matrix) / Py Tests (windows-latest) (push) Canceled after 0s
CI / Extended Validation (Tier 2) (push) Canceled after 0s
CI / Heavy CI (database-provider) (push) Canceled after 0s
CI / Heavy CI (e2e) (push) Canceled after 0s
CI / Heavy CI (integration) (push) Canceled after 0s
CI / Heavy CI (model-validation) (push) Canceled after 0s
CI / Heavy CI (research-backtest) (push) Canceled after 0s
CI / Aggregate CI Results (push) Canceled after 0s
Full project import for the self-hosted code hosting (https://code.aifunny.ltd/gavindiaz/my-NexusTradingForexBot.git). Includes the live-freshness + scaler-hash fixes for the permanent STALE dashboard (tick_pipeline now_utc stamps; infer_probabilities computes model_input_hash on the actual scaled 70D tensor), the data-fetch default-path fix, the g29 web-auth test fixes, and a Chinese user manual (使用手册.md) for the web dashboard. Scratch diagnostic scripts (check*.py, contain a live web-auth token) and the .kilo/ agent-worktree directory are gitignored, not committed. Co-Authored-By: Claude Code <noreply@anthropic.com>
94 lines
3.3 KiB
TypeScript
94 lines
3.3 KiB
TypeScript
import { defineConfig } from "vite";
|
|
import react from "@vitejs/plugin-react";
|
|
import path from "node:path";
|
|
|
|
// NSE Alternative UI — Vite configuration.
|
|
//
|
|
// Architecture contract (DEC-0002 lineage): Node/Vite is a BUILD/DEV tool only.
|
|
// The production artifact is a fully static `dist/` bundle served by the
|
|
// existing FastAPI process (no Node HTTP server, no extra ports in production).
|
|
//
|
|
// Development: `npm run dev` serves the UI on :5173 and proxies /api, /health,
|
|
// /ws and /web to the authoritative NSE backend (default 127.0.0.1:8080,
|
|
// override with NSE_API_ORIGIN) so cookies/tokens and SSE/WebSockets work
|
|
// without CORS games. The backend stays the single source of truth.
|
|
//
|
|
// BUG-267: when the engine auto-incremented past an occupied port (8080 ->
|
|
// 8081), the launcher records the ACTUAL bind in the repo-root .env
|
|
// (NSE_WEB_ACTUAL_PORT, gitignored). Read it so `npm run dev` proxies to the
|
|
// engine that is actually running instead of a dead :8080 (the "React
|
|
// console shows UNAUTHORIZED / nothing loads" dev trap). Explicit
|
|
// NSE_API_ORIGIN still wins.
|
|
import { existsSync, readFileSync } from "node:fs";
|
|
|
|
function recordedBackendPort(): number | null {
|
|
const envPath = path.resolve(__dirname, "..", ".env");
|
|
if (!existsSync(envPath)) return null;
|
|
try {
|
|
const m = readFileSync(envPath, "utf8").match(/^NSE_WEB_ACTUAL_PORT=(\d{1,5})$/m);
|
|
if (!m) return null;
|
|
const p = Number(m[1]);
|
|
return p >= 1 && p <= 65535 ? p : null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
const backendOrigin =
|
|
process.env.NSE_API_ORIGIN || `http://127.0.0.1:${recordedBackendPort() ?? 8080}`;
|
|
|
|
// WebSocket proxy needs raw TCP (http://); everything else keeps http(s).
|
|
const wsTarget = backendOrigin.replace(/^https/, "http");
|
|
|
|
export default defineConfig({
|
|
plugins: [react()],
|
|
base: "/alt/",
|
|
server: {
|
|
port: 5173,
|
|
strictPort: false,
|
|
proxy: {
|
|
"/api": { target: backendOrigin, changeOrigin: true },
|
|
"/health": { target: backendOrigin, changeOrigin: true },
|
|
"/healthz": { target: backendOrigin, changeOrigin: true },
|
|
// BUG-267: cookie bootstrap in dev — the client's one-shot 401 heal
|
|
// fetches /app.js (the engine's Set-Cookie carrier). Without proxying
|
|
// it, vite answers from its own SPA and no cookie ever lands.
|
|
"/app.js": { target: backendOrigin, changeOrigin: true },
|
|
"/api_client.js": { target: backendOrigin, changeOrigin: true },
|
|
"/ws": {
|
|
target: wsTarget,
|
|
changeOrigin: true,
|
|
ws: true,
|
|
},
|
|
"/web": {
|
|
target: wsTarget,
|
|
changeOrigin: true,
|
|
ws: true,
|
|
},
|
|
// Primary realtime transport: the backend's SSE stream (production
|
|
// uvicorn runs with ws="none"; see src/websocket/realtimeSocket.ts).
|
|
"/api/ticks/stream": {
|
|
target: backendOrigin,
|
|
changeOrigin: true,
|
|
// SSE must not be buffered/compressed by the dev proxy.
|
|
configure: (proxy) => {
|
|
proxy.on("proxyRes", (proxyRes) => {
|
|
proxyRes.headers["cache-control"] = "no-cache";
|
|
proxyRes.headers["x-accel-buffering"] = "no";
|
|
});
|
|
},
|
|
},
|
|
},
|
|
},
|
|
build: {
|
|
outDir: "dist",
|
|
sourcemap: false,
|
|
chunkSizeWarningLimit: 1200,
|
|
},
|
|
resolve: {
|
|
alias: {
|
|
"@": path.resolve(__dirname, "src"),
|
|
},
|
|
},
|
|
});
|