cosmiconfig
Advanced tools
Comparing version 5.2.1 to 6.0.0
# Changelog | ||
## 6.0.0 | ||
- **Breaking change:** The package now has named exports. See examples below. | ||
- **Breaking change:** Separate async and sync APIs, accessible from different named exports. If you used `explorer.searchSync()` or `explorer.loadSync()`, you'll now create a sync explorer with `cosmiconfigSync()`, then use `explorerSync.search()` and `explorerSync.load()`. | ||
```js | ||
// OLD: cosmiconfig v5 | ||
import cosmiconfig from 'cosmiconfig'; | ||
const explorer = cosmiconfig('example'); | ||
const searchAsyncResult = await explorer.search(); | ||
const loadAsyncResult = await explorer.load('./file/to/load'); | ||
const searchSyncResult = explorer.searchSync(); | ||
const loadSyncResult = explorer.loadSync('./file/to/load'); | ||
// NEW: cosmiconfig v6 | ||
import { cosmiconfig, cosmiconfigSync } from 'cosmiconfig'; | ||
const explorer = cosmiconfig('example'); | ||
const searchAsyncResult = await explorer.search(); | ||
const loadAsyncResult = await explorer.load('./file/to/load'); | ||
const explorerSync = cosmiconfigSync('example'); | ||
const searchSyncResult = explorerSync.search(); | ||
const loadSyncResult = explorerSync.load('./file/to/load'); | ||
``` | ||
- **Breaking change:** Remove support for Node 4 and 6. Requires Node 8+. | ||
- **Breaking change:** Use npm package [yaml](https://www.npmjs.com/package/yaml) to parse YAML instead of npm package [js-yaml](https://www.npmjs.com/package/js-yaml). | ||
- **Breaking change:** Remove `cosmiconfig.loaders` and add named export `defaultLoaders` that exports the default loaders used for each extension. | ||
```js | ||
import { defaultLoaders } from 'cosmiconfig'; | ||
console.log(Object.entries(defaultLoaders)) | ||
// [ | ||
// [ '.js', [Function: loadJs] ], | ||
// [ '.json', [Function: loadJson] ], | ||
// [ '.yaml', [Function: loadYaml] ], | ||
// [ '.yml', [Function: loadYaml] ], | ||
// [ 'noExt', [Function: loadYaml] ] | ||
// ] | ||
``` | ||
- Migrate from Flowtype to Typescript. | ||
- Lazy load all default loaders. | ||
## 5.2.1 | ||
@@ -4,0 +49,0 @@ |
@@ -1,10 +0,24 @@ | ||
// | ||
'use strict'; | ||
"use strict"; | ||
function cacheWrapper (cache , key , fn ) { | ||
if (!cache) { | ||
return fn(); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.cacheWrapper = cacheWrapper; | ||
exports.cacheWrapperSync = cacheWrapperSync; | ||
async function cacheWrapper(cache, key, fn) { | ||
const cached = cache.get(key); | ||
if (cached !== undefined) { | ||
return cached; | ||
} | ||
const result = await fn(); | ||
cache.set(key, result); | ||
return result; | ||
} | ||
function cacheWrapperSync(cache, key, fn) { | ||
const cached = cache.get(key); | ||
if (cached !== undefined) { | ||
@@ -18,3 +32,2 @@ return cached; | ||
} | ||
module.exports = cacheWrapper; | ||
//# sourceMappingURL=cacheWrapper.js.map |
@@ -1,22 +0,38 @@ | ||
// | ||
'use strict'; | ||
"use strict"; | ||
const path = require('path'); | ||
const isDirectory = require('is-directory'); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.getDirectory = getDirectory; | ||
exports.getDirectorySync = getDirectorySync; | ||
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)); | ||
}); | ||
}); | ||
var _path = _interopRequireDefault(require("path")); | ||
var _pathType = require("path-type"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
async function getDirectory(filepath) { | ||
const filePathIsDirectory = await (0, _pathType.isDirectory)(filepath); | ||
if (filePathIsDirectory === true) { | ||
return filepath; | ||
} | ||
const directory = _path.default.dirname(filepath); | ||
return directory; | ||
} | ||
getDirectory.sync = function getDirectorySync(filepath ) { | ||
return isDirectory.sync(filepath) ? filepath : path.dirname(filepath); | ||
}; | ||
function getDirectorySync(filepath) { | ||
const filePathIsDirectory = (0, _pathType.isDirectorySync)(filepath); | ||
module.exports = getDirectory; | ||
if (filePathIsDirectory === true) { | ||
return filepath; | ||
} | ||
const directory = _path.default.dirname(filepath); | ||
return directory; | ||
} | ||
//# sourceMappingURL=getDirectory.js.map |
@@ -1,4 +0,8 @@ | ||
// | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.getPropertyByPath = getPropertyByPath; | ||
// Resolves property names or property paths defined with period-delimited | ||
@@ -9,8 +13,9 @@ // strings or arrays of strings. Property names that are found on the source | ||
// understood in array paths. | ||
function getPropertyByPath(source , path ) { | ||
if (typeof path === 'string' && source.hasOwnProperty(path)) { | ||
function getPropertyByPath(source, path) { | ||
if (typeof path === 'string' && Object.prototype.hasOwnProperty.call(source, path)) { | ||
return source[path]; | ||
} | ||
const parsedPath = typeof path === 'string' ? path.split('.') : path; | ||
const parsedPath = typeof path === 'string' ? path.split('.') : path; // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
return parsedPath.reduce((previous, key) => { | ||
@@ -20,6 +25,6 @@ if (previous === undefined) { | ||
} | ||
return previous[key]; | ||
}, source); | ||
} | ||
module.exports = getPropertyByPath; | ||
//# sourceMappingURL=getPropertyByPath.js.map |
@@ -1,81 +0,80 @@ | ||
// | ||
'use strict'; | ||
"use strict"; | ||
const os = require('os'); | ||
const createExplorer = require('./createExplorer'); | ||
const loaders = require('./loaders'); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.cosmiconfig = cosmiconfig; | ||
exports.cosmiconfigSync = cosmiconfigSync; | ||
exports.defaultLoaders = void 0; | ||
module.exports = cosmiconfig; | ||
var _os = _interopRequireDefault(require("os")); | ||
function cosmiconfig( | ||
moduleName , | ||
options | ||
) { | ||
options = options || {}; | ||
var _Explorer = require("./Explorer"); | ||
var _ExplorerSync = require("./ExplorerSync"); | ||
var _loaders = require("./loaders"); | ||
var _types = require("./types"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type | ||
function cosmiconfig(moduleName, options = {}) { | ||
const normalizedOptions = normalizeOptions(moduleName, options); | ||
const explorer = new _Explorer.Explorer(normalizedOptions); | ||
return { | ||
search: explorer.search.bind(explorer), | ||
load: explorer.load.bind(explorer), | ||
clearLoadCache: explorer.clearLoadCache.bind(explorer), | ||
clearSearchCache: explorer.clearSearchCache.bind(explorer), | ||
clearCaches: explorer.clearCaches.bind(explorer) | ||
}; | ||
} // eslint-disable-next-line @typescript-eslint/explicit-function-return-type | ||
function cosmiconfigSync(moduleName, options = {}) { | ||
const normalizedOptions = normalizeOptions(moduleName, options); | ||
const explorerSync = new _ExplorerSync.ExplorerSync(normalizedOptions); | ||
return { | ||
search: explorerSync.searchSync.bind(explorerSync), | ||
load: explorerSync.loadSync.bind(explorerSync), | ||
clearLoadCache: explorerSync.clearLoadCache.bind(explorerSync), | ||
clearSearchCache: explorerSync.clearSearchCache.bind(explorerSync), | ||
clearCaches: explorerSync.clearCaches.bind(explorerSync) | ||
}; | ||
} // do not allow mutation of default loaders. Make sure it is set inside options | ||
const defaultLoaders = Object.freeze({ | ||
'.js': _loaders.loaders.loadJs, | ||
'.json': _loaders.loaders.loadJson, | ||
'.yaml': _loaders.loaders.loadYaml, | ||
'.yml': _loaders.loaders.loadYaml, | ||
noExt: _loaders.loaders.loadYaml | ||
}); | ||
exports.defaultLoaders = defaultLoaders; | ||
function normalizeOptions(moduleName, 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`, | ||
], | ||
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(), | ||
stopDir: _os.default.homedir(), | ||
cache: true, | ||
transform: identity, | ||
loaders: defaultLoaders | ||
}; | ||
const normalizedOptions = Object.assign( | ||
{}, | ||
defaults, | ||
options, | ||
{ | ||
loaders: normalizeLoaders(options.loaders), | ||
const normalizedOptions = { ...defaults, | ||
...options, | ||
loaders: { ...defaults.loaders, | ||
...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); | ||
return normalizedOptions; | ||
} | ||
function identity(x) { | ||
const identity = function identity(x) { | ||
return x; | ||
} | ||
}; | ||
//# sourceMappingURL=index.js.map |
@@ -1,30 +0,60 @@ | ||
// | ||
'use strict'; | ||
"use strict"; | ||
const parseJson = require('parse-json'); | ||
const yaml = require('js-yaml'); | ||
const importFresh = require('import-fresh'); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.loaders = void 0; | ||
function loadJs(filepath ) { | ||
/* eslint-disable @typescript-eslint/no-require-imports */ | ||
let importFresh; | ||
const loadJs = function loadJs(filepath) { | ||
if (importFresh === undefined) { | ||
importFresh = require('import-fresh'); | ||
} | ||
const result = importFresh(filepath); | ||
return result; | ||
} | ||
}; | ||
function loadJson(filepath , content ) { | ||
let parseJson; | ||
const loadJson = function loadJson(filepath, content) { | ||
if (parseJson === undefined) { | ||
parseJson = require('parse-json'); | ||
} | ||
try { | ||
return parseJson(content); | ||
} catch (err) { | ||
err.message = `JSON Error in ${filepath}:\n${err.message}`; | ||
throw err; | ||
const result = parseJson(content); | ||
return result; | ||
} catch (error) { | ||
error.message = `JSON Error in ${filepath}:\n${error.message}`; | ||
throw error; | ||
} | ||
} | ||
}; | ||
function loadYaml(filepath , content ) { | ||
return yaml.safeLoad(content, { filename: filepath }); | ||
} | ||
let yaml; | ||
module.exports = { | ||
const loadYaml = function loadYaml(filepath, content) { | ||
if (yaml === undefined) { | ||
yaml = require('yaml'); | ||
} | ||
try { | ||
const result = yaml.parse(content, { | ||
prettyErrors: true | ||
}); | ||
return result; | ||
} catch (error) { | ||
error.message = `YAML Error in ${filepath}:\n${error.message}`; | ||
throw error; | ||
} | ||
}; | ||
const loaders = { | ||
loadJs, | ||
loadJson, | ||
loadYaml, | ||
loadYaml | ||
}; | ||
exports.loaders = loaders; | ||
//# sourceMappingURL=loaders.js.map |
@@ -1,21 +0,22 @@ | ||
// | ||
'use strict'; | ||
"use strict"; | ||
const fs = require('fs'); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.readFile = readFile; | ||
exports.readFileSync = readFileSync; | ||
var _fs = _interopRequireDefault(require("fs")); | ||
function readFile(filepath , options ) { | ||
options = options || {}; | ||
const throwNotFound = options.throwNotFound || false; | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
async function fsReadFileAsync(pathname, encoding) { | ||
return new Promise((resolve, reject) => { | ||
fs.readFile(filepath, 'utf8', (err, content) => { | ||
if (err && err.code === 'ENOENT' && !throwNotFound) { | ||
return resolve(null); | ||
_fs.default.readFile(pathname, encoding, (error, contents) => { | ||
if (error) { | ||
reject(error); | ||
return; | ||
} | ||
if (err) return reject(err); | ||
resolve(content); | ||
resolve(contents); | ||
}); | ||
@@ -25,19 +26,32 @@ }); | ||
readFile.sync = function readFileSync( | ||
filepath , | ||
options | ||
) { | ||
options = options || {}; | ||
const throwNotFound = options.throwNotFound || false; | ||
async function readFile(filepath, options = {}) { | ||
const throwNotFound = options.throwNotFound === true; | ||
try { | ||
return fs.readFileSync(filepath, 'utf8'); | ||
} catch (err) { | ||
if (err.code === 'ENOENT' && !throwNotFound) { | ||
const content = await fsReadFileAsync(filepath, 'utf8'); | ||
return content; | ||
} catch (error) { | ||
if (throwNotFound === false && error.code === 'ENOENT') { | ||
return null; | ||
} | ||
throw err; | ||
throw error; | ||
} | ||
}; | ||
} | ||
module.exports = readFile; | ||
function readFileSync(filepath, options = {}) { | ||
const throwNotFound = options.throwNotFound === true; | ||
try { | ||
const content = _fs.default.readFileSync(filepath, 'utf8'); | ||
return content; | ||
} catch (error) { | ||
if (throwNotFound === false && error.code === 'ENOENT') { | ||
return null; | ||
} | ||
throw error; | ||
} | ||
} | ||
//# sourceMappingURL=readFile.js.map |
114
package.json
{ | ||
"name": "cosmiconfig", | ||
"version": "5.2.1", | ||
"version": "6.0.0", | ||
"description": "Find and load configuration from a package.json property, rc file, or CommonJS module", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts", | ||
"files": [ | ||
@@ -10,17 +11,27 @@ "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", | ||
"clean": "del-cli --dot=true \"./dist/**/*\"", | ||
"build": "npm run clean && npm run build:compile && npm run build:types", | ||
"build:compile": "cross-env NODE_ENV=production babel src -d dist --verbose --extensions .js,.ts --ignore \"**/**/*.test.js\",\"**/**/*.test.ts\" --source-maps", | ||
"build:types": "cross-env NODE_ENV=production tsc --project tsconfig.types.json", | ||
"dev": "npm run clean && npm run build:compile -- --watch", | ||
"lint": "eslint --ext .js,.ts . && npm run lint:md", | ||
"lint:fix": "eslint --ext .js,.ts . --fix", | ||
"lint:md": "remark-preset-davidtheclark", | ||
"format": "prettier \"**/*.{js,ts,json,yml,yaml}\" --write", | ||
"format:md": "remark-preset-davidtheclark --format", | ||
"format:check": "prettier \"**/*.{js,ts,json,yml,yaml}\" --check", | ||
"typescript": "tsc", | ||
"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" | ||
"check:all": "npm run test && npm run typescript && npm run lint && npm run format:check", | ||
"prepublishOnly": "npm run check:all && npm run build" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "lint-staged && npm run typescript && npm run test", | ||
"pre-push": "npm run check:all" | ||
} | ||
}, | ||
"lint-staged": { | ||
"*.js": [ | ||
"*.{js,ts}": [ | ||
"eslint --fix", | ||
@@ -30,4 +41,9 @@ "prettier --write", | ||
], | ||
"*.{json,yml,yaml}": [ | ||
"prettier --write", | ||
"git add" | ||
], | ||
"*.md": [ | ||
"npm run lint:md-partial", | ||
"remark-preset-davidtheclark", | ||
"remark-preset-davidtheclark --format", | ||
"git add" | ||
@@ -56,3 +72,4 @@ ] | ||
"prettier": { | ||
"trailingComma": "es5", | ||
"trailingComma": "all", | ||
"arrowParens": "always", | ||
"singleQuote": true, | ||
@@ -65,3 +82,3 @@ "printWidth": 80, | ||
"collectCoverageFrom": [ | ||
"src/*.js" | ||
"src/**/*.{js,ts}" | ||
], | ||
@@ -82,38 +99,55 @@ "coverageReporters": [ | ||
"resetModules": true, | ||
"resetMocks": true | ||
"resetMocks": true, | ||
"restoreMocks": true | ||
}, | ||
"babel": { | ||
"plugins": [ | ||
"transform-flow-strip-types" | ||
"presets": [ | ||
[ | ||
"@babel/preset-env", | ||
{ | ||
"targets": { | ||
"node": "8.9" | ||
} | ||
} | ||
], | ||
"@babel/preset-typescript" | ||
] | ||
}, | ||
"dependencies": { | ||
"import-fresh": "^2.0.0", | ||
"is-directory": "^0.3.1", | ||
"js-yaml": "^3.13.1", | ||
"parse-json": "^4.0.0" | ||
"@types/parse-json": "^4.0.0", | ||
"import-fresh": "^3.1.0", | ||
"parse-json": "^5.0.0", | ||
"path-type": "^4.0.0", | ||
"yaml": "^1.7.2" | ||
}, | ||
"devDependencies": { | ||
"babel-eslint": "^8.0.3", | ||
"babel-plugin-transform-flow-strip-types": "^6.22.0", | ||
"del": "^3.0.0", | ||
"eslint": "^4.12.1", | ||
"@babel/cli": "^7.6.4", | ||
"@babel/core": "^7.6.4", | ||
"@babel/preset-env": "^7.6.3", | ||
"@babel/preset-typescript": "^7.6.0", | ||
"@types/jest": "^24.0.19", | ||
"@types/node": "^12.11.5", | ||
"@typescript-eslint/eslint-plugin": "^2.5.0", | ||
"@typescript-eslint/parser": "^2.5.0", | ||
"cross-env": "^6.0.3", | ||
"del": "^5.1.0", | ||
"del-cli": "^3.0.0", | ||
"eslint": "^6.5.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" | ||
"eslint-config-prettier": "^6.4.0", | ||
"eslint-plugin-import": "^2.18.2", | ||
"eslint-plugin-jest": "^22.20.0", | ||
"eslint-plugin-node": "^10.0.0", | ||
"husky": "^3.0.9", | ||
"jest": "^24.9.0", | ||
"lint-staged": "^9.4.2", | ||
"make-dir": "^3.0.0", | ||
"parent-module": "^2.0.0", | ||
"prettier": "^1.18.2", | ||
"remark-preset-davidtheclark": "^0.10.0", | ||
"typescript": "^3.6.4" | ||
}, | ||
"engines": { | ||
"node": ">=4" | ||
"node": ">=8" | ||
} | ||
} |
197
README.md
@@ -18,16 +18,16 @@ # cosmiconfig | ||
For example, if your module's name is "soursocks", cosmiconfig will search up the directory tree for configuration in the following places: | ||
For example, if your module's name is "myapp", 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 | ||
- a `myapp` property in `package.json` | ||
- a `.myapprc` file in JSON or YAML format | ||
- a `.myapprc.json` file | ||
- a `.myapprc.yaml`, `.myapprc.yml`, or `.myapprc.js` file | ||
- a `myapp.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). | ||
👀 **Looking for the v5 docs?** | ||
v6 involves slight changes to Cosmiconfig's API, clarifying the difference between synchronous and asynchronous usage. | ||
If you have trouble switching from v5 to v6, please file an issue. | ||
If you are still using v5, those v5 docs are available [in the `5.x.x` tagged code](https://github.com/davidtheclark/cosmiconfig/tree/5.2.1). | ||
@@ -39,12 +39,16 @@ ## Table of contents | ||
- [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) | ||
- [Asynchronous API](#asynchronous-api) | ||
- [cosmiconfig()](#cosmiconfig) | ||
- [explorer.search()](#explorersearch) | ||
- [explorer.load()](#explorerload) | ||
- [explorer.clearLoadCache()](#explorerclearloadcache) | ||
- [explorer.clearSearchCache()](#explorerclearsearchcache) | ||
- [explorer.clearCaches()](#explorerclearcaches) | ||
- [Synchronsous API](#synchronsous-api) | ||
- [cosmiconfigSync()](#cosmiconfigsync) | ||
- [explorerSync.search()](#explorersyncsearch) | ||
- [explorerSync.load()](#explorersyncload) | ||
- [explorerSync.clearLoadCache()](#explorersyncclearloadcache) | ||
- [explorerSync.clearSearchCache()](#explorersyncclearsearchcache) | ||
- [explorerSync.clearCaches()](#explorersyncclearcaches) | ||
- [cosmiconfigOptions](#cosmiconfigoptions) | ||
@@ -68,3 +72,3 @@ - [searchPlaces](#searchplaces) | ||
Tested in Node 4+. | ||
Tested in Node 8+. | ||
@@ -76,3 +80,3 @@ ## Usage | ||
```js | ||
const cosmiconfig = require('cosmiconfig'); | ||
const { cosmiconfig, cosmiconfigSync } = require('cosmiconfig'); | ||
// ... | ||
@@ -99,4 +103,6 @@ const explorer = cosmiconfig(moduleName); | ||
// You can also search and load synchronously. | ||
const searchedFor = explorer.searchSync(); | ||
const loaded = explorer.loadSync(pathToConfig); | ||
const explorerSync = cosmiconfigSync(moduleName); | ||
const searchedFor = explorerSync.search(); | ||
const loaded = explorerSync.load(pathToConfig); | ||
``` | ||
@@ -112,5 +118,8 @@ | ||
## cosmiconfig() | ||
## Asynchronous API | ||
### cosmiconfig() | ||
```js | ||
const { cosmiconfig } = require('cosmiconfig'); | ||
const explorer = cosmiconfig(moduleName[, cosmiconfigOptions]) | ||
@@ -121,3 +130,3 @@ ``` | ||
### moduleName | ||
#### moduleName | ||
@@ -128,6 +137,8 @@ Type: `string`. **Required.** | ||
If your [`searchPlaces`] value will include files, as it does by default (e.g. `${moduleName}rc`), your `moduleName` must consist of characters allowed in filenames. That means you should not copy scoped package names, such as `@my-org/my-package`, directly into `moduleName`. | ||
**[`cosmiconfigOptions`] are documented below.** | ||
You may not need them, and should first read about the functions you'll use. | ||
## explorer.search() | ||
### explorer.search() | ||
@@ -140,3 +151,3 @@ ```js | ||
You can do the same thing synchronously with [`searchSync()`]. | ||
You can do the same thing synchronously with [`explorerSync.search()`]. | ||
@@ -155,5 +166,5 @@ Let's say your module name is `goldengrahams` so you initialized with `const explorer = cosmiconfig('goldengrahams');`. | ||
- 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 at any point a parsable configuration is found, the [`search()`] Promise resolves with its [result] \(or, with [`explorerSync.search()`], the [result] is returned). | ||
- If no configuration object is found, the [`search()`] Promise resolves with `null` (or, with [`explorerSync.search()`], `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 [`explorerSync.search()`], the error is thrown.) | ||
@@ -165,3 +176,3 @@ **If you know exactly where your configuration file should be, you can use [`load()`], instead.** | ||
### searchFrom | ||
#### searchFrom | ||
@@ -177,47 +188,74 @@ Type: `string`. | ||
## explorer.searchSync() | ||
### explorer.load() | ||
```js | ||
const result = explorer.searchSync([searchFrom]); | ||
explorer.load(loadPath).then(result => {..}) | ||
``` | ||
Synchronous version of [`search()`]. | ||
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). | ||
Returns a [result] or `null`. | ||
Use `load` if you already know where the configuration file is and you just need to load it. | ||
## explorer.load() | ||
```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`]. | ||
You can do the same thing synchronously with [`explorerSync.load()`]. | ||
### explorer.clearLoadCache() | ||
Clears the cache used in [`load()`]. | ||
### explorer.clearSearchCache() | ||
Clears the cache used in [`search()`]. | ||
### explorer.clearCaches() | ||
Performs both [`clearLoadCache()`] and [`clearSearchCache()`]. | ||
## Synchronsous API | ||
### cosmiconfigSync() | ||
```js | ||
explorer.load(loadPath).then(result => {..}) | ||
const { cosmiconfigSync } = require('cosmiconfig'); | ||
const explorerSync = cosmiconfigSync(moduleName[, cosmiconfigOptions]) | ||
``` | ||
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). | ||
Creates a *synchronous* cosmiconfig instance ("explorerSync") configured according to the arguments, and initializes its caches. | ||
Use `load` if you already know where the configuration file is and you just need to load it. | ||
See [`cosmiconfig()`]. | ||
### explorerSync.search() | ||
```js | ||
explorer.load('load/this/file.json'); // Tries to load load/this/file.json. | ||
const result = explorerSync.search([searchFrom]); | ||
``` | ||
If you load a `package.json` file, the result will be derived from whatever property is specified as your [`packageProp`]. | ||
Synchronous version of [`explorer.search()`]. | ||
## explorer.loadSync() | ||
Returns a [result] or `null`. | ||
### explorerSync.load() | ||
```js | ||
const result = explorer.loadSync(loadPath); | ||
const result = explorerSync.load(loadPath); | ||
``` | ||
Synchronous version of [`load()`]. | ||
Synchronous version of [`explorer.load()`]. | ||
Returns a [result]. | ||
## explorer.clearLoadCache() | ||
### explorerSync.clearLoadCache() | ||
Clears the cache used in [`load()`]. | ||
## explorer.clearSearchCache() | ||
### explorerSync.clearSearchCache() | ||
Clears the cache used in [`search()`]. | ||
## explorer.clearCaches() | ||
### explorerSync.clearCaches() | ||
@@ -316,3 +354,3 @@ Performs both [`clearLoadCache()`] and [`clearSearchCache()`]. | ||
Cosmiconfig exposes its default loaders for `.js`, `.json`, and `.yaml` as `cosmiconfig.loadJs`, `cosmiconfig.loadJson`, and `cosmiconfig.loadYaml`, respectively. | ||
Cosmiconfig exposes its default loaders on a named export `defaultLoaders`. | ||
@@ -322,9 +360,12 @@ **Default `loaders`:** | ||
```js | ||
{ | ||
'.json': cosmiconfig.loadJson, | ||
'.yaml': cosmiconfig.loadYaml, | ||
'.yml': cosmiconfig.loadYaml, | ||
'.js': cosmiconfig.loadJs, | ||
noExt: cosmiconfig.loadYaml | ||
} | ||
const { defaultLoaders } = require('cosmiconfig'); | ||
console.log(Object.entries(defaultLoaders)) | ||
// [ | ||
// [ '.js', [Function: loadJs] ], | ||
// [ '.json', [Function: loadJson] ], | ||
// [ '.yaml', [Function: loadYaml] ], | ||
// [ '.yml', [Function: loadYaml] ], | ||
// [ 'noExt', [Function: loadYaml] ] | ||
// ] | ||
``` | ||
@@ -337,5 +378,5 @@ | ||
**Keys in `loaders`** are extensions (starting with a period), or `noExt` to specify the loader for files *without* extensions, like `.soursocksrc`. | ||
**Keys in `loaders`** are extensions (starting with a period), or `noExt` to specify the loader for files *without* extensions, like `.myapprc`. | ||
**Values in `loaders`** are either a loader function (described below) or an object with `sync` and/or `async` properties, whose values are loader functions. | ||
**Values in `loaders`** are a loader function (described below) whose values are loader functions. | ||
@@ -347,3 +388,3 @@ **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). | ||
{ | ||
noExt: cosmiconfig.loadJson | ||
noExt: defaultLoaders['.json'] | ||
} | ||
@@ -378,11 +419,6 @@ ``` | ||
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`. | ||
- If you use a custom loader, be aware of whether it's sync or async: you cannot use async customer loaders with the sync API ([`cosmiconfigSync()`]). | ||
- **Special JS syntax can also be handled by using a `require` hook**, because `defaultLoaders['.js']` just uses `require`. | ||
Whether you use custom loaders or a `require` hook is up to you. | ||
@@ -398,7 +434,2 @@ | ||
// Allow XML, and treat sync and async separately: | ||
{ | ||
'.xml': { async: asyncXmlLoader, sync: syncXmlLoader } | ||
} | ||
// Allow a special configuration syntax of your own creation: | ||
@@ -418,5 +449,5 @@ { | ||
{ | ||
'.mjs': cosmiconfig.loadJs, | ||
'.ts': cosmiconfig.loadJs, | ||
'.coffee': cosmiconfig.loadJs | ||
'.mjs': defaultLoaders['.js'], | ||
'.ts': defaultLoaders['.js'], | ||
'.coffee': defaultLoaders['.js'] | ||
} | ||
@@ -489,3 +520,3 @@ ``` | ||
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. | ||
If using `cosmiconfigSync`, [`search()`] or [`load()`], the function must be synchronous and return the transformed result. | ||
@@ -535,8 +566,4 @@ 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. | ||
[`loadsync()`]: #explorerloadsync | ||
[`search()`]: #explorersearch | ||
[`searchsync()`]: #explorersearchsync | ||
[`clearloadcache()`]: #explorerclearloadcache | ||
@@ -546,2 +573,6 @@ | ||
[`cosmiconfig()`]: #cosmiconfig | ||
[`cosmiconfigSync()`]: #cosmiconfigsync | ||
[`clearcaches()`]: #explorerclearcaches | ||
@@ -560,1 +591,9 @@ | ||
[`cosmiconfigoptions`]: #cosmiconfigoptions | ||
[`explorerSync.search()`]: #explorersyncsearch | ||
[`explorerSync.load()`]: #explorersyncload | ||
[`explorer.search()`]: #explorersearch | ||
[`explorer.load()`]: #explorerload |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
99585
44
655
577
5
25
1
+ Added@types/parse-json@^4.0.0
+ Addedpath-type@^4.0.0
+ Addedyaml@^1.7.2
+ Added@babel/code-frame@7.24.2(transitive)
+ Added@babel/helper-validator-identifier@7.24.5(transitive)
+ Added@babel/highlight@7.24.5(transitive)
+ Added@types/parse-json@4.0.2(transitive)
+ Addedansi-styles@3.2.1(transitive)
+ Addedcallsites@3.1.0(transitive)
+ Addedchalk@2.4.2(transitive)
+ Addedcolor-convert@1.9.3(transitive)
+ Addedcolor-name@1.1.3(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedhas-flag@3.0.0(transitive)
+ Addedimport-fresh@3.3.0(transitive)
+ Addedjs-tokens@4.0.0(transitive)
+ Addedjson-parse-even-better-errors@2.3.1(transitive)
+ Addedlines-and-columns@1.2.4(transitive)
+ Addedparent-module@1.0.1(transitive)
+ Addedparse-json@5.2.0(transitive)
+ Addedpath-type@4.0.0(transitive)
+ Addedpicocolors@1.0.0(transitive)
+ Addedresolve-from@4.0.0(transitive)
+ Addedsupports-color@5.5.0(transitive)
+ Addedyaml@1.10.2(transitive)
- Removedis-directory@^0.3.1
- Removedjs-yaml@^3.13.1
- Removedargparse@1.0.10(transitive)
- Removedcaller-callsite@2.0.0(transitive)
- Removedcaller-path@2.0.0(transitive)
- Removedcallsites@2.0.0(transitive)
- Removedesprima@4.0.1(transitive)
- Removedimport-fresh@2.0.0(transitive)
- Removedis-directory@0.3.1(transitive)
- Removedjs-yaml@3.14.1(transitive)
- Removedjson-parse-better-errors@1.0.2(transitive)
- Removedparse-json@4.0.0(transitive)
- Removedresolve-from@3.0.0(transitive)
- Removedsprintf-js@1.0.3(transitive)
Updatedimport-fresh@^3.1.0
Updatedparse-json@^5.0.0