Update build scripts, entry points, and packaged-path detection for the new toolchain. Co-authored-by: Cursor <cursoragent@cursor.com>
253 lines
6.4 KiB
JavaScript
253 lines
6.4 KiB
JavaScript
// config.js - Configuration handling
|
|
import fs from "fs";
|
|
import path from "path";
|
|
import { fileURLToPath } from "url";
|
|
import log4js from "log4js";
|
|
import { startWaiting, stopWaiting } from "./spinner.js";
|
|
|
|
// Determine environment
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
const isPackaged =
|
|
__dirname.includes(path.sep + "build" + path.sep) ||
|
|
__dirname.includes(path.sep + "Resources" + path.sep);
|
|
|
|
if (!process.env.NODE_ENV) {
|
|
process.env.NODE_ENV = "production";
|
|
}
|
|
const NODE_ENV = process.env.NODE_ENV;
|
|
|
|
// Configure paths
|
|
function getProductionConfigPath() {
|
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
switch (process.platform) {
|
|
case "win32":
|
|
return path.join(
|
|
process.env.PROGRAMDATA || "C:\\ProgramData",
|
|
"farmcontrol-server",
|
|
"config.json",
|
|
);
|
|
case "darwin":
|
|
return path.join(
|
|
homeDir,
|
|
"Library",
|
|
"Application Support",
|
|
"farmcontrol-server",
|
|
"config.json",
|
|
);
|
|
case "linux":
|
|
default:
|
|
return "/etc/farmcontrol-server/config.json";
|
|
}
|
|
}
|
|
|
|
function getDevelopmentConfigPath() {
|
|
// If we're in a packaged app (asar), we can't write to the app directory.
|
|
// We should use a writable user data directory instead.
|
|
if (isPackaged) {
|
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
switch (process.platform) {
|
|
case "win32":
|
|
return path.join(
|
|
process.env.APPDATA || path.join(homeDir, "AppData", "Roaming"),
|
|
"farmcontrol-server",
|
|
"config.json",
|
|
);
|
|
case "darwin":
|
|
return path.join(
|
|
homeDir,
|
|
"Library",
|
|
"Application Support",
|
|
"farmcontrol-server",
|
|
"config.json",
|
|
);
|
|
default:
|
|
return path.join(
|
|
homeDir,
|
|
".config",
|
|
"farmcontrol-server",
|
|
"config.json",
|
|
);
|
|
}
|
|
}
|
|
return path.resolve(__dirname, "../config.json");
|
|
}
|
|
|
|
const CONFIG_PATH =
|
|
NODE_ENV === "production"
|
|
? getProductionConfigPath()
|
|
: getDevelopmentConfigPath();
|
|
|
|
const logger = log4js.getLogger("Config");
|
|
logger.level = "info";
|
|
|
|
function getDefaultProductionDataDir() {
|
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
switch (process.platform) {
|
|
case "win32":
|
|
return path.join(
|
|
process.env.PROGRAMDATA || "C:\\ProgramData",
|
|
"farmcontrol-server",
|
|
"data",
|
|
);
|
|
case "darwin":
|
|
return path.join(
|
|
homeDir,
|
|
"Library",
|
|
"Application Support",
|
|
"farmcontrol-server",
|
|
"data",
|
|
);
|
|
case "linux":
|
|
default:
|
|
return "/var/lib/farmcontrol-server";
|
|
}
|
|
}
|
|
|
|
function getDefaultDevelopmentDataDir() {
|
|
if (isPackaged) {
|
|
return path.join(path.dirname(getDevelopmentConfigPath()), "data");
|
|
}
|
|
return path.resolve(__dirname, "../data");
|
|
}
|
|
|
|
function resolveDataDir(envConfig) {
|
|
let dataDir = envConfig.dataDir;
|
|
const wasMissing = !dataDir;
|
|
|
|
if (!dataDir) {
|
|
dataDir =
|
|
NODE_ENV === "production"
|
|
? getDefaultProductionDataDir()
|
|
: getDefaultDevelopmentDataDir();
|
|
}
|
|
|
|
dataDir = path.resolve(dataDir);
|
|
|
|
if (!fs.existsSync(dataDir)) {
|
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
logger.info(`Created data directory at ${dataDir}`);
|
|
}
|
|
|
|
return { dataDir, shouldPersist: wasMissing && NODE_ENV === "production" };
|
|
}
|
|
|
|
const DEFAULT_CONFIG = {
|
|
development: {
|
|
logLevel: "debug",
|
|
url: "https://dev-wss.tombutcher.work",
|
|
apiUrl: "https://dev.tombutcher.work/api",
|
|
host: {
|
|
id: "",
|
|
authCode: "",
|
|
},
|
|
},
|
|
production: {
|
|
logLevel: "info",
|
|
url: "https://ws.farmcontrol.app",
|
|
apiUrl: "https://api.farmcontrol.app",
|
|
host: {
|
|
id: "",
|
|
authCode: "",
|
|
},
|
|
},
|
|
};
|
|
|
|
// Load config file
|
|
export function loadConfig() {
|
|
try {
|
|
if (!fs.existsSync(CONFIG_PATH)) {
|
|
logger.info(
|
|
`Configuration file not found at ${CONFIG_PATH}. Creating a new one.`,
|
|
);
|
|
const configDir = path.dirname(CONFIG_PATH);
|
|
if (!fs.existsSync(configDir)) {
|
|
fs.mkdirSync(configDir, { recursive: true });
|
|
}
|
|
fs.writeFileSync(
|
|
CONFIG_PATH,
|
|
JSON.stringify(DEFAULT_CONFIG, null, 2),
|
|
"utf8",
|
|
);
|
|
}
|
|
|
|
const configData = fs.readFileSync(CONFIG_PATH, "utf8");
|
|
const config = JSON.parse(configData);
|
|
|
|
if (!config[NODE_ENV]) {
|
|
throw new Error(
|
|
`Configuration for environment '${NODE_ENV}' not found in config.json`,
|
|
);
|
|
}
|
|
|
|
const { dataDir, shouldPersist } = resolveDataDir(config[NODE_ENV]);
|
|
config[NODE_ENV] = { ...config[NODE_ENV], dataDir };
|
|
|
|
if (shouldPersist) {
|
|
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), "utf8");
|
|
logger.info(`Set data directory to ${dataDir} in config`);
|
|
}
|
|
|
|
return config[NODE_ENV];
|
|
} catch (err) {
|
|
logger.error("Error loading config:", err);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
// Save config file
|
|
export async function saveConfig(newConfig) {
|
|
startWaiting("Saving...", logger);
|
|
try {
|
|
let config = {};
|
|
if (fs.existsSync(CONFIG_PATH)) {
|
|
const configData = fs.readFileSync(CONFIG_PATH, "utf8");
|
|
config = JSON.parse(configData);
|
|
} else {
|
|
const configDir = path.dirname(CONFIG_PATH);
|
|
if (!fs.existsSync(configDir)) {
|
|
fs.mkdirSync(configDir, { recursive: true });
|
|
}
|
|
}
|
|
|
|
// Update current environment
|
|
config[NODE_ENV] = newConfig;
|
|
|
|
// Write back to file with 2-space indentation
|
|
fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), "utf8");
|
|
await stopWaiting();
|
|
logger.info(`Configuration for '${NODE_ENV}' saved successfully.`);
|
|
} catch (err) {
|
|
await stopWaiting();
|
|
logger.error("Error saving config:", err);
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
// Get current environment
|
|
export function getEnvironment() {
|
|
return NODE_ENV;
|
|
}
|
|
|
|
// Get the path to the active config.json file
|
|
export function getConfigPath() {
|
|
return CONFIG_PATH;
|
|
}
|
|
|
|
// Get the configured data directory, optionally with subpaths
|
|
export function getDataDir(...subpaths) {
|
|
const config = loadConfig();
|
|
return subpaths.length > 0
|
|
? path.join(config.dataDir, ...subpaths)
|
|
: config.dataDir;
|
|
}
|
|
|
|
// Ensure a subdirectory exists within the data directory
|
|
export function ensureDataDir(...subpaths) {
|
|
const dir = getDataDir(...subpaths);
|
|
if (!fs.existsSync(dir)) {
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
}
|
|
return dir;
|
|
}
|