UNPKG

18.4 kBMarkdownView Raw
1# cosmiconfig
2
3[![Build Status](https://img.shields.io/travis/davidtheclark/cosmiconfig/master.svg?label=unix%20build)](https://travis-ci.org/davidtheclark/cosmiconfig) [![Build status](https://img.shields.io/appveyor/ci/davidtheclark/cosmiconfig/master.svg?label=windows%20build)](https://ci.appveyor.com/project/davidtheclark/cosmiconfig/branch/master)
4[![codecov](https://codecov.io/gh/davidtheclark/cosmiconfig/branch/master/graph/badge.svg)](https://codecov.io/gh/davidtheclark/cosmiconfig)
5
6Cosmiconfig searches for and loads configuration for your program.
7
8It features smart defaults based on conventional expectations in the JavaScript ecosystem.
9But it's also flexible enough to search wherever you'd like to search, and load whatever you'd like to load.
10
11By default, Cosmiconfig will start where you tell it to start and search up the directory tree for the following:
12
13- a `package.json` property
14- a JSON or YAML, extensionless "rc file"
15- an "rc file" with the extensions `.json`, `.yaml`, `.yml`, or `.js`.
16- a `.config.js` CommonJS module
17
18For example, if your module's name is "soursocks", cosmiconfig will search up the directory tree for configuration in the following places:
19
20- a `soursocks` property in `package.json`
21- a `.soursocksrc` file in JSON or YAML format
22- a `.soursocksrc.json` file
23- a `.soursocksrc.yaml`, `.soursocksrc.yml`, or `.soursocksrc.js` file
24- a `soursocks.config.js` file exporting a JS object
25
26Cosmiconfig continues to search up the directory tree, checking each of these places in each directory, until it finds some acceptable configuration (or hits the home directory).
27
28👀 **Looking for the v4 docs?**
29v5 involves significant revisions to Cosmiconfig's API, allowing for much greater flexibility and clarifying some things.
30If you have trouble switching from v4 to v5, please file an issue.
31If you are still using v4, those v4 docs are available [in the `4.0.0` tag](https://github.com/davidtheclark/cosmiconfig/tree/4.0.0).
32
33## Table of contents
34
35- [Installation](#installation)
36- [Usage](#usage)
37- [Result](#result)
38- [cosmiconfig()](#cosmiconfig-1)
39 - [moduleName](#modulename)
40- [explorer.search()](#explorersearch)
41 - [searchFrom](#searchfrom)
42- [explorer.searchSync()](#explorersearchsync)
43- [explorer.load()](#explorerload)
44- [explorer.loadSync()](#explorerloadsync)
45- [explorer.clearLoadCache()](#explorerclearloadcache)
46- [explorer.clearSearchCache()](#explorerclearsearchcache)
47- [explorer.clearCaches()](#explorerclearcaches)
48- [cosmiconfigOptions](#cosmiconfigoptions)
49 - [searchPlaces](#searchplaces)
50 - [loaders](#loaders)
51 - [packageProp](#packageprop)
52 - [stopDir](#stopdir)
53 - [cache](#cache)
54 - [transform](#transform)
55 - [ignoreEmptySearchPlaces](#ignoreemptysearchplaces)
56- [Caching](#caching)
57- [Differences from rc](#differences-from-rc)
58- [Contributing & Development](#contributing--development)
59
60## Installation
61
62```
63npm install cosmiconfig
64```
65
66Tested in Node 4+.
67
68## Usage
69
70Create a Cosmiconfig explorer, then either `search` for or directly `load` a configuration file.
71
72```js
73const cosmiconfig = require('cosmiconfig');
74// ...
75const explorer = cosmiconfig(moduleName);
76
77// Search for a configuration by walking up directories.
78// See documentation for search, below.
79explorer.search()
80 .then((result) => {
81 // result.config is the parsed configuration object.
82 // result.filepath is the path to the config file that was found.
83 // result.isEmpty is true if there was nothing to parse in the config file.
84 })
85 .catch((error) => {
86 // Do something constructive.
87 });
88
89// Load a configuration directly when you know where it should be.
90// The result object is the same as for search.
91// See documentation for load, below.
92explorer.load(pathToConfig).then(..);
93
94// You can also search and load synchronously.
95const searchedFor = explorer.searchSync();
96const loaded = explorer.loadSync(pathToConfig);
97```
98
99## Result
100
101The result object you get from `search` or `load` has the following properties:
102
103- **config:** The parsed configuration object. `undefined` if the file is empty.
104- **filepath:** The path to the configuration file that was found.
105- **isEmpty:** `true` if the configuration file is empty. This property will not be present if the configuration file is not empty.
106
107## cosmiconfig()
108
109```js
110const explorer = cosmiconfig(moduleName[, cosmiconfigOptions])
111```
112
113Creates a cosmiconfig instance ("explorer") configured according to the arguments, and initializes its caches.
114
115### moduleName
116
117Type: `string`. **Required.**
118
119Your module name. This is used to create the default [`searchPlaces`] and [`packageProp`].
120
121**[`cosmiconfigOptions`] are documented below.**
122You may not need them, and should first read about the functions you'll use.
123
124## explorer.search()
125
126```js
127explorer.search([searchFrom]).then(result => {..})
128```
129
130Searches for a configuration file. Returns a Promise that resolves with a [result] or with `null`, if no configuration file is found.
131
132You can do the same thing synchronously with [`searchSync()`].
133
134Let's say your module name is `goldengrahams` so you initialized with `const explorer = cosmiconfig('goldengrahams');`.
135Here's how your default [`search()`] will work:
136
137- Starting from `process.cwd()` (or some other directory defined by the `searchFrom` argument to [`search()`]), look for configuration objects in the following places:
138 1. A `goldengrahams` property in a `package.json` file.
139 2. A `.goldengrahamsrc` file with JSON or YAML syntax.
140 3. A `.goldengrahamsrc.json` file.
141 4. A `.goldengrahamsrc.yaml`, `.goldengrahamsrc.yml`, or `.goldengrahamsrc.js` file.
142 5. A `goldengrahams.config.js` JS file exporting the object.
143- If none of those searches reveal a configuration object, move up one directory level and try again.
144 So the search continues in `./`, `../`, `../../`, `../../../`, etc., checking the same places in each directory.
145- Continue searching until arriving at your home directory (or some other directory defined by the cosmiconfig option [`stopDir`]).
146- If at any point a parseable configuration is found, the [`search()`] Promise resolves with its [result] \(or, with [`searchSync()`], the [result] is returned).
147- If no configuration object is found, the [`search()`] Promise resolves with `null` (or, with [`searchSync()`], `null` is returned).
148- If a configuration object is found *but is malformed* (causing a parsing error), the [`search()`] Promise rejects with that error (so you should `.catch()` it). (Or, with [`searchSync()`], the error is thrown.)
149
150**If you know exactly where your configuration file should be, you can use [`load()`], instead.**
151
152**The search process is highly customizable.**
153Use the cosmiconfig options [`searchPlaces`] and [`loaders`] to precisely define where you want to look for configurations and how you want to load them.
154
155### searchFrom
156
157Type: `string`.
158Default: `process.cwd()`.
159
160A filename.
161[`search()`] will start its search here.
162
163If the value is a directory, that's where the search starts.
164If it's a file, the search starts in that file's directory.
165
166## explorer.searchSync()
167
168```js
169const result = explorer.searchSync([searchFrom]);
170```
171
172Synchronous version of [`search()`].
173
174Returns a [result] or `null`.
175
176## explorer.load()
177
178```js
179explorer.load(loadPath).then(result => {..})
180```
181
182Loads a configuration file. Returns a Promise that resolves with a [result] or rejects with an error (if the file does not exist or cannot be loaded).
183
184Use `load` if you already know where the configuration file is and you just need to load it.
185
186```js
187explorer.load('load/this/file.json'); // Tries to load load/this/file.json.
188```
189
190If you load a `package.json` file, the result will be derived from whatever property is specified as your [`packageProp`].
191
192## explorer.loadSync()
193
194```js
195const result = explorer.loadSync(loadPath);
196```
197
198Synchronous version of [`load()`].
199
200Returns a [result].
201
202## explorer.clearLoadCache()
203
204Clears the cache used in [`load()`].
205
206## explorer.clearSearchCache()
207
208Clears the cache used in [`search()`].
209
210## explorer.clearCaches()
211
212Performs both [`clearLoadCache()`] and [`clearSearchCache()`].
213
214## cosmiconfigOptions
215
216Type: `Object`.
217
218Possible options are documented below.
219
220### searchPlaces
221
222Type: `Array<string>`.
223Default: See below.
224
225An array of places that [`search()`] will check in each directory as it moves up the directory tree.
226Each place is relative to the directory being searched, and the places are checked in the specified order.
227
228**Default `searchPlaces`:**
229
230```js
231[
232 'package.json',
233 `.${moduleName}rc`,
234 `.${moduleName}rc.json`,
235 `.${moduleName}rc.yaml`,
236 `.${moduleName}rc.yml`,
237 `.${moduleName}rc.js`,
238 `${moduleName}.config.js`,
239]
240```
241
242Create your own array to search more, fewer, or altogether different places.
243
244Every item in `searchPlaces` needs to have a loader in [`loaders`] that corresponds to its extension.
245(Common extensions are covered by default loaders.)
246Read more about [`loaders`] below.
247
248`package.json` is a special value: When it is included in `searchPlaces`, Cosmiconfig will always parse it as JSON and load a property within it, not the whole file.
249That property is defined with the [`packageProp`] option, and defaults to your module name.
250
251Examples, with a module named `porgy`:
252
253```js
254// Disallow extensions on rc files:
255[
256 'package.json',
257 '.porgyrc',
258 'porgy.config.js'
259]
260
261// ESLint searches for configuration in these places:
262[
263 '.eslintrc.js',
264 '.eslintrc.yaml',
265 '.eslintrc.yml',
266 '.eslintrc.json',
267 '.eslintrc',
268 'package.json'
269]
270
271// Babel looks in fewer places:
272[
273 'package.json',
274 '.babelrc'
275]
276
277// Maybe you want to look for a wide variety of JS flavors:
278[
279 'porgy.config.js',
280 'porgy.config.mjs',
281 'porgy.config.ts',
282 'porgy.config.coffee'
283]
284// ^^ You will need to designate custom loaders to tell
285// Cosmiconfig how to handle these special JS flavors.
286
287// Look within a .config/ subdirectory of every searched directory:
288[
289 'package.json',
290 '.porgyrc',
291 '.config/.porgyrc',
292 '.porgyrc.json',
293 '.config/.porgyrc.json'
294]
295```
296
297### loaders
298
299Type: `Object`.
300Default: See below.
301
302An object that maps extensions to the loader functions responsible for loading and parsing files with those extensions.
303
304Cosmiconfig exposes its default loaders for `.js`, `.json`, and `.yaml` as `cosmiconfig.loadJs`, `cosmiconfig.loadJson`, and `cosmiconfig.loadYaml`, respectively.
305
306**Default `loaders`:**
307
308```js
309{
310 '.json': cosmiconfig.loadJson,
311 '.yaml': cosmiconfig.loadYaml,
312 '.yml': cosmiconfig.loadYaml,
313 '.js': cosmiconfig.loadJs,
314 noExt: cosmiconfig.loadYaml
315}
316```
317
318(YAML is a superset of JSON; which means YAML parsers can parse JSON; which is how extensionless files can be either YAML *or* JSON with only one parser.)
319
320**If you provide a `loaders` object, your object will be *merged* with the defaults.**
321So you can override one or two without having to override them all.
322
323**Keys in `loaders`** are extensions (starting with a period), or `noExt` to specify the loader for files *without* extensions, like `.soursocksrc`.
324
325**Values in `loaders`** are either a loader function (described below) or an object with `sync` and/or `async` properties, whose values are loader functions.
326
327**The most common use case for custom loaders value is to load extensionless `rc` files as strict JSON**, instead of JSON *or* YAML (the default).
328To accomplish that, provide the following `loaders` value:
329
330```js
331{
332 noExt: cosmiconfig.loadJson
333}
334```
335
336If you want to load files that are not handled by the loader functions Cosmiconfig exposes, you can write a custom loader function or use one from NPM if it exists.
337
338**Third-party loaders:**
339
340- [@endemolshinegroup/cosmiconfig-typescript-loader](https://github.com/EndemolShineGroup/cosmiconfig-typescript-loader)
341
342**Use cases for custom loader function:**
343
344- Allow configuration syntaxes that aren't handled by Cosmiconfig's defaults, like JSON5, INI, or XML.
345- Allow ES2015 modules from `.mjs` configuration files.
346- Parse JS files with Babel before deriving the configuration.
347
348**Custom loader functions** have the following signature:
349
350```js
351// Sync
352(filepath: string, content: string) => Object | null
353
354// Async
355(filepath: string, content: string) => Object | null | Promise<Object | null>
356```
357
358Cosmiconfig reads the file when it checks whether the file exists, so it will provide you with both the file's path and its content.
359Do whatever you need to, and return either a configuration object or `null` (or, for async-only loaders, a Promise that resolves with one of those).
360`null` indicates that no real configuration was found and the search should continue.
361
362It's easiest if you make your custom loader function synchronous.
363Then it can be used regardless of whether you end up calling [`search()`] or [`searchSync()`], [`load()`] or [`loadSync()`].
364If you want or need to provide an async-only loader, you can do so by making the value of `loaders` an object with an `async` property whose value is the async loader.
365You can also add a `sync` property to designate a sync loader, if you want to use both async and sync search and load functions.
366
367A few things to note:
368
369- If you use a custom loader, be aware of whether it's sync or async and how that aligned with your usage of sync or async search and load functions.
370- **Special JS syntax can also be handled by using a `require` hook**, because `cosmiconfig.loadJs` just uses `require`.
371 Whether you use custom loaders or a `require` hook is up to you.
372
373Examples:
374
375```js
376// Allow JSON5 syntax:
377{
378 '.json': json5Loader
379}
380
381// Allow XML, and treat sync and async separately:
382{
383 '.xml': { async: asyncXmlLoader, sync: syncXmlLoader }
384}
385
386// Allow a special configuration syntax of your own creation:
387{
388 '.special': specialLoader
389}
390
391// Allow many flavors of JS, using custom loaders:
392{
393 '.mjs': esmLoader,
394 '.ts': typeScriptLoader,
395 '.coffee': coffeeScriptLoader
396}
397
398// Allow many flavors of JS but rely on require hooks:
399{
400 '.mjs': cosmiconfig.loadJs,
401 '.ts': cosmiconfig.loadJs,
402 '.coffee': cosmiconfig.loadJs
403}
404```
405
406### packageProp
407
408Type: `string | Array<string>`.
409Default: `` `${moduleName}` ``.
410
411Name of the property in `package.json` to look for.
412
413Use a period-delimited string or an array of strings to describe a path to nested properties.
414
415For example, the value `'configs.myPackage'` or `['configs', 'myPackage']` will get you the `"myPackage"` value in a `package.json` like this:
416
417```json
418{
419 "configs": {
420 "myPackage": {..}
421 }
422}
423```
424
425If nested property names within the path include periods, you need to use an array of strings. For example, the value `['configs', 'foo.bar', 'baz']` will get you the `"baz"` value in a `package.json` like this:
426
427```json
428{
429 "configs": {
430 "foo.bar": {
431 "baz": {..}
432 }
433 }
434}
435```
436
437If a string includes period but corresponds to a top-level property name, it will not be interpreted as a period-delimited path. For example, the value `'one.two'` will get you the `"three"` value in a `package.json` like this:
438
439```json
440{
441 "one.two": "three",
442 "one": {
443 "two": "four"
444 }
445}
446```
447
448### stopDir
449
450Type: `string`.
451Default: Absolute path to your home directory.
452
453Directory where the search will stop.
454
455### cache
456
457Type: `boolean`.
458Default: `true`.
459
460If `false`, no caches will be used.
461Read more about ["Caching"](#caching) below.
462
463### transform
464
465Type: `(Result) => Promise<Result> | Result`.
466
467A function that transforms the parsed configuration. Receives the [result].
468
469If using [`search()`] or [`load()`] \(which are async), the transform function can return the transformed result or return a Promise that resolves with the transformed result.
470If using [`searchSync()`] or [`loadSync()`], the function must be synchronous and return the transformed result.
471
472The reason you might use this option — instead of simply applying your transform function some other way — is that *the transformed result will be cached*. If your transformation involves additional filesystem I/O or other potentially slow processing, you can use this option to avoid repeating those steps every time a given configuration is searched or loaded.
473
474### ignoreEmptySearchPlaces
475
476Type: `boolean`.
477Default: `true`.
478
479By default, if [`search()`] encounters an empty file (containing nothing but whitespace) in one of the [`searchPlaces`], it will ignore the empty file and move on.
480If you'd like to load empty configuration files, instead, set this option to `false`.
481
482Why might you want to load empty configuration files?
483If you want to throw an error, or if an empty configuration file means something to your program.
484
485## Caching
486
487As of v2, cosmiconfig uses caching to reduce the need for repetitious reading of the filesystem or expensive transforms. Every new cosmiconfig instance (created with `cosmiconfig()`) has its own caches.
488
489To avoid or work around caching, you can do the following:
490
491- Set the `cosmiconfig` option [`cache`] to `false`.
492- Use the cache-clearing methods [`clearLoadCache()`], [`clearSearchCache()`], and [`clearCaches()`].
493- Create separate instances of cosmiconfig (separate "explorers").
494
495## Differences from [rc](https://github.com/dominictarr/rc)
496
497[rc](https://github.com/dominictarr/rc) serves its focused purpose well. cosmiconfig differs in a few key ways — making it more useful for some projects, less useful for others:
498
499- Looks for configuration in some different places: in a `package.json` property, an rc file, a `.config.js` file, and rc files with extensions.
500- Built-in support for JSON, YAML, and CommonJS formats.
501- Stops at the first configuration found, instead of finding all that can be found up the directory tree and merging them automatically.
502- Options.
503- Asynchronous by default (though can be run synchronously).
504
505## Contributing & Development
506
507Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
508
509And please do participate!
510
511[result]: #result
512
513[`load()`]: #explorerload
514
515[`loadsync()`]: #explorerloadsync
516
517[`search()`]: #explorersearch
518
519[`searchsync()`]: #explorersearchsync
520
521[`clearloadcache()`]: #explorerclearloadcache
522
523[`clearsearchcache()`]: #explorerclearsearchcache
524
525[`clearcaches()`]: #explorerclearcaches
526
527[`packageprop`]: #packageprop
528
529[`cache`]: #cache
530
531[`stopdir`]: #stopdir
532
533[`searchplaces`]: #searchplaces
534
535[`loaders`]: #loaders
536
537[`cosmiconfigoptions`]: #cosmiconfigoptions