diff options
Diffstat (limited to 'services/docker/mail-server/relay/config.ts')
-rw-r--r-- | services/docker/mail-server/relay/config.ts | 89 |
1 files changed, 45 insertions, 44 deletions
diff --git a/services/docker/mail-server/relay/config.ts b/services/docker/mail-server/relay/config.ts index 55d71fa..d58b163 100644 --- a/services/docker/mail-server/relay/config.ts +++ b/services/docker/mail-server/relay/config.ts @@ -1,97 +1,99 @@ -import { transformProperties } from "./util.ts"; - export const APP_PREFIX = "crupest"; -export const APP_NAME = "mailserver"; +export const APP_NAME = "mail-server"; -interface ConfigItemDef { - env: string; +export interface ConfigItemDefinition { description: string; default?: string; secret?: boolean; } -export const CONFIG_DEFS = { +export const CONFIG_DEFINITIONS = { mailDomain: { - env: "MAIL_DOMAIN", description: "the part after `@` of an address", }, dataPath: { - env: "DATA_PATH", description: "path to save app persistent data", }, ldaPath: { - env: "LDA_PATH", description: "full path of lda executable", "default": "/dovecot/libexec/dovecot/dovecot-lda", }, inboundFallback: { - env: "INBOUND_FALLBACK", - description: "comma separated addresses used as fallback receipts", + description: "comma separated addresses used as fallback recipients", "default": "", }, - awsRegion: { env: "AWS_REGION", description: "aws region" }, - awsAccessKeyId: { env: "AWS_USER", description: "aws access key id" }, - awsSecretAccessKey: { - env: "AWS_PASSWORD", + awsInboundPath: { + description: "(random set) path for aws sns", + }, + awsInboundKey: { + description: "(random set) http header Authorization for aws sns", + }, + awsRegion: { + description: "aws region", + }, + awsUser: { + description: "aws access key id", + }, + awsPassword: { 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>; +} as const satisfies Record<string, ConfigItemDefinition>; -type ConfigDefs = typeof CONFIG_DEFS; -type ConfigKey = keyof ConfigDefs; +type ConfigDefinitions = typeof CONFIG_DEFINITIONS; +type ConfigNames = keyof ConfigDefinitions; type ConfigMap = { - [K in ConfigKey]: ConfigItemDef & { value: string }; + [K in ConfigNames]: ConfigDefinitions[K] & { + readonly env: string; + readonly 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.`, - ); +function resolveConfig(): ConfigMap { + const result: Record<string, ConfigMap[ConfigNames]> = {}; + for (const [name, def] of Object.entries(CONFIG_DEFINITIONS)) { + const env = `${APP_PREFIX}-${APP_NAME}-${ + name.replace(/[A-Z]/g, (m) => "-" + m.toLowerCase()) + }`.replaceAll("-", "_").toUpperCase(); + const value = Deno.env.get(env) ?? (def as ConfigItemDefinition).default; + if (value == null) { + throw new Error(`Required env ${env} (${def.description}) is not set.`); + } + result[name] = { ...def, env, value }; + } + return result as ConfigMap; } export class Config { - #config = transformProperties( - CONFIG_DEFS, - (def) => ({ ...def, value: resolveAppConfigItem(def) }), - ) as ConfigMap; + #config = resolveConfig(); readonly HTTP_HOST = "0.0.0.0"; readonly HTTP_PORT = 2345; readonly SMTP_HOST = "127.0.0.1"; readonly SMTP_PORT = 2346; - get<K extends ConfigKey>(key: K): ConfigMap[K] { + getAllConfig<K extends ConfigNames>(key: K): ConfigMap[K] { return this.#config[key]; } - getValue(key: ConfigKey): string { - return this.get(key).value; + get(key: ConfigNames): string { + return this.getAllConfig(key).value; } - getValueList(key: ConfigKey, separator: string = ","): string[] { - const value = this.getValue(key); + getList(key: ConfigNames, separator: string = ","): string[] { + const value = this.get(key); if (value.length === 0) return []; return value.split(separator); } [Symbol.for("Deno.customInspect")]() { return Object.entries(this.#config).map(([key, item]) => - `${key} [env: ${getFullEnvKey(item.env)}]: ${ - item.secret === true ? "***" : item.value + `${key} [env: ${item.env}]: ${ + (item as ConfigItemDefinition).secret === true ? "***" : item.value }` ).join("\n"); } @@ -99,4 +101,3 @@ export class Config { const config = new Config(); export default config; -export const getConfigValue = config.getValue.bind(config); |