vite.config.ts
Rama main · réplica de lectura del repositorio original.
import { defineConfig, loadEnv, type Plugin } from "vite";
import react from "@vitejs/plugin-react-swc";
import path from "path";
import { execSync } from "child_process";
/**
* Read the current git commit at build time so the Deploy Status panel can
* show which frontend revision is live. Falls back gracefully in sandboxes
* where `git` isn't available or the workspace isn't a git checkout.
*/
function readGit(cmd: string, fallback: string): string {
try {
return execSync(cmd, { stdio: ["ignore", "pipe", "ignore"] })
.toString()
.trim();
} catch {
return fallback;
}
}
const GIT_COMMIT = process.env.VITE_GIT_COMMIT || readGit("git rev-parse --short HEAD", "unknown");
const GIT_COMMIT_FULL = process.env.VITE_GIT_COMMIT_FULL || readGit("git rev-parse HEAD", "unknown");
const GIT_COMMIT_DATE = process.env.VITE_GIT_COMMIT_DATE || readGit("git log -1 --format=%cI", "");
const GIT_BRANCH = process.env.VITE_GIT_BRANCH || readGit("git rev-parse --abbrev-ref HEAD", "unknown");
const BUILD_TIME = new Date().toISOString();
/**
* How this build is deployed and which repo it came from — the update notice
* says what "update" means for THIS instance: a fork on Vercel syncs on GitHub,
* a Docker image pulls a newer tag, a source checkout pulls main.
*/
const DEPLOY_KIND = process.env.FLOWWINK_DEPLOY_KIND || (process.env.VERCEL ? "vercel" : "source");
function repoFromRemote(url: string): string {
const m = url.match(/github\.com[:/]([^/]+\/[^/.]+?)(?:\.git)?$/);
return m ? m[1] : "";
}
const SOURCE_REPO =
process.env.VERCEL_GIT_REPO_OWNER && process.env.VERCEL_GIT_REPO_SLUG
? `${process.env.VERCEL_GIT_REPO_OWNER}/${process.env.VERCEL_GIT_REPO_SLUG}`
: process.env.FLOWWINK_SOURCE_REPO || repoFromRemote(readGit("git config --get remote.origin.url", ""));
/**
* Runtime-overridable Supabase config. Every `import.meta.env.VITE_SUPABASE_*`
* access in src/ is compiled to a `__FLOWWINK_RUNTIME__.<key>` lookup — a
* global assembled by index.html from (a) the values baked in at build time
* (Vite's %VITE_*% HTML replacement) and (b) /runtime-config.js overrides.
* This lets one Docker image serve any Supabase instance: the container
* entrypoint regenerates runtime-config.js from container env vars on every
* start, so self-hosted deployments (Easypanel) switch instances with a
* restart instead of a rebuild. On Vercel and `vite dev`,
* public/runtime-config.js sets no overrides and the baked values apply —
* behavior is unchanged.
*
* NB: the define value must be an entity name (dotted identifier chain) —
* esbuild's dep-optimizer pass rejects arbitrary expressions. Vitest is
* unaffected (vitest.config.ts does not extend this config).
*
* NB2: the baked values reach index.html through the __BAKED_VITE_*__
* placeholders + the plugin below — NOT Vite's %VITE_*% HTML replacement,
* which resolves through `define` and would circularly insert the define
* string itself instead of the value.
*/
const RUNTIME_ENV_KEYS = [
"VITE_SUPABASE_URL",
"VITE_SUPABASE_PUBLISHABLE_KEY",
"VITE_SUPABASE_PROJECT_ID",
];
const RUNTIME_ENV_DEFINES = Object.fromEntries(
RUNTIME_ENV_KEYS.map((key) => [`import.meta.env.${key}`, `__FLOWWINK_RUNTIME__.${key}`]),
);
function bakedEnvHtmlPlugin(mode: string): Plugin {
const fileEnv = loadEnv(mode, process.cwd(), "");
return {
name: "flowwink-baked-env-html",
transformIndexHtml(html) {
return html.replace(/__BAKED_(VITE_[A-Z_]+)__/g, (_, key) => {
// Same precedence as Vite itself: real process env beats .env files.
const value = process.env[key] ?? fileEnv[key] ?? "";
if (/["\\]/.test(value)) throw new Error(`${key} must not contain quotes/backslashes`);
return value;
});
},
};
}
export default defineConfig(({ mode }) => ({
server: {
host: "0.0.0.0",
port: 8080,
strictPort: true,
},
plugins: [react(), bakedEnvHtmlPlugin(mode)],
resolve: {
dedupe: ["react", "react-dom", "@codemirror/state", "@codemirror/view"],
alias: {
"@": path.resolve(__dirname, "./src"),
"@templates": path.resolve(__dirname, "./templates"),
},
},
define: {
...RUNTIME_ENV_DEFINES,
__GIT_COMMIT__: JSON.stringify(GIT_COMMIT),
__GIT_COMMIT_FULL__: JSON.stringify(GIT_COMMIT_FULL),
__GIT_COMMIT_DATE__: JSON.stringify(GIT_COMMIT_DATE),
__GIT_BRANCH__: JSON.stringify(GIT_BRANCH),
__BUILD_TIME__: JSON.stringify(BUILD_TIME),
__DEPLOY_KIND__: JSON.stringify(DEPLOY_KIND),
__SOURCE_REPO__: JSON.stringify(SOURCE_REPO),
},
}));