diff options
Diffstat (limited to 'services/docker/mail-server/relay/config.ts')
-rw-r--r-- | services/docker/mail-server/relay/config.ts | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/services/docker/mail-server/relay/config.ts b/services/docker/mail-server/relay/config.ts new file mode 100644 index 0000000..77c6e6e --- /dev/null +++ b/services/docker/mail-server/relay/config.ts @@ -0,0 +1,78 @@ +import { createSingleton, transformProperties } from "./util.ts"; + +export const APP_PREFIX = "crupest"; +export const APP_NAME = "mailserver"; + +interface ConfigItemDef { + env: string; + description: string; + default?: string; + secret?: boolean; +} + +export const CONFIG_DEFS = { + mailDomain: { + env: "MAIL_DOMAIN", + description: "the part after `@` of an address", + }, + dataPath: { + env: "DATA_PATH", + description: "path to save app persistent data", + }, + awsAccessKeyId: { env: "AWS_USER", description: "aws access key id" }, + awsSecretAccessKey: { + env: "AWS_PASSWORD", + description: "aws secret access key", + secret: true, + }, + awsMailBucket: { + env: "AWS_MAIL_BUCKET", + description: "aws s3 bucket saving raw mails", + secret: true, + }, +} as const satisfies Record<string, ConfigItemDef>; + +type ConfigDefs = typeof CONFIG_DEFS; +type ConfigKey = keyof ConfigDefs; +type ConfigMap = { + [K in ConfigKey]: ConfigItemDef & { value: string }; +}; + +function getFullEnvKey(key: string): string { + return `${APP_PREFIX.toUpperCase()}_${APP_NAME.toUpperCase()}_${key}`; +} + +function resolveAppConfigItem(def: ConfigItemDef): string { + const envKey = getFullEnvKey(def.env); + const value = Deno.env.get(envKey); + if (value != null) return value; + if (def.default != null) return def.default; + throw new Error( + `Required env ${envKey} (${def.description}) is not set.`, + ); +} + +export class Config { + #config = transformProperties( + CONFIG_DEFS, + (def) => ({ ...def, value: resolveAppConfigItem(def) }), + ) as ConfigMap; + + get<K extends ConfigKey>(key: K): ConfigMap[K] { + return this.#config[key]; + } + + getValue(key: ConfigKey): string { + return this.get(key).value; + } + + [Symbol.for("Deno.customInspect")]() { + return Object.entries(this.#config).map(([key, item]) => + `${key} [env: ${getFullEnvKey(item.env)}]: ${ + item.secret === true ? "***" : item.value + }` + ).join("\n"); + } +} + +export const [getConfig, setConfig] = createSingleton<Config>("Config"); |