From cdbcc6eb31e2e5344bb92a0576c7929401b76024 Mon Sep 17 00:00:00 2001 From: Charlotte Vermandel Date: Sat, 22 May 2021 11:28:01 +0200 Subject: [PATCH] Lint code --- .gitignore | 4 + .prettierignore | 2 + .prettierrc.json | 1 + package-lock.json | 57 ---------- package.json | 4 + src/cli.js | 16 ++- src/combine-json.js | 255 ++++++++++++++++++++++---------------------- src/file_utils.js | 45 ++++---- src/index.js | 5 +- src/slow-combine.js | 121 ++++++++++----------- yarn.lock | 47 ++++++++ 11 files changed, 276 insertions(+), 281 deletions(-) create mode 100644 .prettierignore create mode 100644 .prettierrc.json delete mode 100644 package-lock.json create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore index 14b0db6..ed07491 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,7 @@ lerna-debug.log Thumbs.db combined.json + +# Ignore artifacts: +build +coverage diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..5339fab --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +combined.json +/misc diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1 @@ +{} diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index df727fe..0000000 --- a/package-lock.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "combine-json", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "requires": { - "has-flag": "^4.0.0" - } - } - } -} diff --git a/package.json b/package.json index b868577..320aa0a 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,15 @@ "bin": "./src/cli.js", "scripts": { "link": "npm link", + "lint": "prettier --write .", "test": "./src/cli.js misc" }, "author": "", "license": "ISC", "dependencies": { "chalk": "^3.0.0" + }, + "devDependencies": { + "prettier": "2.3.0" } } diff --git a/src/cli.js b/src/cli.js index 5c0f697..6bbaf1e 100755 --- a/src/cli.js +++ b/src/cli.js @@ -2,17 +2,15 @@ const combineJson = require('./combine-json'); (async () => { - console.log(combineJson); + console.log(combineJson); try { if (process.argv.length === 2) { - console.log(chalk.red('Error: Missing path argument')); + console.log(chalk.red('Error: Missing path argument')); + } else { + await combineJson(process.argv[2], process.argv[3]); } - else { - await combineJson(process.argv[2], process.argv[3]) - } - } - catch(e) { + } catch (e) { console.error(e); - throw(e) + throw e; } -})() +})(); diff --git a/src/combine-json.js b/src/combine-json.js index b662e94..0ff52a7 100755 --- a/src/combine-json.js +++ b/src/combine-json.js @@ -1,152 +1,153 @@ const fs = require('fs'); const chalk = require('chalk'); -const path = require('path') +const path = require('path'); const { - inputFilesAndDir, - resolveOutputFilePath, - filterNonJson - } = require('./file_utils') + inputFilesAndDir, + resolveOutputFilePath, + filterNonJson, +} = require('./file_utils'); function findLastBracket(filePath, fd, buffer, position) { - let charRed = fs.readSync(fd, buffer, 0, 8, position); - let array = [...buffer].map(char => String.fromCharCode(char)); - let bracket = array.indexOf("]"); - if (charRed === 0) return null; - if (bracket > -1) return position + bracket + 1; - fs.closeSync(fd) - fd = fs.openSync(filePath); - return getLastBracket(filePath, fd, position - 8) + let charRed = fs.readSync(fd, buffer, 0, 8, position); + let array = [...buffer].map((char) => String.fromCharCode(char)); + let bracket = array.indexOf(']'); + if (charRed === 0) return null; + if (bracket > -1) return position + bracket + 1; + fs.closeSync(fd); + fd = fs.openSync(filePath); + return getLastBracket(filePath, fd, position - 8); } function getLastBracket(filePath, fd, position) { - let buffer = new Int8Array(8); - return findLastBracket(filePath, fd, buffer, position); + let buffer = new Int8Array(8); + return findLastBracket(filePath, fd, buffer, position); } function findFirstBracketType(fileFd, buffer, position) { - let charRed = fs.readSync(fileFd, buffer, 0, 8) - let array = [...buffer].map(char => String.fromCharCode(char)); - let curly = array.indexOf("{"); - let bracket = array.indexOf("["); - if (charRed === 0) return null; - if ((curly < bracket || bracket === -1) && curly > -1) return { - type: "{", - pos: position + curly - } - if ((bracket < curly || curly === -1) && bracket > -1) return { - type: "[", - pos: position + bracket - } - return findFirstBracketType(fileFd, buffer, position + 8) + let charRed = fs.readSync(fileFd, buffer, 0, 8); + let array = [...buffer].map((char) => String.fromCharCode(char)); + let curly = array.indexOf('{'); + let bracket = array.indexOf('['); + if (charRed === 0) return null; + if ((curly < bracket || bracket === -1) && curly > -1) + return { + type: '{', + pos: position + curly, + }; + if ((bracket < curly || curly === -1) && bracket > -1) + return { + type: '[', + pos: position + bracket, + }; + return findFirstBracketType(fileFd, buffer, position + 8); } function getFirstBracketType(fd) { - let buffer = new Int8Array(8); - return findFirstBracketType(fd, buffer, 0); + let buffer = new Int8Array(8); + return findFirstBracketType(fd, buffer, 0); } -async function combine({inputFiles, inputDirPath, outputFilePath}) { - fs.writeFileSync(outputFilePath, "["); // start of new file - const numberOfFiles = inputFiles.length - numberOfFiles.map(( fileName, index) => { - let inputFile = `${inputDirPath}${fileName}`; - - // open destination file for appending - const writeStreamPath = fs.createWriteStream(outputFilePath, { - flags: 'a' +async function combine({ inputFiles, inputDirPath, outputFilePath }) { + fs.writeFileSync(outputFilePath, '['); // start of new file + const numberOfFiles = inputFiles.length; + numberOfFiles.map((fileName, index) => { + let inputFile = `${inputDirPath}${fileName}`; + + // open destination file for appending + const writeStreamPath = fs.createWriteStream(outputFilePath, { + flags: 'a', + }); + + let start = isArray ? firstBracketType.pos + 1 : firstBracketType.pos; + }); + for (let index = 0; index < numberOfFiles; index++) { + let file = inputFiles[index]; + let inputFile = `${inputDirPath}${file}`; + + const fd = fs.openSync(`${inputDirPath}${file}`); + let firstBracketType = getFirstBracketType(fd); + let lastBracket = undefined; + + if (firstBracketType) { + let isArray = firstBracketType.type === '['; + if (isArray) { + let stats = fs.statSync(inputFile); + lastBracket = getLastBracket(inputFile, fd, stats.size - 8) - 2; + } + // open destination file for appending + var w = fs.createWriteStream(outputFilePath, { + flags: 'a', + }); + // open source file for reading + let start = isArray ? firstBracketType.pos + 1 : firstBracketType.pos; + var r = fs.createReadStream(inputFile, { + start, + end: lastBracket, + }); + + r.pipe(w); + const combineFiles = new Promise(function (resolve, reject) { + w.on('close', function () { + resolve('foo'); + console.log('done writing'); }); + }); + await combineFiles; - let start = (isArray) ? firstBracketType.pos + 1 : firstBracketType.pos; - - }) - for (let index = 0; index < numberOfFiles; index++) { - let file = inputFiles[index]; - let inputFile = `${inputDirPath}${file}`; - - const fd = fs.openSync(`${inputDirPath}${file}`); - let firstBracketType = getFirstBracketType(fd); - let lastBracket = undefined; - - - if (firstBracketType) { - let isArray = firstBracketType.type === '['; - if (isArray) { - let stats = fs.statSync(inputFile) - lastBracket = getLastBracket(inputFile, fd, stats.size - 8) - 2; - } - // open destination file for appending - var w = fs.createWriteStream(outputFilePath, { - flags: 'a' - }); - // open source file for reading - let start = (isArray) ? firstBracketType.pos + 1 : firstBracketType.pos; - var r = fs.createReadStream(inputFile, { - start, - end: lastBracket - }); - - r.pipe(w); - const combineFiles = new Promise(function(resolve, reject) { - w.on('close', function() { - resolve('foo'); - console.log("done writing"); - }); - }); - await combineFiles; - + let last = index === numberOfFiles - 1; - let last = (index === numberOfFiles - 1); - - if (!last) { - let coma = path.resolve(__dirname, '../assets/coma') - let comaWrite = fs.createWriteStream(outputFilePath, { - flags: 'a' - }); - let comaRead = fs.createReadStream(coma); - comaRead.pipe(comaWrite); - const addComa = new Promise(function(resolve, reject) { - comaWrite.on('close', function() { - resolve('foo'); - console.log("done writing coma"); - }); - }); - await addComa - } else { - let closingBracket = path.resolve(__dirname, '../assets/closing_bracket'); - let closingBracketWrite = fs.createWriteStream(outputFilePath, { - flags: 'a' - }); - let closingBracketRead = fs.createReadStream(closingBracket); - closingBracketRead.pipe(closingBracketWrite); - const addclosingBracket = new Promise(function(resolve, reject) { - closingBracketWrite.on('close', function() { - resolve('foo'); - console.log("done writing closingBracket"); - }); - }); - await addclosingBracket - } - console.log(chalk.green( - 'file: ' + - chalk.blue.underline.bold(file) + - ` has been added! last : ${last}, index: ${index}, numberOfFiles: ${numberOfFiles}` - )) - } + if (!last) { + let coma = path.resolve(__dirname, '../assets/coma'); + let comaWrite = fs.createWriteStream(outputFilePath, { + flags: 'a', + }); + let comaRead = fs.createReadStream(coma); + comaRead.pipe(comaWrite); + const addComa = new Promise(function (resolve, reject) { + comaWrite.on('close', function () { + resolve('foo'); + console.log('done writing coma'); + }); + }); + await addComa; + } else { + let closingBracket = path.resolve( + __dirname, + '../assets/closing_bracket' + ); + let closingBracketWrite = fs.createWriteStream(outputFilePath, { + flags: 'a', + }); + let closingBracketRead = fs.createReadStream(closingBracket); + closingBracketRead.pipe(closingBracketWrite); + const addclosingBracket = new Promise(function (resolve, reject) { + closingBracketWrite.on('close', function () { + resolve('foo'); + console.log('done writing closingBracket'); + }); + }); + await addclosingBracket; + } + console.log( + chalk.green( + 'file: ' + + chalk.blue.underline.bold(file) + + ` has been added! last : ${last}, index: ${index}, numberOfFiles: ${numberOfFiles}` + ) + ); } + } } - async function combineJson(inputDir, outputFile = undefined) { - try { - const { inputDirPath, filesName } = inputFilesAndDir({ inputDir }) - const outputFilePath = resolveOutputFilePath({ fileName: outputFile }) - const inputFiles = filterNonJson({ filesName }); - await combine({inputFiles, inputDirPath, outputFilePath}) - }catch(e) { - throw(e) - } + try { + const { inputDirPath, filesName } = inputFilesAndDir({ inputDir }); + const outputFilePath = resolveOutputFilePath({ fileName: outputFile }); + const inputFiles = filterNonJson({ filesName }); + await combine({ inputFiles, inputDirPath, outputFilePath }); + } catch (e) { + throw e; + } } -module.exports = combineJson - - +module.exports = combineJson; diff --git a/src/file_utils.js b/src/file_utils.js index 3d697b1..6a7ab5b 100644 --- a/src/file_utils.js +++ b/src/file_utils.js @@ -1,11 +1,12 @@ -const path = require('path') -const fs = require('fs') +const path = require('path'); +const fs = require('fs'); function resolveDir({ dir }) { dir = path.resolve(dir); - if (!fs.existsSync(dir)) { // test for Fully Qualified path - console.log(`Error: ${dir} no such named directory`); - process.exit() + if (!fs.existsSync(dir)) { + // test for Fully Qualified path + console.log(`Error: ${dir} no such named directory`); + process.exit(); } return dir; } @@ -16,33 +17,33 @@ function outputFile({ dirName, fileName = undefined }) { } function inputFilesAndDir({ inputDir }) { - const resolvedDir = resolveDir({ dir: inputDir}) - const inputDirPath = resolvedDir + ((resolvedDir[resolvedDir.length - 1] === '/') ? '' : '/') // add slash at the end of the dir if it is not there yet - const filesName = fs.readdirSync(inputDirPath) // read all files names in dir + const resolvedDir = resolveDir({ dir: inputDir }); + const inputDirPath = + resolvedDir + (resolvedDir[resolvedDir.length - 1] === '/' ? '' : '/'); // add slash at the end of the dir if it is not there yet + const filesName = fs.readdirSync(inputDirPath); // read all files names in dir return { - inputDirPath, - filesName - } + inputDirPath, + filesName, + }; } function resolveOutputFilePath({ fileName }) { const workingDir = process.cwd(); - const outputFilePath = outputFile({ dirName: workingDir, fileName}); - createFileIfNotExist(outputFilePath) - return outputFilePath + const outputFilePath = outputFile({ dirName: workingDir, fileName }); + createFileIfNotExist(outputFilePath); + return outputFilePath; } - function createFileIfNotExist({ file }) { if (fs.existsSync(file)) { - fs.writeFileSync(file, ""); + fs.writeFileSync(file, ''); } } -function filterNonJson({ filesName }){ - return filesName.reduce((acc, file)=>{ - if (path.extname(file)=== '.json') return [...acc, file]; - return acc; +function filterNonJson({ filesName }) { + return filesName.reduce((acc, file) => { + if (path.extname(file) === '.json') return [...acc, file]; + return acc; }, []); } @@ -52,5 +53,5 @@ module.exports = { inputFilesAndDir, resolveOutputFilePath, createFileIfNotExist, - filterNonJson -} + filterNonJson, +}; diff --git a/src/index.js b/src/index.js index 28666db..e893566 100644 --- a/src/index.js +++ b/src/index.js @@ -1,4 +1,3 @@ -const combineJson = require('./combine-json') +const combineJson = require('./combine-json'); - -module.exports = combineJson +module.exports = combineJson; diff --git a/src/slow-combine.js b/src/slow-combine.js index 26e0474..8999c6d 100644 --- a/src/slow-combine.js +++ b/src/slow-combine.js @@ -1,83 +1,78 @@ #!/usr/bin/env node const fs = require('fs'); const chalk = require('chalk'); -const path = require('path') +const path = require('path'); function outputPath(outputDir) { - let fileName = (process.argv[3]) ? process.argv[3] : 'combined.json'; - return `${outputDir}/${fileName}`; + let fileName = process.argv[3] ? process.argv[3] : 'combined.json'; + return `${outputDir}/${fileName}`; } function createIfNotExist(file) { - if (fs.existsSync(file)) { - fs.writeFileSync(file, ""); - } + if (fs.existsSync(file)) { + fs.writeFileSync(file, ''); + } } -function listOfJsonFiles(files){ - return files.reduce((acc, file)=>{ - if (path.extname(file)=== '.json') return [...acc, file]; - return acc; - }, []); +function listOfJsonFiles(files) { + return files.reduce((acc, file) => { + if (path.extname(file) === '.json') return [...acc, file]; + return acc; + }, []); } - async function combineJson(files, dir, outputDir) { - - let outputFile = outputPath(outputDir); - let filePath = dir + ((dir[dir.length - 1] === '/') ? '' : '/') // add slash at the end of the dir if it is not there yet - createIfNotExist(outputFile) - - - fs.writeFileSync(outputFile, "["); // start of new file - const jsonFiles = listOfJsonFiles(files); - const numberOfFiles = jsonFiles.length - - for (let index = 0; index < numberOfFiles; index++) { - let file = jsonFiles[index]; - - let inputFile = `${filePath}${file}`; - let content = require(inputFile); - content = JSON.stringify(content); - if (Array.isArray(content)) content = content.substr(1, content.length - 2); - let last = (index === numberOfFiles - 1); - fs.appendFileSync(outputFile, `${content}${(last)? "" : ","}\n`); - console.log(chalk.green( - 'file: ' + - chalk.blue.underline.bold(file) + - ` has been added! last : ${last}, index: ${index}, numberOfFiles: ${numberOfFiles}` - )) - - } - fs.appendFileSync(outputFile, `]`); + let outputFile = outputPath(outputDir); + let filePath = dir + (dir[dir.length - 1] === '/' ? '' : '/'); // add slash at the end of the dir if it is not there yet + createIfNotExist(outputFile); + + fs.writeFileSync(outputFile, '['); // start of new file + const jsonFiles = listOfJsonFiles(files); + const numberOfFiles = jsonFiles.length; + + for (let index = 0; index < numberOfFiles; index++) { + let file = jsonFiles[index]; + + let inputFile = `${filePath}${file}`; + let content = require(inputFile); + content = JSON.stringify(content); + if (Array.isArray(content)) content = content.substr(1, content.length - 2); + let last = index === numberOfFiles - 1; + fs.appendFileSync(outputFile, `${content}${last ? '' : ','}\n`); + console.log( + chalk.green( + 'file: ' + + chalk.blue.underline.bold(file) + + ` has been added! last : ${last}, index: ${index}, numberOfFiles: ${numberOfFiles}` + ) + ); + } + fs.appendFileSync(outputFile, `]`); } - function determineDir(dir) { - dir = path.resolve(dir); - if (!fs.existsSync(dir)) { // test for Fully Qualified path - console.log(`Error: ${process.argv[2]} no such named directory`); - process.exit() - } - return dir; + dir = path.resolve(dir); + if (!fs.existsSync(dir)) { + // test for Fully Qualified path + console.log(`Error: ${process.argv[2]} no such named directory`); + process.exit(); + } + return dir; } (async () => { - if (process.argv.length === 2) { - console.log(chalk.red('Error: Missing path argument')); + if (process.argv.length === 2) { + console.log(chalk.red('Error: Missing path argument')); + } else { + try { + let dir = determineDir(process.argv[2]); + console.log({ dir }); + let outputDir = process.cwd(); + let files = fs.readdirSync(dir); + + await combineJson(files, dir, outputDir); + } catch (e) { + throw e; } - else { - try { - let dir = determineDir(process.argv[2]) - console.log({ dir }); - let outputDir = process.cwd(); - let files = fs.readdirSync(dir) - - await combineJson(files, dir, outputDir) - }catch(e) { - throw(e) - } - } -})() - - + } +})(); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..5219a7b --- /dev/null +++ b/yarn.lock @@ -0,0 +1,47 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +prettier@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18" + integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0"