From dcccfed366823fc0afb703a2f4c64e7148cb1fb0 Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Mon, 10 Jul 2017 22:26:36 +1000 Subject: [PATCH] Implement cosmiconfig for workspace configuration (#2434) * Implement cosmiconfig * Add resolveOptions API and extname support * Add --resolve-config and --config, rename resolveOptions to resolveConfig * Move color to top-level CLI options * Fix unknown param warning * Change from {} to null when no config is found * Change override API to emulate eslint * Add test for eslint-style overrides * Delete overrides from resolveConfig --- bin/prettier.js | 212 +++++++++++++----- index.js | 9 +- package.json | 3 + src/resolve-config.js | 68 ++++++ .../__snapshots__/config-resolution.js.snap | 118 ++++++++++ .../__tests__/config-resolution.js | 75 +++++++ tests_integration/cli/config/.prettierrc | 6 + tests_integration/cli/config/jest/.prettierrc | 8 + .../cli/config/jest/Component.js | 2 + .../cli/config/jest/Component.test.js | 2 + .../cli/config/jest/__best-tests__/file.js | 2 + tests_integration/cli/config/js/file.js | 5 + .../cli/config/js/prettier.config.js | 5 + .../cli/config/no-config/file.js | 5 + .../cli/config/no-config/file.ts | 3 + tests_integration/cli/config/package/file.js | 5 + tests_integration/cli/config/package/file.ts | 3 + .../cli/config/package/package.json | 15 ++ .../cli/config/rc-json/.prettierrc | 4 + tests_integration/cli/config/rc-json/file.js | 9 + yarn.lock | 30 ++- 21 files changed, 525 insertions(+), 64 deletions(-) create mode 100644 src/resolve-config.js create mode 100644 tests_integration/__tests__/__snapshots__/config-resolution.js.snap create mode 100644 tests_integration/__tests__/config-resolution.js create mode 100644 tests_integration/cli/config/.prettierrc create mode 100644 tests_integration/cli/config/jest/.prettierrc create mode 100644 tests_integration/cli/config/jest/Component.js create mode 100644 tests_integration/cli/config/jest/Component.test.js create mode 100644 tests_integration/cli/config/jest/__best-tests__/file.js create mode 100644 tests_integration/cli/config/js/file.js create mode 100644 tests_integration/cli/config/js/prettier.config.js create mode 100644 tests_integration/cli/config/no-config/file.js create mode 100644 tests_integration/cli/config/no-config/file.ts create mode 100644 tests_integration/cli/config/package/file.js create mode 100644 tests_integration/cli/config/package/file.ts create mode 100644 tests_integration/cli/config/package/package.json create mode 100644 tests_integration/cli/config/rc-json/.prettierrc create mode 100644 tests_integration/cli/config/rc-json/file.js diff --git a/bin/prettier.js b/bin/prettier.js index be2b0701..1cdc0b00 100755 --- a/bin/prettier.js +++ b/bin/prettier.js @@ -2,24 +2,41 @@ "use strict"; +const chalk = require("chalk"); +const dashify = require("dashify"); const fs = require("fs"); const getStream = require("get-stream"); const globby = require("globby"); -const chalk = require("chalk"); const minimist = require("minimist"); +const path = require("path"); const readline = require("readline"); -const prettier = eval("require")("../index"); -const cleanAST = require("../src/clean-ast.js").cleanAST; -const argv = minimist(process.argv.slice(2), { +const prettier = eval("require")("../index"); +const cleanAST = require("../src/clean-ast").cleanAST; +const resolver = require("../src/resolve-config"); + +const args = process.argv.slice(2); + +const booleanOptionNames = [ + "use-tabs", + "semi", + "single-quote", + "bracket-spacing", + "jsx-bracket-same-line", + // Deprecated in 0.0.10 + "flow-parser" +]; +const stringOptionNames = [ + "print-width", + "tab-width", + "parser", + "trailing-comma" +]; + +const argv = minimist(args, { boolean: [ "write", "stdin", - "use-tabs", - "semi", - "single-quote", - "bracket-spacing", - "jsx-bracket-same-line", // The supports-color package (a sub sub dependency) looks directly at // `process.argv` for `--no-color` and such-like options. The reason it is // listed here is to avoid "Ignored unknown option: --no-color" warnings. @@ -30,31 +47,34 @@ const argv = minimist(process.argv.slice(2), { "version", "debug-print-doc", "debug-check", - "with-node-modules", - // Deprecated in 0.0.10 - "flow-parser" + "with-node-modules" ], string: [ - "print-width", - "tab-width", - "parser", - "trailing-comma", "cursor-offset", "range-start", "range-end", - "stdin-filepath" + "stdin-filepath", + "config", + "resolve-config" ], default: { - semi: true, - color: true, - "bracket-spacing": true, - parser: "babylon" + color: true + }, + alias: { + help: "h", + version: "v", + "list-different": "l" }, - alias: { help: "h", version: "v", "list-different": "l" }, unknown: param => { if (param.startsWith("-")) { - console.warn("Ignored unknown option: " + param + "\n"); - return false; + const paramName = param.substring(2); + if ( + booleanOptionNames.indexOf(paramName) === -1 && + stringOptionNames.indexOf(paramName) === -1 + ) { + console.warn("Ignored unknown option: " + param + "\n"); + return false; + } } } }); @@ -78,9 +98,56 @@ if (write && argv["debug-check"]) { process.exit(1); } -function getParserOption() { - const optionName = "parser"; - const value = argv[optionName]; +if (argv["resolve-config"] && filepatterns.length) { + console.error("Cannot use --resolve-config with multiple files"); + process.exit(1); +} + +function getOptionsForFile(filePath) { + return resolver + .resolveConfig(filePath, { configFile: argv["config"] }) + .then(options => { + const parsedArgs = minimist(args, { + boolean: booleanOptionNames, + string: stringOptionNames, + default: Object.assign( + { + semi: true, + "bracket-spacing": true, + parser: "babylon" + }, + dashifyObject(options) + ) + }); + + return getOptions(Object.assign({}, argv, parsedArgs)); + }) + .catch(error => { + console.error("Invalid configuration file:", error.toString()); + process.exit(2); + }); +} + +function getOptions(argv) { + return { + cursorOffset: getIntOption(argv, "cursor-offset"), + rangeStart: getIntOption(argv, "range-start"), + rangeEnd: getIntOption(argv, "range-end"), + useTabs: argv["use-tabs"], + semi: argv["semi"], + printWidth: getIntOption(argv, "print-width"), + tabWidth: getIntOption(argv, "tab-width"), + bracketSpacing: argv["bracket-spacing"], + singleQuote: argv["single-quote"], + jsxBracketSameLine: argv["jsx-bracket-same-line"], + filepath: argv["stdin-filepath"], + trailingComma: getTrailingComma(argv), + parser: getParserOption(argv) + }; +} + +function getParserOption(argv) { + const value = argv.parser; if (value === undefined) { return value; @@ -95,7 +162,7 @@ function getParserOption() { return value; } -function getIntOption(optionName) { +function getIntOption(argv, optionName) { const value = argv[optionName]; if (value === undefined) { @@ -115,7 +182,7 @@ function getIntOption(optionName) { process.exit(1); } -function getTrailingComma() { +function getTrailingComma(argv) { switch (argv["trailing-comma"]) { case undefined: case "none": @@ -135,21 +202,12 @@ function getTrailingComma() { } } -const options = { - cursorOffset: getIntOption("cursor-offset"), - rangeStart: getIntOption("range-start"), - rangeEnd: getIntOption("range-end"), - useTabs: argv["use-tabs"], - semi: argv["semi"], - printWidth: getIntOption("print-width"), - tabWidth: getIntOption("tab-width"), - bracketSpacing: argv["bracket-spacing"], - singleQuote: argv["single-quote"], - jsxBracketSameLine: argv["jsx-bracket-same-line"], - filepath: argv["stdin-filepath"], - trailingComma: getTrailingComma(), - parser: getParserOption() -}; +function dashifyObject(object) { + return Object.keys(object || {}).reduce((output, key) => { + output[dashify(key)] = object[key]; + return output; + }, {}); +} function diff(a, b) { return require("diff").createTwoFilesPatch("", "", a, b, "", "", { @@ -214,12 +272,17 @@ function handleError(filename, e) { process.exitCode = 2; } -if (argv["help"] || (!filepatterns.length && !stdin)) { +if ( + argv["help"] || + (!filepatterns.length && !stdin && !argv["resolve-config"]) +) { console.log( "Usage: prettier [opts] [filename ...]\n\n" + "Available options:\n" + " --write Edit the file in-place. (Beware!)\n" + " --list-different or -l Print filenames of files that are different from Prettier formatting.\n" + + " --config Path to a prettier configuration file (.prettierrc, package.json, prettier.config.js).\n" + + " --resolve-config Resolve the path to a configuration file for a given input file.\n" + " --stdin Read input from stdin.\n" + " --stdin-filepath Path to the file used to read from stdin.\n" + " --print-width Specify the length of line that the printer will wrap on. Defaults to 80.\n" + @@ -251,20 +314,24 @@ if (argv["help"] || (!filepatterns.length && !stdin)) { process.exit(argv["help"] ? 0 : 1); } -if (stdin) { +if (argv["resolve-config"]) { + resolveConfig(argv["resolve-config"]); +} else if (stdin) { getStream(process.stdin).then(input => { - if (listDifferent(input, options, "(stdin)")) { - return; - } + getOptionsForFile(process.cwd()).then(options => { + if (listDifferent(input, options, "(stdin)")) { + return; + } - try { - writeOutput(format(input, options)); - } catch (e) { - handleError("stdin", e); - } + try { + writeOutput(format(input, options), options); + } catch (e) { + handleError("stdin", e); + } + }); }); } else { - eachFilename(filepatterns, filename => { + eachFilename(filepatterns, (filename, options) => { if (write) { // Don't use `console.log` here since we need to replace this line. process.stdout.write(filename); @@ -337,7 +404,7 @@ if (stdin) { process.exitCode = 2; } } else if (!argv["list-different"]) { - writeOutput(result); + writeOutput(result, options); } }); } @@ -359,7 +426,17 @@ function listDifferent(input, options, filename) { return true; } -function writeOutput(result) { +function resolveConfig(filePath) { + resolver.resolveConfigFile(filePath).then(configFile => { + if (configFile) { + console.log(path.relative(process.cwd(), configFile)); + } else { + process.exitCode = 1; + } + }); +} + +function writeOutput(result, options) { // Don't use `console.log` here since it adds an extra newline at the end. process.stdout.write(result.formatted); @@ -382,9 +459,11 @@ function eachFilename(patterns, callback) { process.exitCode = 2; return; } - - filePaths.forEach(filePath => { - return callback(filePath); + // Use map series to ensure idempotency + mapSeries(filePaths, filePath => { + return getOptionsForFile(filePath).then(options => + callback(filePath, options) + ); }); }) .catch(err => { @@ -395,3 +474,16 @@ function eachFilename(patterns, callback) { process.exitCode = 2; }); } + +function mapSeries(array, iteratee) { + let current = Promise.resolve(); + + const promises = array.map((item, i) => { + current = current.then(() => { + return iteratee(item, i, array); + }); + return current; + }); + + return Promise.all(promises); +} diff --git a/index.js b/index.js index 05464d5e..738651e9 100644 --- a/index.js +++ b/index.js @@ -9,6 +9,7 @@ const printDocToString = require("./src/doc-printer").printDocToString; const normalizeOptions = require("./src/options").normalize; const parser = require("./src/parser"); const printDocToDebug = require("./src/doc-debug").printDocToDebug; +const resolveConfig = require("./src/resolve-config").resolveConfig; function guessLineEnding(text) { const index = text.indexOf("\n"); @@ -323,9 +324,11 @@ module.exports = { formatWithCursor: function(text, opts) { return formatWithCursor(text, normalizeOptions(opts)); }, + format: function(text, opts) { return format(text, normalizeOptions(opts)); }, + check: function(text, opts) { try { const formatted = format(text, normalizeOptions(opts)); @@ -334,7 +337,11 @@ module.exports = { return false; } }, - version: version, + + resolveConfig, + + version, + __debug: { parse: function(text, opts) { return parser.parse(text, opts); diff --git a/package.json b/package.json index ba0bb137..8513990c 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,8 @@ "babel-code-frame": "7.0.0-alpha.12", "babylon": "7.0.0-beta.13", "chalk": "2.0.1", + "cosmiconfig": "2.1.3", + "dashify": "0.2.2", "diff": "3.2.0", "esutils": "2.0.2", "flow-parser": "0.47.0", @@ -22,6 +24,7 @@ "graphql": "0.10.1", "jest-validate": "20.0.3", "json-to-ast": "2.0.0-alpha1.2", + "minimatch": "3.0.4", "minimist": "1.2.0", "parse5": "3.0.2", "postcss": "^6.0.1", diff --git a/src/resolve-config.js b/src/resolve-config.js new file mode 100644 index 00000000..bf265cba --- /dev/null +++ b/src/resolve-config.js @@ -0,0 +1,68 @@ +"use strict"; + +const cosmiconfig = require("cosmiconfig"); +const minimatch = require("minimatch"); +const path = require("path"); + +const withCache = cosmiconfig("prettier"); +const noCache = cosmiconfig("prettier", { cache: false }); + +function resolveConfig(filePath, opts) { + const useCache = !(opts && opts.useCache === false); + const fileDir = filePath ? path.dirname(filePath) : undefined; + + return ( + (useCache ? withCache : noCache) + // https://github.com/davidtheclark/cosmiconfig/pull/68 + .load(fileDir, opts && opts.configFile) + .then(result => { + if (!result) { + return null; + } + + return mergeOverrides(result.config, filePath); + }) + ); +} + +function resolveConfigFile(filePath) { + return noCache.load(filePath).then(result => { + if (result) { + return result.filepath; + } + return null; + }); +} + +function mergeOverrides(config, filePath) { + const options = Object.assign({}, config); + if (filePath && options.overrides) { + for (const override of options.overrides) { + if (pathMatchesGlobs(filePath, override.files, override.excludeFiles)) { + Object.assign(options, override.options); + } + } + } + + delete options.overrides; + return options; +} + +// Based on eslint: https://github.com/eslint/eslint/blob/master/lib/config/config-ops.js +function pathMatchesGlobs(filePath, patterns, excludedPatterns) { + const patternList = [].concat(patterns); + const excludedPatternList = [].concat(excludedPatterns || []); + const opts = { matchBase: true }; + + return ( + patternList.some(pattern => minimatch(filePath, pattern, opts)) && + !excludedPatternList.some(excludedPattern => + minimatch(filePath, excludedPattern, opts) + ) + ); +} + +module.exports = { + resolveConfig, + resolveConfigFile +}; diff --git a/tests_integration/__tests__/__snapshots__/config-resolution.js.snap b/tests_integration/__tests__/__snapshots__/config-resolution.js.snap new file mode 100644 index 00000000..34befee4 --- /dev/null +++ b/tests_integration/__tests__/__snapshots__/config-resolution.js.snap @@ -0,0 +1,118 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`CLI overrides take precedence 1`] = ` +"/* eslint-disable */ +console.log( + \\"should have semi\\" +); +/* eslint-disable */ +console.log( + \\"should not have semi\\" +) +/* eslint-disable */ +console.log( + \\"should have semi\\" +); +/* eslint-disable */ + +function f() { + console.log( + \\"should have tab width 8\\" + ); +} +\\"use strict\\"; + +module.exports = { + tabWidth: 8 +}; +/* eslint-disable */ + +function f() { + console.log( + \\"should have no semicolons\\" + ) +} +/* eslint-disable */ + +function f() { + console.log( + \\"should have tab width 3\\" + ); +} +/* eslint-disable */ + +function f() { + console.log.apply( + null, + [ + 'this file', + 'should have trailing comma', + 'and single quotes', + ], + ); +} +" +`; + +exports[`accepts configuration from --config 1`] = ` +"/* eslint-disable */ + +function f() { + console.log(\\"should have tab width 8\\") +} +" +`; + +exports[`resolves configuration file with --resolve-config file 1`] = ` +".prettierrc +" +`; + +exports[`resolves configuration from external files 1`] = ` +"/* eslint-disable */ +console.log(\\"should have semi\\"); +/* eslint-disable */ +console.log(\\"should not have semi\\") +/* eslint-disable */ +console.log(\\"should have semi\\"); +/* eslint-disable */ + +function f() { + console.log(\\"should have tab width 8\\"); +} +\\"use strict\\"; + +module.exports = { + tabWidth: 8 +}; +/* eslint-disable */ + +function f() { + console.log(\\"should have no semicolons\\") +} +/* eslint-disable */ + +function f() { + console.log(\\"should have tab width 3\\"); +} +/* eslint-disable */ + +function f() { + console.log.apply(null, [ + 'this file', + 'should have trailing comma', + 'and single quotes', + ]); +} +" +`; + +exports[`resolves configuration from external files and overrides by extname 1`] = ` +"function g() { + console.log(\\"should have semicolons because it has a .ts extension\\"); +} +function g() { + console.log(\\"should have tab width 5 because it has .ts extension\\"); +} +" +`; diff --git a/tests_integration/__tests__/config-resolution.js b/tests_integration/__tests__/config-resolution.js new file mode 100644 index 00000000..947d4688 --- /dev/null +++ b/tests_integration/__tests__/config-resolution.js @@ -0,0 +1,75 @@ +"use strict"; + +const path = require("path"); + +const runPrettier = require("../runPrettier"); +const prettier = require("../../"); + +test("resolves configuration from external files", () => { + const output = runPrettier("cli/config/", ["**/*.js"]); + expect(output.stdout).toMatchSnapshot(); + expect(output.status).toEqual(0); +}); + +test("resolves configuration from external files and overrides by extname", () => { + const output = runPrettier("cli/config/", ["**/*.ts"]); + expect(output.stdout).toMatchSnapshot(); + expect(output.status).toEqual(0); +}); + +test("accepts configuration from --config", () => { + const output = runPrettier("cli/config/", [ + "--config", + ".prettierrc", + "./js/file.js" + ]); + expect(output.stdout).toMatchSnapshot(); + expect(output.status).toEqual(0); +}); + +test("resolves configuration file with --resolve-config file", () => { + const output = runPrettier("cli/config/", [ + "--resolve-config", + "no-config/file.js" + ]); + expect(output.stdout).toMatchSnapshot(); + expect(output.status).toEqual(0); +}); + +test("prints nothing when no file found with --resolve-config", () => { + const output = runPrettier("cli/config/", ["--resolve-config", ".."]); + expect(output.stdout).toEqual(""); + expect(output.status).toEqual(1); +}); + +test("CLI overrides take precedence", () => { + const output = runPrettier("cli/config/", ["--print-width", "1", "**/*.js"]); + expect(output.stdout).toMatchSnapshot(); + expect(output.status).toEqual(0); +}); + +test("API resolveConfig with no args", () => { + return prettier.resolveConfig().then(result => { + expect(result).toBeNull(); + }); +}); + +test("API resolveConfig with file arg", () => { + const file = path.resolve(path.join(__dirname, "../cli/config/js/file.js")); + return prettier.resolveConfig(file).then(result => { + expect(result).toMatchObject({ + tabWidth: 8 + }); + }); +}); + +test("API resolveConfig with file arg and extension override", () => { + const file = path.resolve( + path.join(__dirname, "../cli/config/no-config/file.ts") + ); + return prettier.resolveConfig(file).then(result => { + expect(result).toMatchObject({ + semi: true + }); + }); +}); diff --git a/tests_integration/cli/config/.prettierrc b/tests_integration/cli/config/.prettierrc new file mode 100644 index 00000000..177d6bda --- /dev/null +++ b/tests_integration/cli/config/.prettierrc @@ -0,0 +1,6 @@ +semi: false + +overrides: +- files: "*.ts" + options: + semi: true diff --git a/tests_integration/cli/config/jest/.prettierrc b/tests_integration/cli/config/jest/.prettierrc new file mode 100644 index 00000000..3eb673af --- /dev/null +++ b/tests_integration/cli/config/jest/.prettierrc @@ -0,0 +1,8 @@ +semi: false + +overrides: +- files: + - "*.test.js" + - "**/__best-tests__/*.js" + options: + semi: true diff --git a/tests_integration/cli/config/jest/Component.js b/tests_integration/cli/config/jest/Component.js new file mode 100644 index 00000000..a06d12ca --- /dev/null +++ b/tests_integration/cli/config/jest/Component.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +console.log("should not have semi") diff --git a/tests_integration/cli/config/jest/Component.test.js b/tests_integration/cli/config/jest/Component.test.js new file mode 100644 index 00000000..018894b0 --- /dev/null +++ b/tests_integration/cli/config/jest/Component.test.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +console.log("should have semi"); diff --git a/tests_integration/cli/config/jest/__best-tests__/file.js b/tests_integration/cli/config/jest/__best-tests__/file.js new file mode 100644 index 00000000..018894b0 --- /dev/null +++ b/tests_integration/cli/config/jest/__best-tests__/file.js @@ -0,0 +1,2 @@ +/* eslint-disable */ +console.log("should have semi"); diff --git a/tests_integration/cli/config/js/file.js b/tests_integration/cli/config/js/file.js new file mode 100644 index 00000000..ded607e0 --- /dev/null +++ b/tests_integration/cli/config/js/file.js @@ -0,0 +1,5 @@ +/* eslint-disable */ + +function f() { + console.log("should have tab width 8"); +} diff --git a/tests_integration/cli/config/js/prettier.config.js b/tests_integration/cli/config/js/prettier.config.js new file mode 100644 index 00000000..a4b0c1d6 --- /dev/null +++ b/tests_integration/cli/config/js/prettier.config.js @@ -0,0 +1,5 @@ +"use strict"; + +module.exports = { + tabWidth: 8 +}; diff --git a/tests_integration/cli/config/no-config/file.js b/tests_integration/cli/config/no-config/file.js new file mode 100644 index 00000000..da197b3c --- /dev/null +++ b/tests_integration/cli/config/no-config/file.js @@ -0,0 +1,5 @@ +/* eslint-disable */ + +function f() { + console.log("should have no semicolons"); +} diff --git a/tests_integration/cli/config/no-config/file.ts b/tests_integration/cli/config/no-config/file.ts new file mode 100644 index 00000000..0aa07669 --- /dev/null +++ b/tests_integration/cli/config/no-config/file.ts @@ -0,0 +1,3 @@ +function g() { + console.log("should have semicolons because it has a .ts extension"); +} diff --git a/tests_integration/cli/config/package/file.js b/tests_integration/cli/config/package/file.js new file mode 100644 index 00000000..d0bedd4f --- /dev/null +++ b/tests_integration/cli/config/package/file.js @@ -0,0 +1,5 @@ +/* eslint-disable */ + +function f() { + console.log("should have tab width 3"); +} diff --git a/tests_integration/cli/config/package/file.ts b/tests_integration/cli/config/package/file.ts new file mode 100644 index 00000000..77097eff --- /dev/null +++ b/tests_integration/cli/config/package/file.ts @@ -0,0 +1,3 @@ +function g() { + console.log("should have tab width 5 because it has .ts extension"); +} diff --git a/tests_integration/cli/config/package/package.json b/tests_integration/cli/config/package/package.json new file mode 100644 index 00000000..417276f1 --- /dev/null +++ b/tests_integration/cli/config/package/package.json @@ -0,0 +1,15 @@ +{ + "name": "my-package", + "version": "9000", + "prettier": { + "tabWidth": 3, + "overrides": [ + { + "files": "*.ts", + "options": { + "tabWidth": 5 + } + } + ] + } +} diff --git a/tests_integration/cli/config/rc-json/.prettierrc b/tests_integration/cli/config/rc-json/.prettierrc new file mode 100644 index 00000000..1edab64d --- /dev/null +++ b/tests_integration/cli/config/rc-json/.prettierrc @@ -0,0 +1,4 @@ +{ + "trailingComma": "all", + "singleQuote": true +} diff --git a/tests_integration/cli/config/rc-json/file.js b/tests_integration/cli/config/rc-json/file.js new file mode 100644 index 00000000..f530b344 --- /dev/null +++ b/tests_integration/cli/config/rc-json/file.js @@ -0,0 +1,9 @@ +/* eslint-disable */ + +function f() { + console.log.apply(null, [ + "this file", + "should have trailing comma", + "and single quotes", + ]); +} diff --git a/yarn.lock b/yarn.lock index 1a8849ed..f4ea346c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1004,6 +1004,18 @@ core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" +cosmiconfig@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-2.1.3.tgz#952771eb0dddc1cb3fa2f6fbe51a522e93b3ee0a" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.4.3" + minimist "^1.2.0" + object-assign "^4.1.0" + os-homedir "^1.0.1" + parse-json "^2.2.0" + require-from-string "^1.1.0" + create-ecdh@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.0.tgz#888c723596cdf7612f6498233eebd7a35301737d" @@ -1083,6 +1095,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +dashify@0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dashify/-/dashify-0.2.2.tgz#6a07415a01c91faf4a32e38d9dfba71f61cb20fe" + date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" @@ -1892,6 +1908,10 @@ is-ci@^1.0.10: dependencies: ci-info "^1.0.0" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + is-dotfile@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" @@ -2311,7 +2331,7 @@ js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@^3.7.0, js-yaml@^3.8.4: +js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.8.4: version "3.8.4" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" dependencies: @@ -2588,7 +2608,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -2767,7 +2787,7 @@ os-browserify@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.2.1.tgz#63fc4ccee5d2d7763d26bbf8601078e6c2e0044f" -os-homedir@^1.0.0: +os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -3228,6 +3248,10 @@ require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" +require-from-string@^1.1.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" + require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"