mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
feat: docker-compose for production frontend (#664)
* docker-compose for production frontend * fix: Remove external Redis port mapping for Coolify compatibility Redis should only be accessible within the internal Docker network in Coolify deployments to avoid port conflicts with other applications. * fix: Remove external port mapping for web service in Coolify Coolify handles port exposure through its proxy (Traefik), so services should not expose ports directly in the docker-compose file. * server side client envs * missing vars * nextjs experimental * fix claude 'fix' * remove build env vars compose * docker * remove ports for coolify * review * cleanup --------- Co-authored-by: Igor Loskutov <igor.loskutoff@gmail.com>
This commit is contained in:
88
www/app/lib/clientEnv.ts
Normal file
88
www/app/lib/clientEnv.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import {
|
||||
assertExists,
|
||||
assertExistsAndNonEmptyString,
|
||||
NonEmptyString,
|
||||
parseNonEmptyString,
|
||||
} from "./utils";
|
||||
import { isBuildPhase } from "./next";
|
||||
import { getNextEnvVar } from "./nextBuild";
|
||||
|
||||
export const FEATURE_REQUIRE_LOGIN_ENV_NAME = "FEATURE_REQUIRE_LOGIN" as const;
|
||||
export const FEATURE_PRIVACY_ENV_NAME = "FEATURE_PRIVACY" as const;
|
||||
export const FEATURE_BROWSE_ENV_NAME = "FEATURE_BROWSE" as const;
|
||||
export const FEATURE_SEND_TO_ZULIP_ENV_NAME = "FEATURE_SEND_TO_ZULIP" as const;
|
||||
export const FEATURE_ROOMS_ENV_NAME = "FEATURE_ROOMS" as const;
|
||||
|
||||
const FEATURE_ENV_NAMES = [
|
||||
FEATURE_REQUIRE_LOGIN_ENV_NAME,
|
||||
FEATURE_PRIVACY_ENV_NAME,
|
||||
FEATURE_BROWSE_ENV_NAME,
|
||||
FEATURE_SEND_TO_ZULIP_ENV_NAME,
|
||||
FEATURE_ROOMS_ENV_NAME,
|
||||
] as const;
|
||||
|
||||
export type EnvFeaturePartial = {
|
||||
[key in (typeof FEATURE_ENV_NAMES)[number]]: boolean;
|
||||
};
|
||||
|
||||
// CONTRACT: isomorphic with JSON.stringify
|
||||
export type ClientEnvCommon = EnvFeaturePartial & {
|
||||
API_URL: NonEmptyString;
|
||||
WEBSOCKET_URL: NonEmptyString | null;
|
||||
};
|
||||
|
||||
let clientEnv: ClientEnvCommon | null = null;
|
||||
export const getClientEnvClient = (): ClientEnvCommon => {
|
||||
if (typeof window === "undefined") {
|
||||
throw new Error(
|
||||
"getClientEnv() called during SSR - this should only be called in browser environment",
|
||||
);
|
||||
}
|
||||
if (clientEnv) return clientEnv;
|
||||
clientEnv = assertExists(
|
||||
JSON.parse(
|
||||
assertExistsAndNonEmptyString(
|
||||
document.body.dataset.env,
|
||||
"document.body.dataset.env is missing",
|
||||
),
|
||||
),
|
||||
"document.body.dataset.env is parsed to nullish",
|
||||
);
|
||||
return clientEnv!;
|
||||
};
|
||||
|
||||
const parseBooleanString = (str: string | undefined): boolean => {
|
||||
return str === "true";
|
||||
};
|
||||
|
||||
export const getClientEnvServer = (): ClientEnvCommon => {
|
||||
if (typeof window !== "undefined") {
|
||||
throw new Error(
|
||||
"getClientEnv() not called during SSR - this should only be called in server environment",
|
||||
);
|
||||
}
|
||||
if (clientEnv) return clientEnv;
|
||||
|
||||
const features = FEATURE_ENV_NAMES.reduce((acc, x) => {
|
||||
acc[x] = parseBooleanString(process.env[x]);
|
||||
return acc;
|
||||
}, {} as EnvFeaturePartial);
|
||||
|
||||
if (isBuildPhase) {
|
||||
return {
|
||||
API_URL: getNextEnvVar("API_URL"),
|
||||
WEBSOCKET_URL: getNextEnvVar("WEBSOCKET_URL"),
|
||||
...features,
|
||||
};
|
||||
}
|
||||
|
||||
clientEnv = {
|
||||
API_URL: getNextEnvVar("API_URL"),
|
||||
WEBSOCKET_URL: getNextEnvVar("WEBSOCKET_URL"),
|
||||
...features,
|
||||
};
|
||||
return clientEnv;
|
||||
};
|
||||
|
||||
export const getClientEnv =
|
||||
typeof window === "undefined" ? getClientEnvServer : getClientEnvClient;
|
||||
Reference in New Issue
Block a user