73 lines
2.0 KiB
TypeScript
73 lines
2.0 KiB
TypeScript
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<S extends yup.Maybe<yup.AnyObject>>(
|
|
schema: yup.ObjectSchema<S>,
|
|
base_name: string = ''
|
|
): Promise<Ok<S>> {
|
|
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<S>
|
|
if (type === 'object') {
|
|
value = await object(sub_scheme as yup.ObjectSchema<S>, 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<S>(value: string | string[], scheme: yup.AnySchema<S>): Promise<Ok<S>> {
|
|
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}
|
|
}
|