import type * as pg from "npm:pg"; import { strToBool } from "../utils/convert.ts"; import { BadConfigErr } from "../utils/errors.ts"; import { readJsonFileSync } from "../utils/io.ts"; import * as path from "jsr:@std/path"; export const POSTGRES_PASSWORD = "POSTGRES_PASSWORD" export const MIC_APPLY_MIGRATIONS = "MIC_APPLY_MIGRATIONS" export const DEFAULT_CONFIG_FILE_PATH = import.meta.dirname ? path.join(import.meta.dirname, '../config.json') : '/app/config.json' export const MIC_DROP_DB = "MIC_DROP_DB" export const BOT_TOKEN = "BOT_TOKEN" export const MIC_CONFIG_PATH = "MIC_CONFIG_PATH" export enum BotMode{ setup, normal } export type BotConfig = { mode: BotMode, bot_token: string, chat_id: number, admin_ids: number[], } export interface EnvConfig { db_password?: string, bot_token?: string, mic_config_path?: string, mic_apply_migrations: boolean, mic_drop_db: boolean, } export interface FileConfig { db_user?: string, db_name?: string, db_port?: number, db_host?: string, db_tls?: boolean, db_password_file?: string, bot_token?: string, } export interface Config { db_user?: string, db_name?: string, db_port?: number, db_host?: string, db_tls?: boolean, db_password: string, bot_token: string, config_path: string, apply_migrations: boolean, drop_db: boolean, } export interface MigrationConfig { dropDb: boolean applyMigrations: boolean migrationsPath: string } export interface CompiledConfig { pgPoolCfg: pg.PoolConfig botCfg: BotConfig migrationCfg?: MigrationConfig } export const getEnvConfig = (): EnvConfig => { const apply_migrations = strToBool(Deno.env.get(MIC_APPLY_MIGRATIONS) || "n") || false if (apply_migrations) Deno.env.set(MIC_APPLY_MIGRATIONS, "n") const drop_db = strToBool(Deno.env.get(MIC_DROP_DB) || "n") || false if (drop_db) Deno.env.set(MIC_DROP_DB, "n") return { db_password: Deno.env.get(POSTGRES_PASSWORD), bot_token: Deno.env.get(BOT_TOKEN), mic_config_path: Deno.env.get(MIC_CONFIG_PATH), mic_apply_migrations: apply_migrations, mic_drop_db: drop_db, } } export const getConfig = (): Config => { const envCfg = getEnvConfig() const config_path = envCfg.mic_config_path || DEFAULT_CONFIG_FILE_PATH const fileCfg = readJsonFileSync(config_path) let db_password: string; if (fileCfg.db_password_file) { const decoder = new TextDecoder("utf-8") const data = Deno.readFileSync(fileCfg.db_password_file) db_password = decoder.decode(data).toString() if (db_password[db_password.length - 1] === '\n') { db_password = db_password.slice(0, -1) } } else if (envCfg.db_password) { db_password = envCfg.db_password } else throw new BadConfigErr( "Expected db_password_file to be set in the config "+ "or the POSTGRES_PASSWORD environment variable, "+ "but bot both are undefined. "+ "Check the Config section in README.md" ) const bot_token: string | undefined = envCfg.bot_token || fileCfg.bot_token if (!bot_token) throw new BadConfigErr( "Expected bot_token to be set in the config "+ "or at the BOT_TOKEN environment variable, "+ "but bot token is undefined. "+ "Check the Config section in README.md" ) return { db_host: fileCfg.db_host, db_user: fileCfg.db_user, db_name: fileCfg.db_name, db_port: fileCfg.db_port, db_tls: fileCfg.db_tls, db_password, config_path, apply_migrations: envCfg.mic_apply_migrations, drop_db: envCfg.mic_drop_db, bot_token, } }