{
  "version": 3,
  "sources": ["../../../src/config.ts"],
  "sourcesContent": ["//\n// Copyright 2021 DXOS.org\n//\n\nimport defaultsDeep from 'lodash.defaultsdeep';\nimport isMatch from 'lodash.ismatch';\n\nimport { InvalidConfigError } from '@dxos/protocols';\nimport { schema } from '@dxos/protocols/proto';\nimport { type Config as ConfigProto } from '@dxos/protocols/proto/dxos/config';\nimport { trace } from '@dxos/tracing';\nimport { getDeep, setDeep } from '@dxos/util';\n\nimport { type ConfigKey, type DeepIndex, type ParseKey } from './types';\n\ntype MappingSpec = Record<string, { path: string; type?: string }>;\nconst configRootType = schema.getCodecForType('dxos.config.Config');\n\n/**\n * Maps the given objects onto a flattened set of (key x values).\n * Expects parsed yaml content of the form:\n *\n * ```\n * ENV_VAR:\n *   path: config.selector.path\n * ```\n *\n * @param {object} spec\n * @param {object} values\n * @return {object}\n */\nexport const mapFromKeyValues = (spec: MappingSpec, values: Record<string, any>) => {\n  const config = {};\n\n  for (const [key, { path, type }] of Object.entries(spec)) {\n    let value = values[key];\n    if (value !== undefined) {\n      if (type) {\n        switch (type) {\n          case 'boolean': {\n            value = String(value).toLowerCase() === 'true' || value === '1';\n            break;\n          }\n\n          case 'number': {\n            value = Number(value);\n            break;\n          }\n\n          case 'string': {\n            break;\n          }\n\n          case 'json': {\n            value = value ? JSON.parse(value) : null;\n            break;\n          }\n\n          default: {\n            throw new Error(`Invalid type: ${type}`);\n          }\n        }\n      }\n\n      setDeep(config, path.split('.'), value);\n    }\n  }\n\n  return config;\n};\n\n/**\n * Maps the given flattend set of (key x values) onto a JSON object.\n * @param {object} spec\n * @param {object} values\n */\nexport const mapToKeyValues = (spec: MappingSpec, values: any) => {\n  const config: Record<string, any> = {};\n\n  for (const [key, { path, type }] of Object.entries(spec)) {\n    const value = getDeep(values, path.split('.'));\n    if (value !== undefined) {\n      switch (type) {\n        case 'json':\n          config[key] = JSON.stringify(value);\n          break;\n        default:\n          config[key] = value;\n      }\n    }\n  }\n\n  return config;\n};\n\n/**\n * Validate config object.\n */\nexport const validateConfig = (config: ConfigProto): ConfigProto => {\n  if (!('version' in config)) {\n    throw new InvalidConfigError({ message: 'Version not specified' });\n  }\n\n  if (config?.version !== 1) {\n    throw new InvalidConfigError({ message: `Invalid config version: ${config.version}` });\n  }\n\n  const error = configRootType.protoType.verify(config);\n  if (error) {\n    throw new InvalidConfigError({ message: String(error) });\n  }\n\n  return config;\n};\n\nexport const ConfigResource = Symbol.for('dxos.resource.Config');\n\n/**\n * Global configuration object.\n * NOTE: Config objects are immutable.\n */\n@trace.resource({ annotation: ConfigResource })\nexport class Config {\n  private readonly _config: any;\n\n  /**\n   * Creates an immutable instance.\n   * @constructor\n   */\n  constructor(config: ConfigProto = {}, ...objects: ConfigProto[]) {\n    this._config = validateConfig(defaultsDeep(config, ...objects, { version: 1 }));\n  }\n\n  /**\n   * Returns an immutable config JSON object.\n   */\n  get values(): ConfigProto {\n    return this._config;\n  }\n\n  /**\n   * Returns the given config property.\n   *\n   * @param key A key in the config object. Can be a nested property with keys separated by dots: 'services.signal.server'.\n   * @param defaultValue Default value to return if option is not present in the config.\n   * @returns The config value or undefined if the option is not present.\n   */\n  get<K extends ConfigKey>(\n    key: K,\n    defaultValue?: DeepIndex<ConfigProto, ParseKey<K>>,\n  ): DeepIndex<ConfigProto, ParseKey<K>> | undefined {\n    return getDeep(this._config, key.split('.')) ?? defaultValue;\n  }\n\n  /**\n   * Get unique key.\n   */\n  find<T = any>(path: string, test: object): T | undefined {\n    const values = getDeep(this._config, path.split('.'));\n    if (!Array.isArray(values)) {\n      return;\n    }\n\n    return values.find((value) => isMatch(value, test));\n  }\n\n  /**\n   * Returns the given config property or throw if it doesn't exist.\n   *\n   * @param key A key in the config object. Can be a nested property with keys separated by dots: 'services.signal.server'.\n   */\n  getOrThrow<K extends ConfigKey>(key: K): Exclude<DeepIndex<ConfigProto, ParseKey<K>>, undefined> {\n    const value: DeepIndex<ConfigProto, ParseKey<K>> | undefined = getDeep(this._config, key.split('.'));\n    if (!value) {\n      throw new Error(`Config option not present: ${key}`);\n    }\n    return value;\n  }\n}\n"],
  "mappings": "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",
  "names": ["defaultsDeep", "isMatch", "InvalidConfigError", "schema", "trace", "getDeep", "setDeep", "configRootType", "getCodecForType", "mapFromKeyValues", "spec", "values", "config", "key", "path", "type", "Object", "entries", "value", "undefined", "String", "toLowerCase", "Number", "JSON", "parse", "Error", "split", "mapToKeyValues", "stringify", "validateConfig", "message", "version", "error", "protoType", "verify", "ConfigResource", "Symbol", "for", "Config", "_config", "objects", "get", "defaultValue", "find", "test", "Array", "isArray", "getOrThrow", "resource", "annotation"]
}
