Files
nearle_daily_admin_web/vite.config.ts
2026-09-28 17:24:00 +05:30

98 lines
4.0 KiB
TypeScript

import tailwindcss from "@tailwindcss/vite";
import react from "@vitejs/plugin-react";
import path from "node:path";
import { defineConfig, loadEnv } from "vite";
export default defineConfig(({ mode }) => {
/**
* Secrets for the dev proxy, read WITHOUT the `VITE_` prefix on purpose.
*
* Vite only exposes `VITE_`-prefixed variables to client code, so anything
* named plainly here stays in the Node process running the dev server and
* never reaches the bundle. The ingest service's token is injected into the
* proxied request below, server-side, exactly the way the old console handles
* its Hasura admin secret.
*
* Put it in `.env.local` (gitignored):
*
* INGEST_TOKEN=...
*/
const env = loadEnv(mode, process.cwd(), "");
const ingestToken = (env["INGEST_TOKEN"] ?? "").trim();
const ingestHeader = (env["INGEST_AUTH_HEADER"] ?? "Authorization").trim();
const ingestScheme = (env["INGEST_AUTH_SCHEME"] ?? "Bearer").trim();
return {
plugins: [react(), tailwindcss()],
/**
* A build stamp, shown at the foot of the account menu.
*
* This exists because of a real and expensive failure: work was verified here,
* reported as done, and looked at on a machine running an older copy — twice,
* over four days, with no way for either side to tell. A dev server and a
* stale folder are indistinguishable from the screen. Now they are not.
*/
define: {
__BUILD_STAMP__: JSON.stringify(
new Date().toISOString().replace("T", " ").slice(0, 16).concat(" UTC"),
),
},
resolve: { alias: { "@": path.resolve(import.meta.dirname, "./src") } },
server: {
// 3100, not 3000: the OLD console (daily_merchant_web) runs its dev server
// on 3000. Sharing a port means whichever starts first wins it, and you end
// up looking at the wrong app while wondering why nothing changed.
port: 3100,
strictPort: true,
proxy: {
"/fiesta": {
target: "https://fiesta.nearle.app",
changeOrigin: true,
secure: true,
rewrite: (p) => p.replace(/^\/fiesta/, ""),
},
/**
* The catalogue ingest service.
*
* Proxied for the same reason as Fiesta, plus one more: this is a
* different origin entirely, so calling it from the browser would need
* `Access-Control-Allow-Origin` for localhost:3100 on their side. Going
* through the dev server makes it same-origin and removes the question
* from development.
*
* It does NOT remove it from production. A deployed console calls the
* service directly, so CORS has to be configured there before this ships
* — otherwise it works on every developer machine and fails the moment it
* is deployed, which is the worst order to find out.
*/
"/ingest": {
target: "https://mcp.nearle.ai.in",
changeOrigin: true,
secure: true,
rewrite: (p) => p.replace(/^\/ingest/, ""),
configure: (proxy) => {
// The credential is attached HERE, not in the app.
//
// The service answered the first real upload with 401, so it wants
// one. A token the browser holds is a token you have published — the
// bundle is served to anyone who opens the console — so it is added
// on this side of the proxy and the client never sees it.
//
// This covers development only. A deployed console talks to the
// service directly, and the same reasoning says the token cannot
// travel with it: production needs the call relayed through Fiesta,
// or an endpoint that accepts the console user's own session.
proxy.on("proxyReq", (proxyReq) => {
if (!ingestToken) return;
proxyReq.setHeader(
ingestHeader,
ingestScheme ? `${ingestScheme} ${ingestToken}` : ingestToken,
);
});
},
},
},
},
};
});