# Config

Source: https://developers.inkdrop.app/modules/config

Used to access all of Inkdrop's configuration details.
This module allows you to get and set configuration settings stored in [`config.json`](https://docs.inkdrop.app/reference/user-data-directory).

Available as `env.config` on the [Environment](https://developers.inkdrop.app/modules/environment) passed to `activate(env)`.

## Getting and setting config settings

```js
// Note that with no value set, `::get` returns the setting's default value.
env.config.get('my-plugin.myKey') // -> 'defaultValue'

env.config.set('my-plugin.myKey', 'value')
env.config.get('my-plugin.myKey') // -> 'value'
```

You may want to watch for changes. Use `::observe` to catch changes to the setting.

```js
env.config.set('my-plugin.myKey', 'value')
env.config.observe('my-plugin.myKey', newValue => {
  // `observe` calls immediately and every time the value is changed
  console.log('My configuration changed:', newValue)
})
```

If you want a notification only when the value changes, use `::onDidChange`.

```js
env.config.onDidChange('my-plugin.myKey', ({ newValue, oldValue }) => {
  console.log('My configuration changed:', newValue, oldValue)
})
```

Alternatively, you can get the config values via the [`localConfig` app state](https://developers.inkdrop.app/states/local-config).

## Value Coercion

Config settings each have a type specified by way of a schema.
For example we might want an integer setting that only allows integers greater than `0`:

```js
// When no value has been set, `::get` returns the setting's default value
env.config.get('my-plugin.anInt') // -> 12

// The string will be coerced to the integer 123
env.config.set('my-plugin.anInt', '123')
env.config.get('my-plugin.anInt') // -> 123

// The string will be coerced to an integer, but it must be greater than 0, so is set to 1
env.config.set('my-plugin.anInt', '-20')
env.config.get('my-plugin.anInt') // -> 1
```

## Defining settings for your plugin

Define a schema under a `config` key in your plugin main.

```js

module.exports = {
  config: {
    someInt: {
      title: 'Some int',
      type: 'integer',
      default: 34,
      minimum: 10
    }
  },

  activate() {
    // ...
```

See [plugin docs](https://developers.inkdrop.app/guides/plugin-word-count) for more info.

## Config Schemas

We use [json schema](http://json-schema.org/) which allows you to define your value's default, the type it should be, etc. A simple example:

```js
{
  config: {
    enableThing: {
      title: 'enable thing',
      type: 'boolean',
      default: false
    },
    thingVolume: {
      title: 'thing volume',
      type: 'integer',
      default: 5,
      minimum: 1,
      maximum: 11
    }
  }
}
```

The type keyword allows for type coercion and validation.
If a `thingVolume` is set to a string `'10'`, it will be coerced into an integer.

### Supported Types

The `type` keyword can be a string with any one of the following.

### string

Values must be a string.

```js
{
  config: {
    someSetting: {
      title: 'some string setting',
      type: 'string',
      default: 'hello'
    }
  }
}
```

### number

Values will be coerced into a number, including real numbers. Supports the (optional) `minimum` and `maximum` keys.

```js
{
  config: {
    someSetting: {
      title: 'some number setting',
      type: 'number',
      default: 5.3,
      minimum: 1.5,
      maximum: 11.5
    }
  }
}
```

### boolean

Values will be coerced into a Boolean.
`'true'` and `'false'` will be coerced.

```js
{
  config: {
    someSetting: {
      title: 'some boolean setting',
      type: 'boolean',
      default: false
    }
  }
}
```

### Other Supported Types

### enum

All types support an `enum` key, which lets you specify all the values the setting can take.
`enum` may be an array of allowed values (of the specified type).

In this example, the setting must be one of the 3 strings:

```js
{
  config: {
    someSetting: {
      title: 'some string setting',
      type: 'string',
      default: 'foo',
      enum: ['foo', 'bar', 'baz']
    }
  }
}
```

### title and description

The settings view will use the `title` and `description` keys to display your config setting in a readable way.
By default the settings view humanizes your config key, so `someSetting` becomes `Some Setting`.
In some cases, this is confusing for users, and a more descriptive title is useful.

Descriptions will be displayed below the title in the settings view.

```js
{
  config: {
    someSetting: {
      title: 'Setting Magnitude',
      description: 'This will affect the blah and the other blah',
      type: 'integer',
      default: 4
    }
  }
}
```

### Manipulating values outside your configuration schema

It is possible to manipulate (`get`, `set`, `observe` etc) values that do not appear in your configuration schema. For example, if the config schema of the plugin 'some-plugin' is

```js
{
  config: {
    someSetting: {
      type: 'boolean',
      default: false
    }
  }
}
```

You can still do the following

```js
let otherSetting = env.config.get('some-plugin.otherSetting')
env.config.set('some-plugin.stillAnotherSetting', otherSetting * 5)
```

In other words, if a function asks for a `key-path`, that path doesn't have to be described in the config schema for the plugin or any plugin.
However, as highlighted in the best practices section, you are advised against doing the above.

## Best practices

- Don't depend on (or write to) configuration keys outside of your keypath.
