All files / config loader.ts

96.29% Statements 26/27
50% Branches 3/6
100% Functions 8/8
96.15% Lines 25/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66                    1x 1x     3x 210x   3x 3x 3x   3x   3x   3x       3x   3x 3x   3x 6x 6x       3x   3x         3x 3x   9x   3x       3x       3x     3x    
import * as yaml from 'js-yaml';
import { readFileSync } from 'fs';
import { resolve } from 'path';
import { plainToInstance } from 'class-transformer';
import { validateSync } from 'class-validator';
import { RootConfig } from './root.config';
import { merge, set } from 'lodash';
 
type RawConfig = { [s: string]: RawConfig | any };
 
const ENV_PREFIX = 'GT_' as const;
const ENV_DELIMITER = '__' as const;
 
function loadEnvironment(env: Record<string, string | undefined>): RawConfig {
  return Object.keys(env)
    .filter(key => key.startsWith(ENV_PREFIX))
    .map(k => {
      const value = env[k];
      const keyWithoutPrefix = k.replace(ENV_PREFIX, '');
      const key = keyWithoutPrefix
        .split(ENV_DELIMITER)
        .map(x => x.toLowerCase())
        .join('.');
      return { key, value };
    })
    .reduce((a, { key, value }) => set(a, key, value), {});
}
 
export default () => {
  const configPaths = ['config.yaml'];
 
  Eif (process.env.LANDSCAPE)
    configPaths.push(`${process.env.LANDSCAPE}.config.yaml`);
 
  const configs = configPaths.map(path => {
    try {
      const content = readFileSync(
        resolve(__dirname, '../../config/app', path),
        'utf8',
      );
      return yaml.load(content) as RawConfig;
    } catch {
      return {};
    }
  });
 
  // Load all environment with GT prefix and merge them into config
  const envConfig = loadEnvironment(process.env ?? {});
  configs.push(envConfig);
 
  const config = configs.reduce((a, b) => merge(a, b), {});
 
  const validatedConfig = plainToInstance(RootConfig, config, {
    enableImplicitConversion: true,
  });
 
  const errors = validateSync(validatedConfig, {
    skipMissingProperties: false,
  });
 
  Iif (errors.length > 0) {
    throw new Error(errors.toString());
  }
  return { ...validatedConfig };
};