add a CLIENT_CONFIG to the client, serve from BE with env vars

This commit is contained in:
Alex Holliday committed 2026-07-09 09:49:45 -07:00
1 parent ef175950b2
commit 62031a0ab1
12 files changed
+81 -7

No files matched your search

+7
View File
@@ -52,6 +52,13 @@ export const createApp = ({
app.use(createStatusPageDocumentCsp(allowedOrigin));
// Client runtime config; registered before express.static so it shadows the
// fallback config.js in the client build output
const clientConfigScript = `window.__CHECKMATE_CONFIG__ = ${JSON.stringify(envSettings.clientConfig).replace(/</g, "\\u003c")};`;
app.get("/config.js", (req, res) => {
res.set("Cache-Control", "no-cache").type("application/javascript").send(clientConfigScript);
});
app.use(express.static(frontendPath));
app.use(express.json());
+8 -2
View File
@@ -1,5 +1,5 @@
import { z } from "zod";
import { DbTypes, QueueModes } from "@/domain/app-settings/app-settings.type.js";
import { DbTypes, LogLevels, QueueModes } from "@/domain/app-settings/app-settings.type.js";
import { booleanCoercion } from "@/api/validation/shared.js";
import { ILogger } from "@/utils/logger.js";
@@ -9,7 +9,7 @@ const envSchema = z.object({
// Port for worker health checks
HEALTH_PORT: z.string().default("52346"),
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
LOG_LEVEL: z.enum(["error", "warn", "info", "debug"]).default("debug"),
LOG_LEVEL: z.enum(LogLevels).default("debug"),
// Database
DB_CONNECTION_STRING: z.string().min(1, "Database connection string is required"),
@@ -25,6 +25,12 @@ const envSchema = z.object({
// Client Configuration
CLIENT_HOST: z.string().url("CLIENT_HOST must be a valid URL"),
// Client runtime config overrides, rendered into GET /config.js; unset keys are
// omitted and the client uses its same-origin defaults
CLIENT_CONFIG_API_BASE_URL: z.string().optional(),
CLIENT_CONFIG_CLIENT_HOST: z.string().url("CLIENT_CONFIG_CLIENT_HOST must be a valid URL").optional(),
CLIENT_CONFIG_LOG_LEVEL: z.enum(LogLevels).optional(),
// Optional
ORIGIN: z.string().optional(),
@@ -1,5 +1,5 @@
import { ISettingsRepository } from "@/domain/app-settings/app-settings-repository.interface.js";
import { Settings, SettingsUpdate, type DbType, type QueueMode } from "@/domain/app-settings/app-settings.type.js";
import { Settings, SettingsUpdate, type ClientRuntimeConfig, type DbType, type QueueMode } from "@/domain/app-settings/app-settings.type.js";
import { AppError } from "@/utils/AppError.js";
import { ValidatedEnv } from "@/config/envValidation.js";
import type { StringValue } from "ms";
@@ -16,6 +16,7 @@ export type EnvConfig = {
queueMode: QueueMode;
queuePrimaryProcesses: boolean;
statusPageThemesEnabled: boolean;
clientConfig: ClientRuntimeConfig;
};
export interface ISettingsService {
@@ -44,6 +45,11 @@ export class SettingsService implements ISettingsService {
queueMode: env.QUEUE_MODE,
queuePrimaryProcesses: env.QUEUE_PRIMARY_PROCESSES,
statusPageThemesEnabled: env.STATUS_PAGE_THEMES_ENABLED,
clientConfig: {
...(env.CLIENT_CONFIG_API_BASE_URL && { apiBaseUrl: env.CLIENT_CONFIG_API_BASE_URL }),
...(env.CLIENT_CONFIG_CLIENT_HOST && { clientHost: env.CLIENT_CONFIG_CLIENT_HOST }),
...(env.CLIENT_CONFIG_LOG_LEVEL && { logLevel: env.CLIENT_CONFIG_LOG_LEVEL }),
},
};
}
@@ -4,6 +4,17 @@ export type DbType = (typeof DbTypes)[number];
export const QueueModes = ["primary", "worker"] as const;
export type QueueMode = (typeof QueueModes)[number];
export const LogLevels = ["error", "warn", "info", "debug"] as const;
export type LogLevel = (typeof LogLevels)[number];
// Rendered into GET /config.js as window.__CHECKMATE_CONFIG__; keys left unset
// fall back to the client's same-origin defaults.
export type ClientRuntimeConfig = {
apiBaseUrl?: string;
clientHost?: string;
logLevel?: LogLevel;
};
export interface SettingsThresholds {
cpu?: number;
memory?: number;