import { existsSync } from "node:fs";
import { join, resolve } from "node:path";
import dotEnvFlow from "dotenv-flow";
import { Env as NodeEnv } from "@ethicdevs/react-monolith";
const NODE_ENV = process.env.NODE_ENV;
const ENV_FILES_DIR = resolve(join(__dirname, ".."));
const baseOpts = {
node_env: NODE_ENV,
};
const files = dotEnvFlow.listDotenvFiles(ENV_FILES_DIR, baseOpts);
function getLoadableFilesDisplay(): string {
return files.filter((path) => existsSync(path) === true).join("\n * ");
}
if (files.length > 0) {
console.log(`[env] Loading environment variables from files:
* ${getLoadableFilesDisplay()}`);
} else {
console.log(
`[env] Found no file to load environment variables from, using system environment.`
);
}
const res = dotEnvFlow.config({
...baseOpts,
encoding: "utf8",
default_node_env: "development",
purge_dotenv: true,
silent: true,
});
if (res.error) {
throw res.error;
}
const isValidNodeEnv = (env?: string | null): env is NodeEnv => {
if (env == null) {
return false;
}
if (["development", "test", "production"].includes(env)) {
return true;
}
return false;
};
const getNodeEnv = (
env?: string | null,
defaultEnv: "production" = "production"
): NodeEnv => {
if (isValidNodeEnv(env)) {
return env;
}
return defaultEnv;
};
const getHostname = (hostname?: string | null): string => {
if (hostname == null || hostname === "fake") {
return "localhost";
}
return String(hostname);
};
const getPort = (port?: string | null): number => {
if (port == null || port === "fake") {
return 4100;
}
return Number(port);
};
const getCookieName = (cookieName?: string | null): string => {
if (cookieName == null || cookieName === "fake") {
throw new Error("[env] COOKIE_NAME is missing.");
}
return String(cookieName);
};
const getDatabaseUrl = (databaseUrl?: string | null): string => {
if (databaseUrl == null || databaseUrl === "fake") {
throw new Error("[env] DATABASE_URL is missing.");
}
return String(databaseUrl);
};
const getDeploymentDomain = (deploymentDomain?: string | null): string => {
if (deploymentDomain == null || deploymentDomain === "fake") {
throw new Error("[env] DEPLOYMENT_DOMAIN is missing.");
}
return String(deploymentDomain);
};
const getDeploymentScheme = (
deploymentScheme?: string | null
): "http" | "https" => {
if (deploymentScheme == null || deploymentScheme === "fake") {
throw new Error("[env] DEPLOYMENT_SCHEME is missing.");
}
const validSchemes = ["http", "https"];
if (validSchemes.includes(deploymentScheme) === false) {
throw new Error(
`[env] DEPLOYMENT_SCHEME value is invalid. Must be one of: "${validSchemes.join(
'", "'
)}". Received: "${deploymentScheme}".`
);
}
return String(deploymentScheme) as "http" | "https";
};
const getCookieSecret = (cookieSecret?: string | null): string => {
if (cookieSecret == null || cookieSecret === "fake") {
throw new Error("[env] COOKIE_SECRET is missing.");
}
return String(cookieSecret);
};
const getGitRepositoriesRoot = (
gitRepositoriesRoot?: string | null
): string => {
if (gitRepositoriesRoot == null || gitRepositoriesRoot === "fake") {
throw new Error("[env] GIT_REPOSITORIES_ROOT is missing.");
}
return String(gitRepositoriesRoot);
};
interface IEnv {
NODE_ENV: NodeEnv;
PORT: number;
HOST: string;
COOKIE_NAME: string;
COOKIE_SECRET: string;
DATABASE_URL: string;
DEPLOYMENT_DOMAIN: string;
DEPLOYMENT_SCHEME: "http" | "https";
GIT_REPOSITORIES_ROOT: string;
}
export const Env: IEnv = {
NODE_ENV: getNodeEnv(process.env.NODE_ENV),
PORT: getPort(process.env.PORT),
HOST: getHostname(process.env.HOST),
COOKIE_NAME: getCookieName(process.env.COOKIE_NAME),
COOKIE_SECRET: getCookieSecret(process.env.COOKIE_SECRET),
DATABASE_URL: getDatabaseUrl(process.env.DATABASE_URL),
DEPLOYMENT_DOMAIN: getDeploymentDomain(process.env.DEPLOYMENT_DOMAIN),
DEPLOYMENT_SCHEME: getDeploymentScheme(process.env.DEPLOYMENT_SCHEME),
GIT_REPOSITORIES_ROOT: getGitRepositoriesRoot(
process.env.GIT_REPOSITORIES_ROOT
),
};