Files
factorio-clusterio/packages/lib/src/bootstrap.ts
T
Hornwitser 2c52c265cf Require config files to be explicitly created (#1040)
The behaviour of creating the config file if it's missing while
convenient causes confusion and problems when the tools are run
in the wrong folder.  They end up creating a shadow installation
and misdirect the user with nonsensical error messages, instead
pointing to the real problem which is that the tool can't find
the configuration needed to actually run.

Require a config file to be present at startup and refuse to run if this
file is missing.  To support the odd use-case of creating the config
when missing a --create-config flag is added. To conveniently generate
a config file to edit out from the "config create" command is added.
2026-09-15 22:16:54 +02:00

51 lines
1.5 KiB
TypeScript

import fs from "node:fs/promises";
import { logger } from "./logging.js";
import { LockFile } from "./LockFile.js";
import type { Config, ConfigLocation } from "./config/classes.js";
import { StartupError } from "./errors.js";
export async function loadConfigFromArgs<T extends typeof Config<any>>(
args: {
config: string,
bypassLockFile: boolean,
createConfig: boolean,
_: (string | number)[],
},
ConfigClass: T,
location: ConfigLocation,
) {
const configLockPath = `${args.config}.lock`;
if (args.bypassLockFile) {
await fs.unlink(configLockPath).catch(() => {}); // ignore error, file might not exist
}
const isCreateCommand = args._[0] === "config" && args._[1] === "create";
const create = args.createConfig || isCreateCommand;
let config;
const configLock = new LockFile(configLockPath);
const message = `${create ? "Creating" : "Loading"} config at ${args.config}`;
if (location === "control" && !create) {
// Ctl uses a verbose level here to avoid spamming the console.
// A better idea would probably be to set Ctl's default level to warn.
logger.verbose(message);
} else {
logger.info(message);
}
try {
config = await ConfigClass.fromFile(location, args.config);
} catch (err: any) {
if (err.code !== "ENOENT" || !create) {
throw new StartupError(`Failed to load ${args.config}: ${err.stack ?? err.message ?? err}`);
}
config = new ConfigClass(location, undefined, args.config);
await config.save(true);
}
return [config as InstanceType<T>, configLock] as const;
}