UNPKG

11.4 kBMarkdownView Raw
1# conf
2
3> Simple config handling for your app or module
4
5All you have to care about is what to persist. This module will handle all the dull details like where and how.
6
7**It does not support multiple processes writing to the same store.**\
8I initially made this tool to let command-line tools persist some data.
9
10*If you need this for Electron, check out [`electron-store`](https://github.com/sindresorhus/electron-store) instead.*
11
12## Install
13
14```
15$ npm install conf
16```
17
18## Usage
19
20```js
21const Conf = require('conf');
22
23const config = new Conf();
24
25config.set('unicorn', '🦄');
26console.log(config.get('unicorn'));
27//=> '🦄'
28
29// Use dot-notation to access nested properties
30config.set('foo.bar', true);
31console.log(config.get('foo'));
32//=> {bar: true}
33
34config.delete('unicorn');
35console.log(config.get('unicorn'));
36//=> undefined
37```
38
39Or [create a subclass](https://github.com/sindresorhus/electron-store/blob/main/index.js).
40
41## API
42
43Changes are written to disk atomically, so if the process crashes during a write, it will not corrupt the existing config.
44
45### Conf(options?)
46
47Returns a new instance.
48
49### options
50
51Type: `object`
52
53#### defaults
54
55Type: `object`
56
57Default values for the config items.
58
59**Note:** The values in `defaults` will overwrite the `default` key in the `schema` option.
60
61#### schema
62
63Type: `object`
64
65[JSON Schema](https://json-schema.org) to validate your config data.
66
67Under the hood, the JSON Schema validator [ajv](https://github.com/epoberezkin/ajv) is used to validate your config. We use [JSON Schema draft-07](https://json-schema.org/latest/json-schema-validation.html) and support all [validation keywords](https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md) and [formats](https://github.com/epoberezkin/ajv#formats).
68
69You should define your schema as an object where each key is the name of your data's property and each value is a JSON schema used to validate that property. See more [here](https://json-schema.org/understanding-json-schema/reference/object.html#properties).
70
71Example:
72
73```js
74const Conf = require('conf');
75
76const schema = {
77 foo: {
78 type: 'number',
79 maximum: 100,
80 minimum: 1,
81 default: 50
82 },
83 bar: {
84 type: 'string',
85 format: 'url'
86 }
87};
88
89const config = new Conf({schema});
90
91console.log(config.get('foo'));
92//=> 50
93
94config.set('foo', '1');
95// [Error: Config schema violation: `foo` should be number]
96```
97
98**Note:** The `default` value will be overwritten by the `defaults` option if set.
99
100### migrations
101
102Type: `object`
103
104You can use migrations to perform operations to the store whenever a **project version** is upgraded.
105
106The `migrations` object should consist of a key-value pair of `'version': handler`. The `version` can also be a [semver range](https://github.com/npm/node-semver#ranges).
107
108Example:
109
110```js
111const Conf = require('conf');
112
113const store = new Conf({
114 migrations: {
115 '0.0.1': store => {
116 store.set('debugPhase', true);
117 },
118 '1.0.0': store => {
119 store.delete('debugPhase');
120 store.set('phase', '1.0.0');
121 },
122 '1.0.2': store => {
123 store.set('phase', '1.0.2');
124 },
125 '>=2.0.0': store => {
126 store.set('phase', '>=2.0.0');
127 }
128 }
129});
130```
131
132> Note: The version the migrations use refers to the **project version** by default. If you want to change this behavior, specify the [`projectVersion`](#projectVersion) option.
133
134#### configName
135
136Type: `string`\
137Default: `'config'`
138
139Name of the config file (without extension).
140
141Useful if you need multiple config files for your app or module. For example, different config files between two major versions.
142
143#### projectName
144
145Type: `string`\
146Default: The `name` field in the package.json closest to where `conf` is imported.
147
148You only need to specify this if you don't have a package.json file in your project or if it doesn't have a name defined within it.
149
150#### projectVersion
151
152Type: `string`\
153Default: The `version` field in the package.json closest to where `conf` is imported.
154
155You only need to specify this if you don't have a package.json file in your project or if it doesn't have a version defined within it.
156
157#### cwd
158
159Type: `string`\
160Default: System default [user config directory](https://github.com/sindresorhus/env-paths#pathsconfig)
161
162**You most likely don't need this. Please don't use it unless you really have to. By default, it will pick the optimal location by adhering to system conventions. You are very likely to get this wrong and annoy users.**
163
164Overrides `projectName`.
165
166The only use-case I can think of is having the config located in the app directory or on some external storage.
167
168#### encryptionKey
169
170Type: `string | Buffer | TypedArray | DataView`\
171Default: `undefined`
172
173Note that this is **not intended for security purposes**, since the encryption key would be easily found inside a plain-text Node.js app.
174
175Its main use is for obscurity. If a user looks through the config directory and finds the config file, since it's just a JSON file, they may be tempted to modify it. By providing an encryption key, the file will be obfuscated, which should hopefully deter any users from doing so.
176
177When specified, the store will be encrypted using the [`aes-256-cbc`](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation) encryption algorithm.
178
179#### fileExtension
180
181Type: `string`\
182Default: `'json'`
183
184Extension of the config file.
185
186You would usually not need this, but could be useful if you want to interact with a file with a custom file extension that can be associated with your app. These might be simple save/export/preference files that are intended to be shareable or saved outside of the app.
187
188#### clearInvalidConfig
189
190Type: `boolean`\
191Default: `false`
192
193The config is cleared if reading the config file causes a `SyntaxError`. This is a good behavior for unimportant data, as the config file is not intended to be hand-edited, so it usually means the config is corrupt and there's nothing the user can do about it anyway. However, if you let the user edit the config file directly, mistakes might happen and it could be more useful to throw an error when the config is invalid instead of clearing.
194
195#### serialize
196
197Type: `Function`\
198Default: `value => JSON.stringify(value, null, '\t')`
199
200Function to serialize the config object to a UTF-8 string when writing the config file.
201
202You would usually not need this, but it could be useful if you want to use a format other than JSON.
203
204#### deserialize
205
206Type: `Function`\
207Default: `JSON.parse`
208
209Function to deserialize the config object from a UTF-8 string when reading the config file.
210
211You would usually not need this, but it could be useful if you want to use a format other than JSON.
212
213#### projectSuffix
214
215Type: `string`\
216Default: `'nodejs'`
217
218**You most likely don't need this. Please don't use it unless you really have to.**
219
220Suffix appended to `projectName` during config file creation to avoid name conflicts with native apps.
221
222You can pass an empty string to remove the suffix.
223
224For example, on macOS, the config file will be stored in the `~/Library/Preferences/foo-nodejs` directory, where `foo` is the `projectName`.
225
226#### accessPropertiesByDotNotation
227
228Type: `boolean`\
229Default: `true`
230
231Accessing nested properties by dot notation. For example:
232
233```js
234const Conf = require('conf');
235
236const config = new Conf();
237
238config.set({
239 foo: {
240 bar: {
241 foobar: '🦄'
242 }
243 }
244});
245
246console.log(config.get('foo.bar.foobar'));
247//=> '🦄'
248```
249
250Alternatively, you can set this option to `false` so the whole string would be treated as one key.
251
252```js
253const Conf = require('conf');
254
255const config = new Conf({accessPropertiesByDotNotation: false});
256
257config.set({
258 `foo.bar.foobar`: '🦄'
259});
260
261console.log(config.get('foo.bar.foobar'));
262//=> '🦄'
263```
264
265#### watch
266
267type: `boolean`\
268Default: `false`
269
270Watch for any changes in the config file and call the callback for `onDidChange` or `onDidAnyChange` if set. This is useful if there are multiple processes changing the same config file.
271
272### Instance
273
274You can use [dot-notation](https://github.com/sindresorhus/dot-prop) in a `key` to access nested properties.
275
276The instance is [`iterable`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols) so you can use it directly in a [`for…of`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/for...of) loop.
277
278#### .set(key, value)
279
280Set an item.
281
282The `value` must be JSON serializable. Trying to set the type `undefined`, `function`, or `symbol` will result in a TypeError.
283
284#### .set(object)
285
286Set multiple items at once.
287
288#### .get(key, defaultValue?)
289
290Get an item or `defaultValue` if the item does not exist.
291
292#### .reset(...keys)
293
294Reset items to their default values, as defined by the `defaults` or `schema` option.
295
296Use `.clear()` to reset all items.
297
298#### .has(key)
299
300Check if an item exists.
301
302#### .delete(key)
303
304Delete an item.
305
306#### .clear()
307
308Delete all items.
309
310This resets known items to their default values, if defined by the `defaults` or `schema` option.
311
312#### .onDidChange(key, callback)
313
314`callback`: `(newValue, oldValue) => {}`
315
316Watches the given `key`, calling `callback` on any changes.
317
318When a key is first set `oldValue` will be `undefined`, and when a key is deleted `newValue` will be `undefined`.
319
320Returns a function which you can use to unsubscribe:
321
322```js
323const unsubscribe = conf.onDidChange(key, callback);
324
325unsubscribe();
326```
327
328#### .onDidAnyChange(callback)
329
330`callback`: `(newValue, oldValue) => {}`
331
332Watches the whole config object, calling `callback` on any changes.
333
334`oldValue` and `newValue` will be the config object before and after the change, respectively. You must compare `oldValue` to `newValue` to find out what changed.
335
336Returns a function which you can use to unsubscribe:
337
338```js
339const unsubscribe = conf.onDidAnyChange(callback);
340
341unsubscribe();
342```
343
344#### .size
345
346Get the item count.
347
348#### .store
349
350Get all the config as an object or replace the current config with an object:
351
352```js
353conf.store = {
354 hello: 'world'
355};
356```
357
358#### .path
359
360Get the path to the config file.
361
362## FAQ
363
364### How is this different from [`configstore`](https://github.com/yeoman/configstore)?
365
366I'm also the author of `configstore`. While it's pretty good, I did make some mistakes early on that are hard to change at this point. This module is the result of everything I learned from making `configstore`. Mainly where the config is stored. In `configstore`, the config is stored in `~/.config` (which is mainly a Linux convention) on all systems, while `conf` stores config in the system default [user config directory](https://github.com/sindresorhus/env-paths#pathsconfig). The `~/.config` directory, it turns out, often have an incorrect permission on macOS and Windows, which has caused a lot of grief for users.
367
368### Can I use YAML or another serialization format?
369
370The `serialize` and `deserialize` options can be used to customize the format of the config file, as long as the representation is compatible with `utf8` encoding.
371
372Example using YAML:
373
374```js
375const Conf = require('conf');
376const yaml = require('js-yaml');
377
378const config = new Conf({
379 fileExtension: 'yaml',
380 serialize: yaml.safeDump,
381 deserialize: yaml.safeLoad
382});
383```
384
385## Related
386
387- [electron-store](https://github.com/sindresorhus/electron-store) - Simple data persistence for your Electron app or module
388- [cache-conf](https://github.com/SamVerschueren/cache-conf) - Simple cache config handling for your app or module