Files
gavindiazandClaude Code 3a005ddcc6
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
chore(repo): initial import of Nexus Trading Forex Bot into self-hosted hosting
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>
2026-09-23 23:24:54 +08:00

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"),
},
},
});