diff options
Diffstat (limited to 'node_modules/cosmiconfig')
| -rw-r--r-- | node_modules/cosmiconfig/CHANGELOG.md | 133 | ||||
| -rw-r--r-- | node_modules/cosmiconfig/LICENSE | 22 | ||||
| -rw-r--r-- | node_modules/cosmiconfig/README.md | 494 | ||||
| -rw-r--r-- | node_modules/cosmiconfig/dist/cacheWrapper.js | 19 | ||||
| -rw-r--r-- | node_modules/cosmiconfig/dist/createExplorer.js | 318 | ||||
| -rw-r--r-- | node_modules/cosmiconfig/dist/getDirectory.js | 22 | ||||
| -rw-r--r-- | node_modules/cosmiconfig/dist/index.js | 81 | ||||
| -rw-r--r-- | node_modules/cosmiconfig/dist/loaders.js | 29 | ||||
| -rw-r--r-- | node_modules/cosmiconfig/dist/readFile.js | 42 | ||||
| l--------- | node_modules/cosmiconfig/node_modules/.bin/js-yaml | 1 | ||||
| -rw-r--r-- | node_modules/cosmiconfig/package.json | 113 |
11 files changed, 1274 insertions, 0 deletions
diff --git a/node_modules/cosmiconfig/CHANGELOG.md b/node_modules/cosmiconfig/CHANGELOG.md new file mode 100644 index 00000000..297945aa --- /dev/null +++ b/node_modules/cosmiconfig/CHANGELOG.md @@ -0,0 +1,133 @@ +# Changelog + +## 5.0.6 + +- Fixed: Better error message if the end user tries an extension Cosmiconfig is not configured to understand. + +## 5.0.5 + +- Fixed: `load` and `loadSync` work with paths relative to `process.cwd()`. + +## 5.0.4 + +- Fixed: `rc` files with `.js` extensions included in default `searchPlaces`. + +## 5.0.3 + +- Docs: Minor corrections to documentation. *Released to update package documentation on npm*. + +## 5.0.2 + +- Fixed: Allow `searchSync` and `loadSync` to load JS configuration files whose export is a Promise. + +## 5.0.1 + +The API has been completely revamped to increase clarity and enable a very wide range of new usage. **Please read the readme for all the details.** + +While the defaults remain just as useful as before — and you can still pass no options at all — now you can also do all kinds of wild and crazy things. + +- The `loaders` option allows you specify custom functions to derive config objects from files. Your loader functions could parse ES2015 modules or TypeScript, JSON5, even INI or XML. Whatever suits you. +- The `searchPlaces` option allows you to specify exactly where cosmiconfig looks within each directory it searches. +- The combination of `loaders` and `searchPlaces` means that you should be able to load pretty much any kind of configuration file you want, from wherever you want it to look. + +Additionally, the overloaded `load()` function has been split up into several clear and focused functions: + +- `search()` now searches up the directory tree, and `load()` loads a configuration file that you don't need to search for. +- The `sync` option has been replaced with separate synchronous functions: `searchSync()` and `loadSync()`. +- `clearFileCache()` and `clearDirectoryCache()` have been renamed to `clearLoadCache()` and `clearSearchPath()` respectively. + +More details: + +- The default JS loader uses `require`, instead of `require-from-string`. So you *could* use `require` hooks to control the loading of JS files (e.g. pass them through esm or Babel). In most cases it is probably preferable to use a custom loader. +- The options `rc`, `js`, and `rcExtensions` have all been removed. You can accomplish the same and more with `searchPlaces`. +- The default `searchPlaces` include `rc` files with extensions, e.g. `.thingrc.json`, `.thingrc.yaml`, `.thingrc.yml`. This is the equivalent of switching the default value of the old `rcExtensions` option to `true`. +- The option `rcStrictJson` has been removed. To get the same effect, you can specify `noExt: cosmiconfig.loadJson` in your `loaders` object. +- `packageProp` no longer accepts `false`. If you don't want to look in `package.json`, write a `searchPlaces` array that does not include it. +- By default, empty files are ignored by `search()`. The new option `ignoreEmptySearchPlaces` allows you to load them, instead, in case you want to do something with empty files. +- The option `configPath` has been removed. Just pass your filepaths directory to `load()`. +- Removed the `format` option. Formats are now all handled via the file extensions specified in `loaders`. + +(If you're wondering with happened to 5.0.0 ... it was a silly publishing mistake.) + +## 4.0.0 + +- Licensing improvement: updated `parse-json` from `3.0.0` to `4.0.0`(see [sindresorhus/parse-json#12][parse-json-pr-12]). +- Changed: error message format for `JSON` parse errors(see [#101][pr-101]). If you were relying on the format of JSON-parsing error messages, this will be a breaking change for you. +- Changed: set default for `searchPath` as `process.cwd()` in `explorer.load`. + +## 3.1.0 + +- Added: infer format based on filePath + +## 3.0.1 + +- Fixed: memory leak due to bug in `require-from-string`. +- Added: for JSON files, append position to end of error message. + +## 3.0.0 + +- Removed: support for loading config path using the `--config` flag. cosmiconfig will not parse command line arguments. Your application can parse command line arguments and pass them to cosmiconfig. +- Removed: `argv` config option. +- Removed: support for Node versions < 4. +- Added: `sync` option. +- Fixed: Throw a clear error on getting empty config file. +- Fixed: when a `options.configPath` is `package.json`, return the package prop, not the entire JSON file. + +## 2.2.2 + +- Fixed: `options.configPath` and `--config` flag are respected. + +## 2.2.0, 2.2.1 + +- 2.2.0 included a number of improvements but somehow broke stylelint. The changes were reverted in 2.2.1, to be restored later. + +## 2.1.3 + +- Licensing improvement: switched from `json-parse-helpfulerror` to `parse-json`. + +## 2.1.2 + +- Fixed: bug where an `ENOENT` error would be thrown is `searchPath` referenced a non-existent file. +- Fixed: JSON parsing errors in Node v7. + +## 2.1.1 + +- Fixed: swapped `graceful-fs` for regular `fs`, fixing a garbage collection problem. + +## 2.1.0 + +- Added: Node 0.12 support. + +## 2.0.2 + +- Fixed: Node version specified in `package.json`. + +## 2.0.1 + +- Fixed: no more infinite loop in Windows. + +## 2.0.0 + +- Changed: module now creates cosmiconfig instances with `load` methods (see README). +- Added: caching (enabled by the change above). +- Removed: support for Node versions <4. + +## 1.1.0 + +- Add `rcExtensions` option. + +## 1.0.2 + +- Fix handling of `require()`'s within JS module configs. + +## 1.0.1 + +- Switch Promise implementation to pinkie-promise. + +## 1.0.0 + +- Initial release. + +[parse-json-pr-12]: https://github.com/sindresorhus/parse-json/pull/12 + +[pr-101]: https://github.com/davidtheclark/cosmiconfig/pull/101 diff --git a/node_modules/cosmiconfig/LICENSE b/node_modules/cosmiconfig/LICENSE new file mode 100644 index 00000000..6d347c06 --- /dev/null +++ b/node_modules/cosmiconfig/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 David Clark + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/node_modules/cosmiconfig/README.md b/node_modules/cosmiconfig/README.md new file mode 100644 index 00000000..4c133525 --- /dev/null +++ b/node_modules/cosmiconfig/README.md @@ -0,0 +1,494 @@ +# cosmiconfig + +[](https://travis-ci.org/davidtheclark/cosmiconfig) [](https://ci.appveyor.com/project/davidtheclark/cosmiconfig/branch/master) +[](https://codecov.io/gh/davidtheclark/cosmiconfig) + +Cosmiconfig searches for and loads configuration for your program. + +It features smart defaults based on conventional expectations in the JavaScript ecosystem. +But it's also flexible enough to search wherever you'd like to search, and load whatever you'd like to load. + +By default, Cosmiconfig will start where you tell it to start and search up the directory tree for the following: + +- a `package.json` property +- a JSON or YAML, extensionless "rc file" +- an "rc file" with the extensions `.json`, `.yaml`, `.yml`, or `.js`. +- a `.config.js` CommonJS module + +For example, if your module's name is "soursocks", cosmiconfig will search up the directory tree for configuration in the following places: + +- a `soursocks` property in `package.json` +- a `.soursocksrc` file in JSON or YAML format +- a `.soursocksrc.json` file +- a `.soursocksrc.yaml`, `.soursocksrc.yml`, or `.soursocksrc.js` file +- a `soursocks.config.js` file exporting a JS object + +Cosmiconfig 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). + +👀 **Looking for the v4 docs?** +v5 involves significant revisions to Cosmiconfig's API, allowing for much greater flexibility and clarifying some things. +If you have trouble switching from v4 to v5, please file an issue. +If 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). + +## Table of contents + +- [Installation](#installation) +- [Usage](#usage) +- [Result](#result) +- [cosmiconfig()](#cosmiconfig-1) + - [moduleName](#modulename) +- [explorer.search()](#explorersearch) + - [searchFrom](#searchfrom) +- [explorer.searchSync()](#explorersearchsync) +- [explorer.load()](#explorerload) +- [explorer.loadSync()](#explorerloadsync) +- [explorer.clearLoadCache()](#explorerclearloadcache) +- [explorer.clearSearchCache()](#explorerclearsearchcache) +- [explorer.clearCaches()](#explorerclearcaches) +- [cosmiconfigOptions](#cosmiconfigoptions) + - [searchPlaces](#searchplaces) + - [loaders](#loaders) + - [packageProp](#packageprop) + - [stopDir](#stopdir) + - [cache](#cache) + - [transform](#transform) + - [ignoreEmptySearchPlaces](#ignoreemptysearchplaces) +- [Caching](#caching) +- [Differences from rc](#differences-from-rc) +- [Contributing & Development](#contributing--development) + +## Installation + +``` +npm install cosmiconfig +``` + +Tested in Node 4+. + +## Usage + +Create a Cosmiconfig explorer, then either `search` for or directly `load` a configuration file. + +```js +const cosmiconfig = require('cosmiconfig'); +// ... +const explorer = cosmiconfig(moduleName); + +// Search for a configuration by walking up directories. +// See documentation for search, below. +explorer.search() + .then((result) => { + // result.config is the parsed configuration object. + // result.filepath is the path to the config file that was found. + // result.isEmpty is true if there was nothing to parse in the config file. + }) + .catch((error) => { + // Do something constructive. + }); + +// Load a configuration directly when you know where it should be. +// The result object is the same as for search. +// See documentation for load, below. +explorer.load(pathToConfig).then(..); + +// You can also search and load synchronously. +const searchedFor = explorer.searchSync(); +const loaded = explorer.loadSync(pathToConfig); +``` + +## Result + +The result object you get from `search` or `load` has the following properties: + +- **config:** The parsed configuration object. `undefined` if the file is empty. +- **filepath:** The path to the configuration file that was found. +- **isEmpty:** `true` if the configuration file is empty. This property will not be present if the configuration file is not empty. + +## cosmiconfig() + +```js +const explorer = cosmiconfig(moduleName[, cosmiconfigOptions]) +``` + +Creates a cosmiconfig instance ("explorer") configured according to the arguments, and initializes its caches. + +### moduleName + +Type: `string`. **Required.** + +Your module name. This is used to create the default [`searchPlaces`] and [`packageProp`]. + +**[`cosmiconfigOptions`] are documented below.** +You may not need them, and should first read about the functions you'll use. + +## explorer.search() + +```js +explorer.search([searchFrom]).then(result => {..}) +``` + +Searches for a configuration file. Returns a Promise that resolves with a [result] or with `null`, if no configuration file is found. + +You can do the same thing synchronously with [`searchSync()`]. + +Let's say your module name is `goldengrahams` so you initialized with `const explorer = cosmiconfig('goldengrahams');`. +Here's how your default [`search()`] will work: + +- Starting from `process.cwd()` (or some other directory defined by the `searchFrom` argument to [`search()`]), look for configuration objects in the following places: + 1. A `goldengrahams` property in a `package.json` file. + 2. A `.goldengrahamsrc` file with JSON or YAML syntax. + 3. A `.goldengrahamsrc.json` file. + 4. A `.goldengrahamsrc.yaml`, `.goldengrahamsrc.yml`, or `.goldengrahamsrc.js` file. + 5. A `goldengrahams.config.js` JS file exporting the object. +- If none of those searches reveal a configuration object, move up one directory level and try again. + So the search continues in `./`, `../`, `../../`, `../../../`, etc., checking the same places in each directory. +- Continue searching until arriving at your home directory (or some other directory defined by the cosmiconfig option [`stopDir`]). +- If at any point a parseable configuration is found, the [`search()`] Promise resolves with its [result] \(or, with [`searchSync()`], the [result] is returned). +- If no configuration object is found, the [`search()`] Promise resolves with `null` (or, with [`searchSync()`], `null` is returned). +- 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.) + +**If you know exactly where your configuration file should be, you can use [`load()`], instead.** + +**The search process is highly customizable.** +Use the cosmiconfig options [`searchPlaces`] and [`loaders`] to precisely define where you want to look for configurations and how you want to load them. + +### searchFrom + +Type: `string`. +Default: `process.cwd()`. + +A filename. +[`search()`] will start its search here. + +If the value is a directory, that's where the search starts. +If it's a file, the search starts in that file's directory. + +## explorer.searchSync() + +```js +const result = explorer.searchSync([searchFrom]); +``` + +Synchronous version of [`search()`]. + +Returns a [result] or `null`. + +## explorer.load() + +```js +explorer.load(loadPath).then(result => {..}) +``` + +Loads 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). + +Use `load` if you already know where the configuration file is and you just need to load it. + +```js +explorer.load('load/this/file.json'); // Tries to load load/this/file.json. +``` + +If you load a `package.json` file, the result will be derived from whatever property is specified as your [`packageProp`]. + +## explorer.loadSync() + +```js +const result = explorer.loadSync(loadPath); +``` + +Synchronous version of [`load()`]. + +Returns a [result]. + +## explorer.clearLoadCache() + +Clears the cache used in [`load()`]. + +## explorer.clearSearchCache() + +Clears the cache used in [`search()`]. + +## explorer.clearCaches() + +Performs both [`clearLoadCache()`] and [`clearSearchCache()`]. + +## cosmiconfigOptions + +### searchPlaces + +Type: `Array<string>`. +Default: See below. + +An array of places that [`search()`] will check in each directory as it moves up the directory tree. +Each place is relative to the directory being searched, and the places are checked in the specified order. + +**Default `searchPlaces`:** + +```js +[ + 'package.json', + `.${moduleName}rc`, + `.${moduleName}rc.json`, + `.${moduleName}rc.yaml`, + `.${moduleName}rc.yml`, + `.${moduleName}rc.js`, + `${moduleName}.config.js`, +] +``` + +Create your own array to search more, fewer, or altogether different places. + +Every item in `searchPlaces` needs to have a loader in [`loaders`] that corresponds to its extension. +(Common extensions are covered by default loaders.) +Read more about [`loaders`] below. + +`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. +That property is defined with the [`packageProp`] option, and defaults to your module name. + +Examples, with a module named `porgy`: + +```js +// Disallow extensions on rc files: +[ + 'package.json', + '.porgyrc', + 'porgy.config.js' +] + +// ESLint searches for configuration in these places: +[ + '.eslintrc.js', + '.eslintrc.yaml', + '.eslintrc.yml', + '.eslintrc.json', + '.eslintrc', + 'package.json' +] + +// Babel looks in fewer places: +[ + 'package.json', + '.babelrc' +] + +// Maybe you want to look for a wide variety of JS flavors: +[ + 'porgy.config.js', + 'porgy.config.mjs', + 'porgy.config.ts', + 'porgy.config.coffee' +] +// ^^ You will need to designate custom loaders to tell +// Cosmiconfig how to handle these special JS flavors. + +// Look within a .config/ subdirectory of every searched directory: +[ + 'package.json', + '.porgyrc', + '.config/.porgyrc', + '.porgyrc.json', + '.config/.porgyrc.json' +] +``` + +### loaders + +Type: `Object`. +Default: See below. + +An object that maps extensions to the loader functions responsible for loading and parsing files with those extensions. + +Cosmiconfig exposes its default loaders for `.js`, `.json`, and `.yaml` as `cosmiconfig.loadJs`, `cosmiconfig.loadJson`, and `cosmiconfig.loadYaml`, respectively. + +**Default `loaders`:** + +```js +{ + '.json': cosmiconfig.loadJson, + '.yaml': cosmiconfig.loadYaml, + '.yml': cosmiconfig.loadYaml, + '.js': cosmiconfig.loadJs, + noExt: cosmiconfig.loadYaml +} +``` + +(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.) + +**If you provide a `loaders` object, your object will be *merged* with the defaults.** +So you can override one or two without having to override them all. + +**Keys in `loaders`** are extensions (starting with a period), or `noExt` to specify the loader for files *without* extensions, like `.soursocksrc`. + +**Values in `loaders`** are either a loader function (described below) or an object with `sync` and/or `async` properties, whose values are loader functions. + +**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). +To accomplish that, provide the following `loaders` value: + +```js +{ + noExt: cosmiconfig.loadJson +} +``` + +If you want to load files that are not handled by the loader functions Cosmiconfig exposes, you can write a custom loader function. + +**Use cases for custom loader function:** + +- Allow configuration syntaxes that aren't handled by Cosmiconfig's defaults, like JSON5, INI, or XML. +- Allow ES2015 modules from `.mjs` configuration files. +- Parse JS files with Babel before deriving the configuration. + +**Custom loader functions** have the following signature: + +```js +// Sync +(filepath: string, content: string) => Object | null + +// Async +(filepath: string, content: string) => Object | null | Promise<Object | null> +``` + +Cosmiconfig reads the file when it checks whether the file exists, so it will provide you with both the file's path and its content. +Do 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). +`null` indicates that no real configuration was found and the search should continue. + +It's easiest if you make your custom loader function synchronous. +Then it can be used regardless of whether you end up calling [`search()`] or [`searchSync()`], [`load()`] or [`loadSync()`]. +If 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. +You can also add a `sync` property to designate a sync loader, if you want to use both async and sync search and load functions. + +A few things to note: + +- 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. +- **Special JS syntax can also be handled by using a `require` hook**, because `cosmiconfig.loadJs` just uses `require`. + Whether you use custom loaders or a `require` hook is up to you. + +Examples: + +```js +// Allow JSON5 syntax: +{ + '.json': json5Loader +} + +// Allow XML, and treat sync and async separately: +{ + '.xml': { async: asyncXmlLoader, sync: syncXmlLoader } +} + +// Allow a special configuration syntax of your own creation: +{ + '.special': specialLoader +} + +// Allow many flavors of JS, using custom loaders: +{ + '.mjs': esmLoader, + '.ts': typeScriptLoader, + '.coffee': coffeeScriptLoader +} + +// Allow many flavors of JS but rely on require hooks: +{ + '.mjs': cosmiconfig.loadJs, + '.ts': cosmiconfig.loadJs, + '.coffee': cosmiconfig.loadJs +} +``` + +### packageProp + +Type: `string`. +Default: `` `${moduleName}` ``. + +Name of the property in `package.json` to look for. + +### stopDir + +Type: `string`. +Default: Absolute path to your home directory. + +Directory where the search will stop. + +### cache + +Type: `boolean`. +Default: `true`. + +If `false`, no caches will be used. +Read more about ["Caching"](#caching) below. + +### transform + +Type: `(Result) => Promise<Result> | Result`. + +A function that transforms the parsed configuration. Receives the [result]. + +If 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. +If using [`searchSync()`] or [`loadSync()`], the function must be synchronous and return the transformed result. + +The 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. + +### ignoreEmptySearchPlaces + +Type: `boolean`. +Default: `true`. + +By 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. +If you'd like to load empty configuration files, instead, set this option to `false`. + +Why might you want to load empty configuration files? +If you want to throw an error, or if an empty configuration file means something to your program. + +## Caching + +As 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. + +To avoid or work around caching, you can do the following: + +- Set the `cosmiconfig` option [`cache`] to `false`. +- Use the cache-clearing methods [`clearLoadCache()`], [`clearSearchCache()`], and [`clearCaches()`]. +- Create separate instances of cosmiconfig (separate "explorers"). + +## Differences from [rc](https://github.com/dominictarr/rc) + +[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: + +- Looks for configuration in some different places: in a `package.json` property, an rc file, a `.config.js` file, and rc files with extensions. +- Built-in support for JSON, YAML, and CommonJS formats. +- Stops at the first configuration found, instead of finding all that can be found up the directory tree and merging them automatically. +- Options. +- Asynchronous by default (though can be run synchronously). + +## Contributing & Development + +Please 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. + +And please do participate! + +[result]: #result + +[`load()`]: #explorerload + +[`loadsync()`]: #explorerloadsync + +[`search()`]: #explorersearch + +[`searchsync()`]: #explorersearchsync + +[`clearloadcache()`]: #explorerclearloadcache + +[`clearsearchcache()`]: #explorerclearsearchcache + +[`clearcaches()`]: #explorerclearcaches + +[`packageprop`]: #packageprop + +[`cache`]: #cache + +[`stopdir`]: #stopdir + +[`searchplaces`]: #searchplaces + +[`loaders`]: #loaders + +[`cosmiconfigoptions`]: #cosmiconfigoptions diff --git a/node_modules/cosmiconfig/dist/cacheWrapper.js b/node_modules/cosmiconfig/dist/cacheWrapper.js new file mode 100644 index 00000000..38c4fcb2 --- /dev/null +++ b/node_modules/cosmiconfig/dist/cacheWrapper.js @@ -0,0 +1,19 @@ +// +'use strict'; + +function cacheWrapper (cache , key , fn ) { + if (!cache) { + return fn(); + } + + const cached = cache.get(key); + if (cached !== undefined) { + return cached; + } + + const result = fn(); + cache.set(key, result); + return result; +} + +module.exports = cacheWrapper; diff --git a/node_modules/cosmiconfig/dist/createExplorer.js b/node_modules/cosmiconfig/dist/createExplorer.js new file mode 100644 index 00000000..2cca5e7c --- /dev/null +++ b/node_modules/cosmiconfig/dist/createExplorer.js @@ -0,0 +1,318 @@ +// +'use strict'; + +const path = require('path'); +const loaders = require('./loaders'); +const readFile = require('./readFile'); +const cacheWrapper = require('./cacheWrapper'); +const getDirectory = require('./getDirectory'); + +const MODE_SYNC = 'sync'; + +// An object value represents a config object. +// null represents that the loader did not find anything relevant. +// undefined represents that the loader found something relevant +// but it was empty. + + +class Explorer { + + + + + + + constructor(options ) { + this.loadCache = options.cache ? new Map() : null; + this.loadSyncCache = options.cache ? new Map() : null; + this.searchCache = options.cache ? new Map() : null; + this.searchSyncCache = options.cache ? new Map() : null; + this.config = options; + this.validateConfig(); + } + + clearLoadCache() { + if (this.loadCache) { + this.loadCache.clear(); + } + if (this.loadSyncCache) { + this.loadSyncCache.clear(); + } + } + + clearSearchCache() { + if (this.searchCache) { + this.searchCache.clear(); + } + if (this.searchSyncCache) { + this.searchSyncCache.clear(); + } + } + + clearCaches() { + this.clearLoadCache(); + this.clearSearchCache(); + } + + validateConfig() { + const config = this.config; + + config.searchPlaces.forEach(place => { + const loaderKey = path.extname(place) || 'noExt'; + const loader = config.loaders[loaderKey]; + if (!loader) { + throw new Error( + `No loader specified for ${getExtensionDescription( + place + )}, so searchPlaces item "${place}" is invalid` + ); + } + }); + } + + search(searchFrom ) { + searchFrom = searchFrom || process.cwd(); + return getDirectory(searchFrom).then(dir => { + return this.searchFromDirectory(dir); + }); + } + + searchFromDirectory(dir ) { + const absoluteDir = path.resolve(process.cwd(), dir); + const run = () => { + return this.searchDirectory(absoluteDir).then(result => { + const nextDir = this.nextDirectoryToSearch(absoluteDir, result); + if (nextDir) { + return this.searchFromDirectory(nextDir); + } + return this.config.transform(result); + }); + }; + + if (this.searchCache) { + return cacheWrapper(this.searchCache, absoluteDir, run); + } + return run(); + } + + searchSync(searchFrom ) { + searchFrom = searchFrom || process.cwd(); + const dir = getDirectory.sync(searchFrom); + return this.searchFromDirectorySync(dir); + } + + searchFromDirectorySync(dir ) { + const absoluteDir = path.resolve(process.cwd(), dir); + const run = () => { + const result = this.searchDirectorySync(absoluteDir); + const nextDir = this.nextDirectoryToSearch(absoluteDir, result); + if (nextDir) { + return this.searchFromDirectorySync(nextDir); + } + return this.config.transform(result); + }; + + if (this.searchSyncCache) { + return cacheWrapper(this.searchSyncCache, absoluteDir, run); + } + return run(); + } + + searchDirectory(dir ) { + return this.config.searchPlaces.reduce((prevResultPromise, place) => { + return prevResultPromise.then(prevResult => { + if (this.shouldSearchStopWithResult(prevResult)) { + return prevResult; + } + return this.loadSearchPlace(dir, place); + }); + }, Promise.resolve(null)); + } + + searchDirectorySync(dir ) { + let result = null; + for (const place of this.config.searchPlaces) { + result = this.loadSearchPlaceSync(dir, place); + if (this.shouldSearchStopWithResult(result)) break; + } + return result; + } + + shouldSearchStopWithResult(result ) { + if (result === null) return false; + if (result.isEmpty && this.config.ignoreEmptySearchPlaces) return false; + return true; + } + + loadSearchPlace(dir , place ) { + const filepath = path.join(dir, place); + return readFile(filepath).then(content => { + return this.createCosmiconfigResult(filepath, content); + }); + } + + loadSearchPlaceSync(dir , place ) { + const filepath = path.join(dir, place); + const content = readFile.sync(filepath); + return this.createCosmiconfigResultSync(filepath, content); + } + + nextDirectoryToSearch( + currentDir , + currentResult + ) { + if (this.shouldSearchStopWithResult(currentResult)) { + return null; + } + const nextDir = nextDirUp(currentDir); + if (nextDir === currentDir || currentDir === this.config.stopDir) { + return null; + } + return nextDir; + } + + loadPackageProp(filepath , content ) { + const parsedContent = loaders.loadJson(filepath, content); + const packagePropValue = parsedContent[this.config.packageProp]; + return packagePropValue || null; + } + + getLoaderEntryForFile(filepath ) { + if (path.basename(filepath) === 'package.json') { + const loader = this.loadPackageProp.bind(this); + return { sync: loader, async: loader }; + } + + const loaderKey = path.extname(filepath) || 'noExt'; + return this.config.loaders[loaderKey] || {}; + } + + getSyncLoaderForFile(filepath ) { + const entry = this.getLoaderEntryForFile(filepath); + if (!entry.sync) { + throw new Error( + `No sync loader specified for ${getExtensionDescription(filepath)}` + ); + } + return entry.sync; + } + + getAsyncLoaderForFile(filepath ) { + const entry = this.getLoaderEntryForFile(filepath); + const loader = entry.async || entry.sync; + if (!loader) { + throw new Error( + `No async loader specified for ${getExtensionDescription(filepath)}` + ); + } + return loader; + } + + loadFileContent( + mode , + filepath , + content + ) { + if (content === null) { + return null; + } + if (content.trim() === '') { + return undefined; + } + const loader = + mode === MODE_SYNC + ? this.getSyncLoaderForFile(filepath) + : this.getAsyncLoaderForFile(filepath); + return loader(filepath, content); + } + + loadedContentToCosmiconfigResult( + filepath , + loadedContent + ) { + if (loadedContent === null) { + return null; + } + if (loadedContent === undefined) { + return { filepath, config: undefined, isEmpty: true }; + } + return { config: loadedContent, filepath }; + } + + createCosmiconfigResult( + filepath , + content + ) { + return Promise.resolve() + .then(() => { + return this.loadFileContent('async', filepath, content); + }) + .then(loaderResult => { + return this.loadedContentToCosmiconfigResult(filepath, loaderResult); + }); + } + + createCosmiconfigResultSync( + filepath , + content + ) { + const loaderResult = this.loadFileContent('sync', filepath, content); + return this.loadedContentToCosmiconfigResult(filepath, loaderResult); + } + + validateFilePath(filepath ) { + if (!filepath) { + throw new Error('load and loadSync must pass a non-empty string'); + } + } + + load(filepath ) { + return Promise.resolve().then(() => { + this.validateFilePath(filepath); + const absoluteFilePath = path.resolve(process.cwd(), filepath); + return cacheWrapper(this.loadCache, absoluteFilePath, () => { + return readFile(absoluteFilePath, { throwNotFound: true }) + .then(content => { + return this.createCosmiconfigResult(absoluteFilePath, content); + }) + .then(this.config.transform); + }); + }); + } + + loadSync(filepath ) { + this.validateFilePath(filepath); + const absoluteFilePath = path.resolve(process.cwd(), filepath); + return cacheWrapper(this.loadSyncCache, absoluteFilePath, () => { + const content = readFile.sync(absoluteFilePath, { throwNotFound: true }); + const result = this.createCosmiconfigResultSync( + absoluteFilePath, + content + ); + return this.config.transform(result); + }); + } +} + +module.exports = function createExplorer(options ) { + const explorer = new Explorer(options); + + return { + search: explorer.search.bind(explorer), + searchSync: explorer.searchSync.bind(explorer), + load: explorer.load.bind(explorer), + loadSync: explorer.loadSync.bind(explorer), + clearLoadCache: explorer.clearLoadCache.bind(explorer), + clearSearchCache: explorer.clearSearchCache.bind(explorer), + clearCaches: explorer.clearCaches.bind(explorer), + }; +}; + +function nextDirUp(dir ) { + return path.dirname(dir); +} + +function getExtensionDescription(filepath ) { + const ext = path.extname(filepath); + return ext ? `extension "${ext}"` : 'files without extensions'; +} diff --git a/node_modules/cosmiconfig/dist/getDirectory.js b/node_modules/cosmiconfig/dist/getDirectory.js new file mode 100644 index 00000000..98b37d63 --- /dev/null +++ b/node_modules/cosmiconfig/dist/getDirectory.js @@ -0,0 +1,22 @@ +// +'use strict'; + +const path = require('path'); +const isDirectory = require('is-directory'); + +function getDirectory(filepath ) { + return new Promise((resolve, reject) => { + return isDirectory(filepath, (err, filepathIsDirectory) => { + if (err) { + return reject(err); + } + return resolve(filepathIsDirectory ? filepath : path.dirname(filepath)); + }); + }); +} + +getDirectory.sync = function getDirectorySync(filepath ) { + return isDirectory.sync(filepath) ? filepath : path.dirname(filepath); +}; + +module.exports = getDirectory; diff --git a/node_modules/cosmiconfig/dist/index.js b/node_modules/cosmiconfig/dist/index.js new file mode 100644 index 00000000..e88224f1 --- /dev/null +++ b/node_modules/cosmiconfig/dist/index.js @@ -0,0 +1,81 @@ +// +'use strict'; + +const os = require('os'); +const createExplorer = require('./createExplorer'); +const loaders = require('./loaders'); + +module.exports = cosmiconfig; + +function cosmiconfig( + moduleName , + options + + + + + + + + +) { + options = options || {}; + const defaults = { + packageProp: moduleName, + searchPlaces: [ + 'package.json', + `.${moduleName}rc`, + `.${moduleName}rc.json`, + `.${moduleName}rc.yaml`, + `.${moduleName}rc.yml`, + `.${moduleName}rc.js`, + `${moduleName}.config.js`, + ], + ignoreEmptySearchPlaces: true, + stopDir: os.homedir(), + cache: true, + transform: identity, + }; + const normalizedOptions = Object.assign( + {}, + defaults, + options, + { + loaders: normalizeLoaders(options.loaders), + } + ); + + return createExplorer(normalizedOptions); +} + +cosmiconfig.loadJs = loaders.loadJs; +cosmiconfig.loadJson = loaders.loadJson; +cosmiconfig.loadYaml = loaders.loadYaml; + +function normalizeLoaders(rawLoaders ) { + const defaults = { + '.js': { sync: loaders.loadJs, async: loaders.loadJs }, + '.json': { sync: loaders.loadJson, async: loaders.loadJson }, + '.yaml': { sync: loaders.loadYaml, async: loaders.loadYaml }, + '.yml': { sync: loaders.loadYaml, async: loaders.loadYaml }, + noExt: { sync: loaders.loadYaml, async: loaders.loadYaml }, + }; + + if (!rawLoaders) { + return defaults; + } + + return Object.keys(rawLoaders).reduce((result, ext) => { + const entry = rawLoaders && rawLoaders[ext]; + if (typeof entry === 'function') { + result[ext] = { sync: entry, async: entry }; + } else { + result[ext] = entry; + } + return result; + }, defaults); +} + +function identity(x) { + return x; +} diff --git a/node_modules/cosmiconfig/dist/loaders.js b/node_modules/cosmiconfig/dist/loaders.js new file mode 100644 index 00000000..e44aaf8c --- /dev/null +++ b/node_modules/cosmiconfig/dist/loaders.js @@ -0,0 +1,29 @@ +// +'use strict'; + +const parseJson = require('parse-json'); +const yaml = require('js-yaml'); + +function loadJs(filepath ) { + const result = require(filepath); + return result; +} + +function loadJson(filepath , content ) { + try { + return parseJson(content); + } catch (err) { + err.message = `JSON Error in ${filepath}:\n${err.message}`; + throw err; + } +} + +function loadYaml(filepath , content ) { + return yaml.safeLoad(content, { filename: filepath }); +} + +module.exports = { + loadJs, + loadJson, + loadYaml, +}; diff --git a/node_modules/cosmiconfig/dist/readFile.js b/node_modules/cosmiconfig/dist/readFile.js new file mode 100644 index 00000000..4fd76cfe --- /dev/null +++ b/node_modules/cosmiconfig/dist/readFile.js @@ -0,0 +1,42 @@ +// +'use strict'; + +const fs = require('fs'); + + + + + +function readFile(filepath , options ) { + options = options || {}; + const throwNotFound = options.throwNotFound || false; + + return new Promise((resolve, reject) => { + fs.readFile(filepath, 'utf8', (err, content) => { + if (err && err.code === 'ENOENT' && !throwNotFound) { + return resolve(null); + } + if (err) return reject(err); + resolve(content); + }); + }); +} + +readFile.sync = function readFileSync( + filepath , + options +) { + options = options || {}; + const throwNotFound = options.throwNotFound || false; + + try { + return fs.readFileSync(filepath, 'utf8'); + } catch (err) { + if (err.code === 'ENOENT' && !throwNotFound) { + return null; + } + throw err; + } +}; + +module.exports = readFile; diff --git a/node_modules/cosmiconfig/node_modules/.bin/js-yaml b/node_modules/cosmiconfig/node_modules/.bin/js-yaml new file mode 120000 index 00000000..daf9f115 --- /dev/null +++ b/node_modules/cosmiconfig/node_modules/.bin/js-yaml @@ -0,0 +1 @@ +../../../js-yaml/bin/js-yaml.js
\ No newline at end of file diff --git a/node_modules/cosmiconfig/package.json b/node_modules/cosmiconfig/package.json new file mode 100644 index 00000000..1b3313f9 --- /dev/null +++ b/node_modules/cosmiconfig/package.json @@ -0,0 +1,113 @@ +{ + "name": "cosmiconfig", + "version": "5.0.6", + "description": "Find and load configuration from a package.json property, rc file, or CommonJS module", + "main": "dist/index.js", + "files": [ + "dist" + ], + "scripts": { + "precommit": "lint-staged && jest && flow check", + "lint:md-partial": "remark -u remark-preset-davidtheclark --frail --quiet --no-stdout --output --", + "lint:md": "npm run lint:md-partial -- *.md", + "lint:fix": "eslint . --fix", + "lint": "eslint . && npm run lint:md", + "format": "prettier --write \"{src/*.js,test/*.js}\"", + "pretest": "npm run lint && flow check", + "test": "jest --coverage", + "test:watch": "jest --watch", + "coverage": "jest --coverage --coverageReporters=html --coverageReporters=text", + "build": "flow-remove-types src --out-dir dist --quiet", + "prepublishOnly": "npm run build" + }, + "lint-staged": { + "*.js": [ + "eslint --fix", + "prettier --write", + "git add" + ], + "*.md": [ + "npm run lint:md-partial", + "git add" + ] + }, + "repository": { + "type": "git", + "url": "git+https://github.com/davidtheclark/cosmiconfig.git" + }, + "keywords": [ + "load", + "configuration", + "config" + ], + "author": "David Clark <david.dave.clark@gmail.com>", + "contributors": [ + "Bogdan Chadkin <trysound@yandex.ru>", + "Suhas Karanth <sudo.suhas@gmail.com>" + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/davidtheclark/cosmiconfig/issues" + }, + "homepage": "https://github.com/davidtheclark/cosmiconfig#readme", + "prettier": { + "trailingComma": "es5", + "singleQuote": true, + "printWidth": 80, + "tabWidth": 2 + }, + "jest": { + "testEnvironment": "node", + "collectCoverageFrom": [ + "src/*.js" + ], + "coverageReporters": [ + "text", + "html", + "lcov" + ], + "coverageThreshold": { + "global": { + "branches": 100, + "functions": 100, + "lines": 100, + "statements": 100 + } + }, + "resetModules": true, + "resetMocks": true + }, + "babel": { + "plugins": [ + "transform-flow-strip-types" + ] + }, + "dependencies": { + "is-directory": "^0.3.1", + "js-yaml": "^3.9.0", + "parse-json": "^4.0.0" + }, + "devDependencies": { + "babel-eslint": "^8.0.3", + "babel-plugin-transform-flow-strip-types": "^6.22.0", + "del": "^3.0.0", + "eslint": "^4.12.1", + "eslint-config-davidtheclark-node": "^0.2.2", + "eslint-config-prettier": "^2.9.0", + "eslint-plugin-flowtype": "^2.39.1", + "eslint-plugin-node": "^5.2.1", + "flow-bin": "^0.68.0", + "flow-remove-types": "^1.2.3", + "husky": "^0.14.3", + "jest": "^21.2.1", + "lint-staged": "^6.0.0", + "make-dir": "^1.2.0", + "parent-module": "^0.1.0", + "prettier": "^1.8.2", + "remark-cli": "^5.0.0", + "remark-preset-davidtheclark": "^0.7.0" + }, + "engines": { + "node": ">=4" + } +} |
