168 lines
5.6 KiB
JavaScript
168 lines
5.6 KiB
JavaScript
// config.js — environment-based JSON config + .env overrides (farmcontrol-api style)
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import { fileURLToPath } from "url";
|
|
import dotenv from "dotenv";
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
// Monorepo: repo-root .env then packages/server/.env (later files only fill missing keys)
|
|
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
|
dotenv.config({ path: path.resolve(__dirname, ".env") });
|
|
|
|
const CONFIG_PATH = path.resolve(__dirname, "config.json");
|
|
|
|
const NODE_ENV = process.env.NODE_ENV || "development";
|
|
|
|
function ensureShape(envConfig) {
|
|
if (!envConfig.server) envConfig.server = {};
|
|
if (!envConfig.app) envConfig.app = {};
|
|
if (!envConfig.database) envConfig.database = {};
|
|
if (!envConfig.database.mongo) envConfig.database.mongo = {};
|
|
if (!envConfig.auth) envConfig.auth = {};
|
|
if (!envConfig.auth.oidc) envConfig.auth.oidc = {};
|
|
if (!envConfig.device) envConfig.device = {};
|
|
if (!envConfig.mqtt) envConfig.mqtt = {};
|
|
if (!envConfig.s3) envConfig.s3 = {};
|
|
if (!envConfig.hub) envConfig.hub = {};
|
|
if (!Array.isArray(envConfig.patches)) envConfig.patches = [];
|
|
}
|
|
|
|
function loadConfig() {
|
|
try {
|
|
if (!fs.existsSync(CONFIG_PATH)) {
|
|
throw new Error(`Configuration file not found at ${CONFIG_PATH}`);
|
|
}
|
|
|
|
const configData = fs.readFileSync(CONFIG_PATH, "utf8");
|
|
const all = JSON.parse(configData);
|
|
|
|
if (!all[NODE_ENV]) {
|
|
throw new Error(
|
|
`Configuration for environment '${NODE_ENV}' not found in config.json`,
|
|
);
|
|
}
|
|
|
|
const envConfig = JSON.parse(JSON.stringify(all[NODE_ENV]));
|
|
ensureShape(envConfig);
|
|
|
|
if (process.env.PORT) {
|
|
envConfig.server.port = Number(process.env.PORT);
|
|
}
|
|
if (process.env.LOG_LEVEL) {
|
|
envConfig.server.logLevel = process.env.LOG_LEVEL;
|
|
}
|
|
if (process.env.CLIENT_URL) {
|
|
envConfig.app.urlClient = process.env.CLIENT_URL;
|
|
}
|
|
if (process.env.MONGODB_URI) {
|
|
envConfig.database.mongo.url = process.env.MONGODB_URI;
|
|
}
|
|
if (process.env.SESSION_SECRET) {
|
|
envConfig.auth.sessionSecret = process.env.SESSION_SECRET;
|
|
}
|
|
if (process.env.OIDC_ISSUER) {
|
|
envConfig.auth.oidc.issuer = process.env.OIDC_ISSUER;
|
|
}
|
|
if (process.env.OIDC_CLIENT_ID) {
|
|
envConfig.auth.oidc.clientId = process.env.OIDC_CLIENT_ID;
|
|
}
|
|
if (process.env.OIDC_CLIENT_SECRET) {
|
|
envConfig.auth.oidc.clientSecret = process.env.OIDC_CLIENT_SECRET;
|
|
}
|
|
if (process.env.OIDC_REDIRECT_URI) {
|
|
envConfig.auth.oidc.redirectUri = process.env.OIDC_REDIRECT_URI;
|
|
}
|
|
if (process.env.OIDC_APP_CALLBACK_URI) {
|
|
envConfig.auth.oidc.appCallbackUri = process.env.OIDC_APP_CALLBACK_URI;
|
|
}
|
|
if (process.env.APP_REDIRECT_URI) {
|
|
envConfig.auth.appRedirectUri = process.env.APP_REDIRECT_URI;
|
|
}
|
|
if (process.env.HUB_API_KEY) {
|
|
envConfig.hub.apiKey = process.env.HUB_API_KEY;
|
|
}
|
|
if (process.env.DEMO_TTN_APP_ID) {
|
|
envConfig.device.ttnApplicationId = process.env.DEMO_TTN_APP_ID;
|
|
}
|
|
if (process.env.DEMO_TTN_DEV_ID) {
|
|
envConfig.device.ttnDeviceId = process.env.DEMO_TTN_DEV_ID;
|
|
}
|
|
if (process.env.DEVICE_TTN_APPLICATION_ID) {
|
|
envConfig.device.ttnApplicationId = process.env.DEVICE_TTN_APPLICATION_ID;
|
|
}
|
|
if (process.env.DEVICE_TTN_DEVICE_ID) {
|
|
envConfig.device.ttnDeviceId = process.env.DEVICE_TTN_DEVICE_ID;
|
|
}
|
|
if (process.env.DEVICE_NAME) {
|
|
envConfig.device.name = process.env.DEVICE_NAME;
|
|
}
|
|
if (process.env.MQTT_CONFIG_PATH) {
|
|
envConfig.mqtt.configPath = process.env.MQTT_CONFIG_PATH;
|
|
}
|
|
if (process.env.S3_BUCKET) {
|
|
envConfig.s3.bucket = process.env.S3_BUCKET;
|
|
}
|
|
if (process.env.AWS_REGION) {
|
|
envConfig.s3.region = process.env.AWS_REGION;
|
|
}
|
|
if (process.env.S3_PREFIX) {
|
|
envConfig.s3.prefix = process.env.S3_PREFIX;
|
|
}
|
|
if (process.env.S3_ENDPOINT) {
|
|
envConfig.s3.endpoint = process.env.S3_ENDPOINT;
|
|
}
|
|
if (process.env.S3_FORCE_PATH_STYLE != null) {
|
|
const v = String(process.env.S3_FORCE_PATH_STYLE).toLowerCase();
|
|
envConfig.s3.forcePathStyle =
|
|
v === "1" || v === "true" || v === "yes";
|
|
}
|
|
if (process.env.S3_ACCESS_KEY_ID) {
|
|
envConfig.s3.accessKeyId = process.env.S3_ACCESS_KEY_ID;
|
|
} else if (process.env.AWS_ACCESS_KEY_ID) {
|
|
envConfig.s3.accessKeyId = process.env.AWS_ACCESS_KEY_ID;
|
|
}
|
|
if (process.env.S3_SECRET_ACCESS_KEY) {
|
|
envConfig.s3.secretAccessKey = process.env.S3_SECRET_ACCESS_KEY;
|
|
} else if (process.env.AWS_SECRET_ACCESS_KEY) {
|
|
envConfig.s3.secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
|
|
}
|
|
if (process.env.S3_SESSION_TOKEN) {
|
|
envConfig.s3.sessionToken = process.env.S3_SESSION_TOKEN;
|
|
} else if (process.env.AWS_SESSION_TOKEN) {
|
|
envConfig.s3.sessionToken = process.env.AWS_SESSION_TOKEN;
|
|
}
|
|
|
|
if (!envConfig.auth.sessionSecret) {
|
|
throw new Error(
|
|
"SESSION_SECRET environment variable is required, or set auth.sessionSecret in config.json for this environment.",
|
|
);
|
|
}
|
|
|
|
if (NODE_ENV === "production") {
|
|
if (!envConfig.database.mongo.url?.trim()) {
|
|
throw new Error(
|
|
"database.mongo.url must be set for production (config.json or MONGODB_URI).",
|
|
);
|
|
}
|
|
if (!envConfig.app.urlClient?.trim()) {
|
|
throw new Error(
|
|
"app.urlClient must be set for production (config.json or CLIENT_URL).",
|
|
);
|
|
}
|
|
}
|
|
|
|
return envConfig;
|
|
} catch (err) {
|
|
console.error("Error loading config:", err);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
export function getEnvironment() {
|
|
return NODE_ENV;
|
|
}
|
|
|
|
const config = loadConfig();
|
|
export default config;
|