import { promises as fs } from 'fs'; import { join as path_join } from 'path'; import { parse as parse_yaml } from 'yaml'; import { deep_merge } from './utilities/deep-merge'; import { OIDCConfig, validate_oidc_conf } from './security/openid-connect'; import { PKCECookieConfig, validate_pkce_cookie_conf } from './security/pkce-cookie'; import { SnowflakeConfig, validate_snowflake_conf } from './utilities/snowflake-uid'; import { StorageConfig } from './storage/config'; import { LoggingConfig, validate_logging_conf } from './logger'; import { Argon2HashConfig } from './security/argon-hash'; import { SessionCookieConfig, validate_session_cookie_conf } from './security/session'; import { HttpConfig } from './http/server'; import { ColorThemeConfig } from './utilities/color-themes'; const conf_dir = process.env.CONF_PATH; if (! conf_dir) { console.error('No CONF_PATH defined'); process.exit(1); } export const app_name = 'My Cool App'; export const app_version = '1.0.0-alpha.0'; export interface Conf { http_web: HttpConfig; http_meta: HttpConfig; logging: LoggingConfig; oidc: OIDCConfig; pkce_cookie: PKCECookieConfig; session_cookie: SessionCookieConfig; snowflake_uid: SnowflakeConfig; storage: StorageConfig; argon2: Argon2HashConfig; color_themes: ColorThemeConfig; } export async function load_conf() : Promise { const conf = Object.create(null); const files = await fs.readdir(conf_dir, { recursive: true }); // Sort configuration files by file name for consistent load order (users should // number prefix their config file names) files.sort((a, b) => a.localeCompare(b)); // Load each config file in order, parse as YAML, and merge the contents into the // results object for (const file of files) { const conf_yaml = await fs.readFile(path_join(conf_dir, file), 'utf8'); const conf_parsed = parse_yaml(conf_yaml); deep_merge(conf, conf_parsed); } return conf; } export function validate_conf(conf: unknown) : asserts conf is Conf { if (typeof conf !== 'object' || ! conf) { throw new Error('`conf` is not an object'); } if ('logging' in conf) { validate_logging_conf(conf.logging); } else { throw new Error('`conf.logging` is missing'); } if ('oidc' in conf) { validate_oidc_conf(conf.oidc) } else { throw new Error('`conf.oidc` is missing'); } if ('pkce_cookie' in conf) { validate_pkce_cookie_conf(conf.pkce_cookie); } else { throw new Error('`conf.pkce_cookie` is missing'); } if ('snowflake_uid' in conf) { validate_snowflake_conf(conf.snowflake_uid); } else { throw new Error('`conf.snowflake_uid` is missing'); } if ('session_cookie' in conf) { validate_session_cookie_conf(conf.session_cookie); } else { throw new Error('`conf.session_cookie` is missing'); } }