module util.config; import std.stdio; import slf4d; import asdf; /** * The path of the config file to attempt to load. */ private const CONFIG_FILE = "finnow-api-config.json"; /** * Finnow API configuration struct, which contains properties used to * configure various parts of the API. */ struct AppConfig { /** * The port on which the HTTP server will accept requests. */ ushort port; /** * The address at which the corresponding Finnow website is available to * clients. In development, this will be another localhost address, but in * deployed environments, it'll be the actual website with a legitimate * domain name. This is used to supply the Access-Control-Allow-Origin * CORS header, which can help to prevent cross-site-scripting attacks. */ string webOrigin; /** * The logging level to use globally in the application. See SLF4D for more: * https://andrewlalis.github.io/slf4d/guide/using-slf4d.html#logging-levels */ string logLevel; } Level getConfiguredLoggingLevel(in AppConfig cfg) { try { return parseLoggingLevel(cfg.logLevel); } catch (LoggingException e) { return Levels.INFO; } } AppConfig readConfig() { import std.file : exists, readText; import std.json; import std.conv : to; AppConfig defaultConfig = AppConfig( 8080, "http://localhost:5173", "INFO" ); // Local dev environment if no config is given. if (!exists(CONFIG_FILE)) { const defaultConfigJson = serializeToJson(defaultConfig); infoF!"No config file \"%s\" found. Using defaults: %s."(CONFIG_FILE, defaultConfigJson); return defaultConfig; } JSONValue obj; try { obj = parseJSON(readText(CONFIG_FILE)); } catch (Exception e) { stderr.writefln!"Failed to read config from file %s, using default config as a fallback: %s"( CONFIG_FILE, e.msg ); return defaultConfig; } if ("port" in obj.object) { defaultConfig.port = obj.object["port"].integer.to!ushort; } if ("webOrigin" in obj.object) { defaultConfig.webOrigin = obj.object["webOrigin"].str; } if ("logLevel" in obj.object) { defaultConfig.logLevel = obj.object["logLevel"].str; } return defaultConfig; }