import * as yup from 'yup' import logger from 'log' import {read_env} from './env' import type {Ok} from './helpers' const log = logger('config:parsing') export async function object>( schema: yup.ObjectSchema, base_name: string = '' ): Promise> { log.debug('Object') if (base_name.length !== 0) base_name = base_name + '_' // @ts-expect-error Ugly hack with type S const data: S = {} for (const key in schema.fields) { const sub_key = base_name + key.toUpperCase() const sub_scheme = schema.fields[key] as yup.AnySchema const type = sub_scheme.describe().type log.debug(`Parse ${sub_key} with type ${type}`) // If it is an object, do not try to read from env let value: Ok if (type === 'object') { value = await object(sub_scheme as yup.ObjectSchema, sub_key) if (!value.ok) return value } else { // For all other types, read value from env const raw = await read_env(sub_key) if (!raw.ok) return raw // if undef : might have a default, might be opt, might be missing if (raw.data === undefined) { const def = sub_scheme.getDefault() if (def !== undefined) value = {ok: true, data: def} else if (sub_scheme.spec.optional) continue else { log.warn('Missing value for', key) return {} } } else { // Normal handling of value (for arrays, split by ',') const less_raw = type === 'array' ? (raw.data.length === 0 ? [] : raw.data.split(',')) : raw.data value = await generic(less_raw, sub_scheme) if (!value.ok) return value } } data[key] = value.data } return {ok: true, data} } export async function generic(value: string | string[], scheme: yup.AnySchema): Promise> { log.debug('Generic', scheme.describe().type) if (!(await scheme.isValid(value))) { log.warn('Invalid value') log.debug('Value:', value) return {} } const res = scheme.cast(value) return {ok: true, data: res} }