1 2
import InvalidJsonBodyError from '../errors/invalid-json-body-error'
2 2
import { constantCase } from 'change-case'
3 2
import { create as createLogger } from '../common/log'
4 2
import { Config as ConfigSchemaTyping } from '../schemas/Config'
5 2
const log = createLogger('config')
6 2
const schema = require('../schemas/Config.json')
7
const {
8
  extractDefaultsFromSchema
9 2
} = require('../lib/utils')
10 2
import Ajv = require('ajv')
11

12 2
const ajv = new Ajv()
13

14 2
const ENV_PREFIX = 'CONNECTOR_'
15

16 2
const BOOLEAN_VALUES = {
17
  '1': true,
18
  'true': true,
19
  '0': false,
20
  'false': false,
21
  '': false
22
}
23

24 2
export default class Config extends ConfigSchemaTyping {
25
  // TODO: These fields are already all defined in the config schema, however
26
  //   they are defined as optional and as a result, TypeScript thinks that they
27
  //   may not be set. However, when we construct a new Config instance, we load
28
  //   the defaults from the schema, so these *will* always be set. These
29
  //   declarations make TypeScript happy.
30
  public store!: string
31
  public quoteExpiry!: number
32
  public routeExpiry!: number
33
  public minMessageWindow!: number
34
  public maxHoldTime!: number
35
  public routeBroadcastInterval!: number
36

37
  protected _validate: Ajv.ValidateFunction
38
  protected _validateAccount: Ajv.ValidateFunction
39

40
  constructor () {
41 2
    super()
42

43 2
    this.loadDefaults()
44

45 2
    this._validate = ajv.compile(schema)
46 2
    this._validateAccount = ajv.compile(schema.properties.accounts.additionalProperties)
47
  }
48

49
  loadDefaults () {
50 2
    Object.assign(this, extractDefaultsFromSchema(schema))
51
  }
52

53
  loadFromEnv (env?: NodeJS.ProcessEnv) {
54 2
    if (!env) {
55 2
      env = process.env
56
    }
57

58
    // Copy all env vars starting with ENV_PREFIX into a set so we can check off
59
    // the ones we recognize and warn the user about any we don't recognize.
60 2
    const unrecognizedEnvKeys = new Set(
61 2
      Object.keys(env).filter(key => key.startsWith(ENV_PREFIX))
62
    )
63

64 2
    const config = {}
65 2
    for (let key of Object.keys(schema.properties)) {
66 2
      const envKey = ENV_PREFIX + constantCase(key)
67 2
      const envValue = env[envKey]
68

69 2
      unrecognizedEnvKeys.delete(envKey)
70

71 2
      if (typeof envValue === 'string') {
72 2
        switch (schema.properties[key].type) {
73 2
          case 'string':
74 2
            config[key] = envValue
75 2
            break
76
          case 'object':
77
          case 'array':
78 2
            try {
79 2
              config[key] = JSON.parse(envValue)
80
            } catch (err) {
81 0
              log.error('unable to parse config. key=%s', envKey)
82
            }
83 2
            break
84
          case 'boolean':
85 2
            config[key] = BOOLEAN_VALUES[envValue] || false
86 0
            break
87
          case 'integer':
88
          case 'number':
89 2
            config[key] = Number(envValue)
90 2
            break
91
          default:
92 0
            throw new TypeError('Unknown JSON schema type: ' + schema.properties[key].type)
93
        }
94
      }
95
    }
96

97 2
    for (const key of unrecognizedEnvKeys) {
98 2
      log.warn('unrecognized environment variable. key=%s', key)
99
    }
100

101 2
    this.validate(config)
102

103 2
    Object.assign(this, config)
104
  }
105

106
  loadFromOpts (opts: object) {
107 0
    this.validate(opts)
108

109 0
    Object.assign(this, opts)
110
  }
111

112
  validate (config: object) {
113 2
    if (!this._validate(config)) {
114 2
      const firstError = this._validate.errors && this._validate.errors[0]
115 2
        ? this._validate.errors[0]
116
        : { message: 'unknown validation error', dataPath: '' }
117 2
      throw new InvalidJsonBodyError('config failed to validate. error=' + firstError.message + ' dataPath=' + firstError.dataPath, this._validate.errors || [])
118
    }
119
  }
120

121
  validateAccount (id: string, accountInfo: any) {
122 2
    if (!this._validateAccount(accountInfo)) {
123 2
      throw new InvalidJsonBodyError('account config failed to validate. id=' + id, this._validateAccount.errors || [])
124
    }
125
  }
126

127
  get (key: string) {
128 2
    return this[key]
129
  }
130
}

Read our documentation on viewing source code .

Loading