mirror of
https://github.com/Infisical/infisical.git
synced 2026-01-08 15:13:55 -05:00
108 lines
3.2 KiB
TypeScript
108 lines
3.2 KiB
TypeScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
|
|
import staticServe from "@fastify/static";
|
|
import RE2 from "re2";
|
|
|
|
import { getConfig, IS_PACKAGED } from "@app/lib/config/env";
|
|
|
|
// to enabled this u need to set standalone mode to true
|
|
export const registerServeUI = async (
|
|
server: FastifyZodProvider,
|
|
{
|
|
standaloneMode,
|
|
dir
|
|
}: {
|
|
standaloneMode?: boolean;
|
|
dir: string;
|
|
}
|
|
) => {
|
|
const appCfg = getConfig();
|
|
const cdnHost = appCfg.CDN_HOST || "";
|
|
|
|
// use this only for frontend runtime static non-sensitive configuration in standalone mode
|
|
// that app needs before loading like posthog dsn key
|
|
// for most of the other usecase use server config
|
|
server.route({
|
|
method: "GET",
|
|
url: "/runtime-ui-env.js",
|
|
schema: {
|
|
hide: true
|
|
},
|
|
handler: (_req, res) => {
|
|
void res.type("application/javascript");
|
|
const config = {
|
|
CAPTCHA_SITE_KEY: appCfg.CAPTCHA_SITE_KEY,
|
|
POSTHOG_API_KEY: appCfg.POSTHOG_PROJECT_API_KEY,
|
|
INTERCOM_ID: appCfg.INTERCOM_ID,
|
|
TELEMETRY_CAPTURING_ENABLED: appCfg.TELEMETRY_ENABLED,
|
|
CDN_HOST: cdnHost
|
|
};
|
|
// Define window.__toCdnUrl for Vite's experimental.renderBuiltUrl runtime support
|
|
// This function is called by dynamically imported chunks to resolve CDN URLs
|
|
const js = `
|
|
window.__INFISICAL_RUNTIME_ENV__ = Object.freeze(${JSON.stringify(config)});
|
|
window.__toCdnUrl = function(filename) {
|
|
var cdnHost = window.__INFISICAL_RUNTIME_ENV__.CDN_HOST || "";
|
|
if (cdnHost && filename.startsWith("assets/")) {
|
|
return cdnHost + "/" + filename;
|
|
}
|
|
return "/" + filename;
|
|
};
|
|
`.trim();
|
|
return res.send(js);
|
|
}
|
|
});
|
|
|
|
if (standaloneMode) {
|
|
const frontendName = IS_PACKAGED ? "frontend" : "frontend-build";
|
|
const frontendPath = path.join(dir, frontendName);
|
|
|
|
const indexHtmlPath = path.join(frontendPath, "index.html");
|
|
let indexHtml = fs.readFileSync(indexHtmlPath, "utf-8");
|
|
|
|
if (cdnHost) {
|
|
// Replace relative asset paths with CDN URLs in script and link tags
|
|
indexHtml = indexHtml
|
|
.replace(/src="\/assets\//g, `src="${cdnHost}/assets/`)
|
|
.replace(/href="\/assets\//g, `href="${cdnHost}/assets/`);
|
|
|
|
// Inject CDN host into CSP directives that need it
|
|
const cspDirectives = ["script-src", "style-src", "font-src", "connect-src", "media-src"];
|
|
for (const directive of cspDirectives) {
|
|
const regex = new RE2(`(${directive}\\s+'self')`, "g");
|
|
indexHtml = indexHtml.replace(regex, `$1 ${cdnHost}`);
|
|
}
|
|
}
|
|
|
|
await server.register(staticServe, {
|
|
root: frontendPath,
|
|
wildcard: false,
|
|
maxAge: "30d",
|
|
immutable: true,
|
|
index: false
|
|
});
|
|
|
|
server.route({
|
|
method: "GET",
|
|
url: "/*",
|
|
schema: {
|
|
hide: true
|
|
},
|
|
handler: (request, reply) => {
|
|
if (request.url.startsWith("/api")) {
|
|
reply.callNotFound();
|
|
return;
|
|
}
|
|
|
|
return reply
|
|
.type("text/html")
|
|
.header("Cache-Control", "no-cache, no-store, must-revalidate")
|
|
.header("Pragma", "no-cache")
|
|
.header("Expires", "0")
|
|
.send(indexHtml);
|
|
}
|
|
});
|
|
}
|
|
};
|