2022-10-11 23:49:36 -05:00
|
|
|
import {
|
|
|
|
type LevelName,
|
|
|
|
LogLevels,
|
|
|
|
} from "https://deno.land/std@0.159.0/log/mod.ts";
|
2022-10-11 12:20:25 -05:00
|
|
|
|
2022-11-09 16:55:27 -06:00
|
|
|
export interface LogConfig {
|
|
|
|
consoleLevelName: LevelName;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface PostgresConfig {
|
|
|
|
url: string;
|
2022-11-10 10:25:35 -06:00
|
|
|
poolSize: number;
|
2022-11-09 16:55:27 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
export interface MailgunConfig {
|
|
|
|
apiKey?: string;
|
|
|
|
domain?: string;
|
|
|
|
}
|
|
|
|
|
2022-10-07 23:22:35 -05:00
|
|
|
export interface Config {
|
2022-11-09 16:55:27 -06:00
|
|
|
log: LogConfig;
|
|
|
|
postgres: PostgresConfig;
|
|
|
|
mailgun: MailgunConfig;
|
|
|
|
isDevelopmentMode: boolean;
|
2022-10-07 23:22:35 -05:00
|
|
|
}
|
2022-10-07 21:55:20 -05:00
|
|
|
|
2022-11-09 16:55:27 -06:00
|
|
|
function truthyEnv(key: string): boolean {
|
|
|
|
return (Deno.env.get(key) || "").toString().toLowerCase().trim() in
|
|
|
|
["true", "1"];
|
2022-10-07 23:22:35 -05:00
|
|
|
}
|
2022-10-07 21:55:20 -05:00
|
|
|
|
2022-11-10 10:25:35 -06:00
|
|
|
function toLogLevelName(s: string): LevelName | undefined {
|
|
|
|
if (s in LogLevels) {
|
|
|
|
return s as LevelName;
|
|
|
|
} else {
|
|
|
|
return undefined;
|
|
|
|
}
|
2022-10-11 23:49:36 -05:00
|
|
|
}
|
|
|
|
|
2022-11-09 16:55:27 -06:00
|
|
|
export let config: Readonly<Config>;
|
|
|
|
|
|
|
|
type Logger = { warning: (s: string, ...opts: unknown[]) => void };
|
|
|
|
|
|
|
|
export function setAll(newConfig: Config) {
|
|
|
|
config = newConfig;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function reload(): [
|
|
|
|
Config,
|
|
|
|
((logger: Logger) => void)[],
|
|
|
|
] {
|
|
|
|
// since we want configuration to be setup before any logging, lets save logs here until the logger is setup
|
2022-11-10 10:25:35 -06:00
|
|
|
const logCalls: ((logger: Logger) => void)[] = [];
|
2022-11-09 16:55:27 -06:00
|
|
|
|
|
|
|
const envOrWarn = (key: string, fallback: string): string => {
|
|
|
|
const val = Deno.env.get(key);
|
|
|
|
if (!val) {
|
|
|
|
logCalls.push((logger: Logger) =>
|
|
|
|
logger.warning(`${key} is not set! Using fallback: ${fallback}`)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return val || fallback;
|
|
|
|
};
|
|
|
|
|
2022-11-10 10:25:35 -06:00
|
|
|
const envToIntOrWarn = (key: string, fallback: number): number => {
|
|
|
|
const ev = envOrWarn(key, fallback.toString());
|
|
|
|
let result = parseInt(ev);
|
|
|
|
if (isNaN(result)) {
|
|
|
|
logCalls.push((logger: Logger) =>
|
|
|
|
logger.warning(
|
|
|
|
`Specified ${key} '${ev}' is not a valid integer. Falling back to ${fallback}.`,
|
|
|
|
)
|
|
|
|
);
|
|
|
|
result = fallback;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
};
|
2022-11-09 16:55:27 -06:00
|
|
|
|
2022-11-10 10:25:35 -06:00
|
|
|
const envToEnumOrWarn = <T extends { toString(self: T): string }>(
|
|
|
|
key: string,
|
|
|
|
converter: (s: string) => T | undefined,
|
|
|
|
fallback: T,
|
|
|
|
): T => {
|
|
|
|
const ev = envOrWarn(key, `${fallback}`);
|
|
|
|
const result = converter(ev);
|
|
|
|
if (result) {
|
|
|
|
return result;
|
|
|
|
} else {
|
|
|
|
logCalls.push((logger: Logger) =>
|
|
|
|
logger.warning(
|
|
|
|
`Specified ${key} '${ev}' is invalid. Falling back to ${fallback}`,
|
|
|
|
)
|
|
|
|
);
|
|
|
|
return fallback;
|
|
|
|
}
|
|
|
|
};
|
2022-11-09 16:55:27 -06:00
|
|
|
|
|
|
|
const config: Config = {
|
|
|
|
log: {
|
2022-11-10 10:25:35 -06:00
|
|
|
consoleLevelName: envToEnumOrWarn("LOG_LEVEL", toLogLevelName, "INFO"),
|
2022-11-09 16:55:27 -06:00
|
|
|
},
|
|
|
|
postgres: {
|
|
|
|
url: envOrWarn(
|
|
|
|
"POSTGRES_URL",
|
|
|
|
"postgresql://postgres:@127.0.0.1:5432/lyricscreen",
|
|
|
|
),
|
2022-11-10 10:25:35 -06:00
|
|
|
poolSize: envToIntOrWarn("POSTGRES_POOL_SIZE", 3),
|
2022-11-09 16:55:27 -06:00
|
|
|
},
|
|
|
|
mailgun: {},
|
|
|
|
isDevelopmentMode: truthyEnv("DEVELOPMENT_MODE"),
|
|
|
|
};
|
|
|
|
|
|
|
|
return [config, logCalls];
|
|
|
|
}
|