diff --git a/packages/utils/package.json b/packages/utils/package.json index 7c8d2bacc..0222e2463 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -29,7 +29,15 @@ "@babel/runtime": "^7.13.9", "clsx": "^1.0.4", "focus-lock": "^0.8.0", - "react-merge-refs": "^1.0.0" + "react-merge-refs": "^1.0.0", + "brotli": "^1.3.3", + "commently": "6.18.3", + "dasherize": "2.0.0", + "get-monorepo-packages": "1.2.0", + "gitlog": "4.0.8", + "markdown-table": "2.0.0", + "node-fetch": "2", + "table": "^6.8.1" }, "peerDependencies": { "@types/react": "*", diff --git a/packages/utils/src/utils/logBundleSize.mjs b/packages/utils/src/utils/logBundleSize.mjs new file mode 100644 index 000000000..ae46cb01a --- /dev/null +++ b/packages/utils/src/utils/logBundleSize.mjs @@ -0,0 +1,483 @@ +// const process = require('process'); +import fs from 'fs'; +import path from 'path'; +import brotli from 'brotli'; +import { once } from 'events'; +import fetch from 'node-fetch'; +import dasherize from 'dasherize'; +import { table } from 'table'; +import markdownTable from 'markdown-table'; +import Commently from 'commently'; +import getPackages from 'get-monorepo-packages'; +import { execSync } from 'child_process'; +import gitlog from 'gitlog'; + +const componentsDir = `${process.cwd()}/components`; +let updatedComponents = []; +let pkgVersion = ''; +let repo = 'qbds'; + +const tableHeader = ['Component', 'Uncompressed', 'Compressed']; + +/** + * load the production Files + */ +const loadProdFiles = async (prodVersion, fileName) => { + const sizeData = []; + + if (prodVersion) { + for (const component of updatedComponents) { + const prodURL = `https://uxfabric.intuitcdn.net/@${repo}/${dasherize( + component + )}/${prodVersion}/${fileName}`; + + const distPath = `${componentsDir}/${component}/dist`; + + // eslint-disable-next-line no-await-in-loop + const res = await fetch(prodURL); + + if (res.status === 200) { + try { + const stream = res.body.pipe( + fs.createWriteStream(`${distPath}/${fileName}.prod`) + ); + + // eslint-disable-next-line no-await-in-loop + await once(stream, 'finish'); + + const uncompressedFileStats = fs.statSync( + `${distPath}/${fileName}.prod` + ); + const compressedFile = brotli.compress( + fs.readFileSync(`${distPath}/${fileName}.prod`) + ); + + fs.writeFileSync(`${distPath}/${fileName}.prod.br`, compressedFile); + const compressedFileStats = fs.statSync( + `${distPath}/${fileName}.prod.br` + ); + + sizeData.push({ + uncompressed: uncompressedFileStats.size, + compressed: compressedFileStats.size, + component + }); + + console.log(`${component} prod file done: ${prodURL}`); + } catch (e) { + console.log('prod: general error:', e); + } + } else { + console.log(`prod: error: ${component}: ${prodURL}`); + sizeData.push({ + uncompressed: 0, + compressed: 0, + component + }); + } + } + } + + return sizeData; +}; + +/** + * load the canary Files + */ +const loadTheCanaryFiles = async (prId) => { + const sizeData = []; + + if (prId) { + for (const component of updatedComponents) { + const canaryURL = `https://uxfabric.intuitcdn.net/components/design-systems/${repo}/canary/${prId}/${component}/ids.js`; + const distPath = `${componentsDir}/${component}/dist`; + + // eslint-disable-next-line no-await-in-loop + const res = await fetch(canaryURL); + if (res.status === 200) { + const stream = res.body.pipe( + fs.createWriteStream(`${distPath}/pr-ids.js`) + ); + + // eslint-disable-next-line no-await-in-loop + await once(stream, 'finish'); + + const uncompressedFileStats = fs.statSync(`${distPath}/pr-ids.js`); + const compressedFile = brotli.compress( + fs.readFileSync(`${distPath}/pr-ids.js`) + ); + + fs.writeFileSync(`${distPath}/pr-ids.js.br`, compressedFile); + const compressedFileStats = fs.statSync(`${distPath}/pr-ids.js.br`); + + sizeData.push({ + uncompressed: uncompressedFileStats.size, + compressed: compressedFileStats.size, + component + }); + + console.log(`${component} canary file done: ${canaryURL}`); + } else { + sizeData.push({ + uncompressed: 0, + compressed: 0, + component + }); + } + } + } + + return sizeData; +}; + +/** + * get the css size data + */ +const cssSizeData = () => { + const sizeData = []; + console.log('\nloading css data'); + console.log('----------------'); + + for (const component of updatedComponents) { + const distPath = `${componentsDir}/${component}/dist`; + + try { + const uncompressedFileStats = fs.statSync(`${distPath}/main.css`); + + const compressedFile = brotli.compress( + fs.readFileSync(`${distPath}/main.css`) + ); + fs.writeFileSync(`${distPath}/main.css.br`, compressedFile); + const compressedFileStats = fs.statSync(`${distPath}/main.css.br`); + + sizeData.push({ + uncompressed: uncompressedFileStats.size, + compressed: compressedFileStats.size, + component + }); + } catch (e) { + console.log('css file not found for ', component); + + sizeData.push({ + uncompressed: 0, + compressed: 0, + component + }); + } + + } + + return sizeData; +}; + +/** + * print the size data + */ +const printTheSizeData = (sizeData, title) => { + const data = sizeData.reduce((acc, curr) => { + acc[curr.component] = curr; + return acc; + }, {}); + + let compressedTotal = 0; + let uncompressedTotal = 0; + + const tableData = [[title, '', ''], tableHeader]; + + Object.keys(data).forEach((key) => { + const { uncompressed, compressed } = data[key]; + + tableData.push([ + key, + `${uncompressed / 1000} kB`, + `${compressed / 1000} kB` + ]); + + compressedTotal += compressed; + uncompressedTotal += uncompressed; + }); + + tableData.push([ + 'Total', + `${uncompressedTotal / 1000} kB`, + `${compressedTotal / 1000} kB` + ]); + console.log(table(tableData)); +}; + +/** + * print the difference between prod and canary + */ +const printTheDifference = (prodData, prData, prodDataCss, prDataCss) => { + const prodObjectIds = prodData.reduce((acc, curr) => { + acc[curr.component] = curr; + return acc; + }, {}); + + const prObjectIds = prData.reduce((acc, curr) => { + acc[curr.component] = curr; + return acc; + }, {}); + + const prodObjectCss = prodDataCss.reduce((acc, curr) => { + acc[curr.component] = curr; + return acc; + }, {}); + + const prObjectCss = prDataCss.reduce((acc, curr) => { + acc[curr.component] = curr; + return acc; + }, {}); + + const tableData = [ + [ + '', + 'ids.js %', + '\u{1F5DC} - ids.js %', + 'main.css %', + '\u{1F5DC} - main.css %', + 'token/theme %', + ] + ]; + + Object.keys(prObjectIds).forEach((key) => { + const { uncompressed: uncompressedPrIds, compressed: compressedPrIds } = prObjectIds[key]; + + const uncompressedProd = prodObjectIds[key]?.uncompressed ? prodObjectIds[key].uncompressed : 0; + const compressedProd = prodObjectIds[key]?.compressed ? prodObjectIds[key].compressed : 0; + + const uncompressedPrCss = prObjectCss[key]?.uncompressed ? prObjectCss[key].uncompressed : 0; + const uncompressedProdCss = prodObjectCss[key]?.uncompressed ? prodObjectCss[key].uncompressed : 0; + + const compressedPrCss = prObjectCss[key]?.compressed ? prObjectCss[key].compressed : 0; + const compressedProdCss = prodObjectCss[key]?.compressed ? prodObjectCss[key].compressed : 0; + + tableData.push([ + key, + `${(100 - (uncompressedProd / uncompressedPrIds) * 100).toFixed(2)} %`, + `${(100 - (uncompressedProdCss / uncompressedPrCss) * 100).toFixed(2)} %`, + `${(100 - (compressedProd / compressedPrIds) * 100).toFixed(2)} %`, + `${(100 - (compressedProdCss / compressedPrCss) * 100).toFixed(2)} %`, + 'TBD' + ]); + }); + + console.log(`BUNDLE SIZE DIFFERENCE:\n`); + console.log(table(tableData)); + + return tableData; +}; + +/** + * helper to calculate download time + */ +const calculateDownloadTime = (size) => { + const downloadSpeeds = []; + const threeGspeed = 50; + const fourGspeed = 875; + + if(size) { + const threeG = (size / 1000 / threeGspeed) >= 1 ? `${(size / 1000 / threeGspeed).toFixed(2)} s` : `${(size / 1000 / threeGspeed * 1000).toFixed(2)} ms`; + const fourG = (size / 1000 / fourGspeed) >= 1 ? `${(size / 1000 / fourGspeed).toFixed(2)} s` : `${(size / 1000 / fourGspeed * 1000).toFixed(2)} ms`; + downloadSpeeds.push(threeG); + downloadSpeeds.push(fourG); + } + + return downloadSpeeds; +} + +/** + * get the download times for PR and Prod + */ +const getDownloadTimes = (prData) => { + const prObjectIds = prData.reduce((acc, curr) => { + acc[curr.component] = curr; + return acc; + }, {}); + + const tableData = [ + [ + '', + 'PR: 3G', + 'PR: 4G', + 'PR: 3G - \u{1F5DC}', + 'PR: 4G - \u{1F5DC}', + ] + ]; + + Object.keys(prObjectIds).forEach((key) => { + const { uncompressed, compressed } = prObjectIds[key]; + + tableData.push([ + key, + ...(calculateDownloadTime(uncompressed)), + ...(calculateDownloadTime(compressed)) + ]); + }); + + console.log(`DOWNLOAD TIMES:\n`); + console.log(table(tableData)); + return tableData; +} + +/** Report the results and success/failure. */ +const reportResultsToPR = async (tableOutput, downloadTimesTable) => { + // eslint-disable-next-line no-console + console.log(tableOutput); + + if (process.env.GH_TOKEN) { + // eslint-disable-next-line new-cap + const commenter = new Commently.default({ + title: 'Component Bundle Size Analysis', + key: 'bundle-size-analysis', + // Jenkin doesn't support owner/repo or any slug so a user must + // provide these values themselves + owner: process.env.OWNER, + repo: process.env.REPO, + useHistory: false + }); + + try { + const comment = `${markdownTable(tableOutput)}\n\nDOWNLOAD TIMES:\n${markdownTable(downloadTimesTable)}\n\nNote: 3G = 50kB/s, 4G = 875kB/s`; + await commenter.autoComment(comment); + } catch (error) { + console.error(error); + } + } +}; + +/** Determine which packages have git changes. */ +function getChangedPackages(mergeBase) { + const all = getPackages('.'); + + try { + // this assumes on master whereas we want the last tag + const packages = execSync('lerna changed --ndjson --toposort', { + stdio: ['pipe'], + }) + .toString() + .trim() + .split('\n'); + const lastTag = execSync('git describe --tags --abbrev=0', { + encoding: 'utf8', + }); + // Use commit-ish hash instead of the last tag if provided + const hash = mergeBase?.trim(); + const changedFiles = gitlog.default({ + repo: process.cwd(), + number: Number.MAX_SAFE_INTEGER, + fields: ['hash', 'authorName', 'authorEmail', 'rawBody'], + execOptions: { maxBuffer: Infinity }, + branch: `${hash || lastTag.trim()}..HEAD`, + }) + .reduce((files, commit) => [...files, ...commit.files], []) + .map((file) => path.resolve(path.join(process.cwd(), file))); + + const changedDeps = []; + + return packages + .map((p) => JSON.parse(p)) + .filter((json) => + changedFiles.some((file) => { + const hasChangedFiles = file.includes(String(json.location)); + + if (hasChangedFiles) { + changedDeps.push(String(json.name)); + } else { + // Check if a dep has changed too + const packageJson = JSON.parse( + fs.readFileSync(path.join(String(json.location), 'package.json'), { + encoding: 'utf-8', + }) + ); + const hasChangedDep = Object.keys(packageJson).some((dep) => + changedDeps.includes(dep) + ); + + if (hasChangedDep) { + changedDeps.push(String(json.name)); + return hasChangedDep; + } + } + + return hasChangedFiles; + }) + ) + .map((json) => { + return { location: json.location, package: { ...json } }; + }); + } catch (error) { + if (!error.message.includes('fatal: ambiguous argument')) { + throw error; + } + + return all; + } +} + +/** Determine which packages have git changes. */ +function setInitialValues(changedPackages) { + if(changedPackages && changedPackages.length > 0) { + pkgVersion = changedPackages[0].package.version; + updatedComponents = changedPackages.map((pkg) => { + const words = pkg.package.location.split('/'); + const pkgName = words[words.length - 1]; + return pkgName; + }); + + console.log('changedPackages: ', updatedComponents); + console.log('version: ', pkgVersion); + } +} + +/** + * get the size data + */ +const getTheSizeData = async (prId, prodVersion) => { + console.log('\nloading ids.js data'); + console.log('----------------'); + + const localData = await loadTheCanaryFiles(prId); + const prodData = await loadProdFiles(prodVersion, 'ids.js'); + + const cssLocalData = cssSizeData(); + const cssProdData = await loadProdFiles(prodVersion, 'main.css'); + + console.log('----------------\n\n'); + + printTheSizeData(localData, 'Canary Data'); + printTheSizeData(prodData, 'Prod Data'); + + printTheSizeData(cssLocalData, 'CSS PR Data'); + printTheSizeData(cssProdData, 'CSS Prod Data'); + + const tableOutput = printTheDifference( + prodData, + localData, + cssProdData, + cssLocalData + ); + + const downloadTimesTable = getDownloadTimes(localData); + + if (process.env.GH_TOKEN && process.env.OWNER && process.env.REPO) { + // print the results to the PR + await reportResultsToPR(tableOutput, downloadTimesTable); + } +}; + + +// get the PR id from the command line +const args = process.argv.slice(2); +if (args.length > 0 && args[0]) { + const prId = args[0]; + repo = (args[1] && args[1] === 'ids-web') ? 'ids-ts' : repo; + + console.log('prId: ', prId); + console.log('repo: ', repo); + + const chgPkgs = getChangedPackages(); + + setInitialValues(chgPkgs); + getTheSizeData(prId, pkgVersion); +} diff --git a/yarn.lock b/yarn.lock index 4dc97822a..6178a355c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1915,7 +1915,7 @@ sketchapp-json-plugin "^0.1.2" "@design-systems/build@link:plugins/build": - version "4.15.0" + version "4.15.2" dependencies: "@babel/code-frame" "^7.12.13" "@babel/core" "^7.13.8" @@ -1957,7 +1957,7 @@ typescript "4.2.2" "@design-systems/bundle@link:plugins/bundle": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/build" "link:plugins/build" "@design-systems/cli-utils" "link:packages/cli-utils" @@ -1973,7 +1973,7 @@ webpack "4.44.1" "@design-systems/clean@link:plugins/clean": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/cli-utils" "link:packages/cli-utils" "@design-systems/plugin" "link:packages/plugin" @@ -1982,7 +1982,7 @@ tslib "2.0.1" "@design-systems/cli-utils@link:packages/cli-utils": - version "4.15.0" + version "4.15.2" dependencies: find-up "5.0.0" npm-which "3.0.1" @@ -1992,7 +1992,7 @@ webpack "4.44.1" "@design-systems/cli@link:packages/cli": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/cli-utils" "link:packages/cli-utils" "@design-systems/core" "link:packages/core" @@ -2007,7 +2007,7 @@ update-check "1.5.4" "@design-systems/core@link:packages/core": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/build" "link:plugins/build" "@design-systems/bundle" "link:plugins/bundle" @@ -2027,7 +2027,7 @@ tslib "2.0.1" "@design-systems/create-command@link:plugins/create-command": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/cli-utils" "link:packages/cli-utils" "@design-systems/create" "link:packages/create" @@ -2046,10 +2046,10 @@ tslib "2.0.1" "@design-systems/create@link:packages/create": - version "4.15.0" + version "4.15.2" "@design-systems/dev@link:plugins/dev": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/cli-utils" "link:packages/cli-utils" "@design-systems/plugin" "link:packages/plugin" @@ -2060,7 +2060,7 @@ tslib "2.0.1" "@design-systems/eslint-config@link:packages/eslint-config": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/cli-utils" "link:packages/cli-utils" "@kendallgassner/eslint-plugin-package-json" "0.2.1" @@ -2085,7 +2085,7 @@ tslib "2.0.1" "@design-systems/lint@link:plugins/lint": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/cli-utils" "link:packages/cli-utils" "@design-systems/eslint-config" "link:packages/eslint-config" @@ -2102,7 +2102,7 @@ tslib "2.0.1" "@design-systems/load-config@link:packages/load-config": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/core" "link:packages/core" "@design-systems/plugin" "link:packages/plugin" @@ -2116,7 +2116,7 @@ tslib "2.0.1" "@design-systems/playroom@link:plugins/playroom": - version "4.15.0" + version "4.15.2" dependencies: "@babel/core" "^7.13.8" "@babel/register" "^7.13.8" @@ -2136,14 +2136,14 @@ webpack "4.44.1" "@design-systems/plugin@link:packages/plugin": - version "4.15.0" + version "4.15.2" dependencies: command-line-application "0.10.1" tslib "2.0.1" utility-types "3.10.0" "@design-systems/proof@link:plugins/proof": - version "4.15.0" + version "4.15.2" dependencies: "@babel/core" "^7.13.8" "@babel/plugin-transform-runtime" "^7.13.9" @@ -2161,7 +2161,7 @@ tslib "2.0.1" "@design-systems/size@link:plugins/size": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/cli-utils" "link:packages/cli-utils" "@design-systems/plugin" "link:packages/plugin" @@ -2192,7 +2192,7 @@ webpack-sources "1.4.3" "@design-systems/storybook@link:plugins/storybook": - version "4.15.0" + version "4.15.2" dependencies: "@alisowski/storybook-addon-notes" "^6.0.1" "@babel/core" "^7.13.8" @@ -2226,7 +2226,7 @@ webpack-filter-warnings-plugin "1.2.1" "@design-systems/stylelint-config@link:packages/stylelint-config": - version "4.15.0" + version "4.15.2" dependencies: stylelint-a11y "1.2.3" stylelint-config-css-modules "2.2.0" @@ -2240,7 +2240,7 @@ tslib "2.0.1" "@design-systems/test@link:plugins/test": - version "4.15.0" + version "4.15.2" dependencies: "@babel/core" "^7.13.8" "@design-systems/build" "link:plugins/build" @@ -2260,7 +2260,7 @@ tslib "2.0.1" "@design-systems/update@link:plugins/update": - version "4.15.0" + version "4.15.2" dependencies: "@design-systems/cli-utils" "link:packages/cli-utils" "@design-systems/plugin" "link:packages/plugin" @@ -2274,12 +2274,20 @@ tslib "2.0.1" "@design-systems/utils@link:packages/utils": - version "4.15.0" + version "4.15.2" dependencies: "@babel/runtime" "^7.13.9" + brotli "^1.3.3" clsx "^1.0.4" + commently "6.18.3" + dasherize "2.0.0" focus-lock "^0.8.0" + get-monorepo-packages "1.2.0" + gitlog "4.0.8" + markdown-table "2.0.0" + node-fetch "2" react-merge-refs "^1.0.0" + table "^6.8.1" "@emotion/cache@^10.0.27", "@emotion/cache@^10.0.9": version "10.0.27" @@ -6467,6 +6475,16 @@ ajv@^7.0.2: require-from-string "^2.0.2" uri-js "^4.2.2" +ajv@^8.0.1: + version "8.12.0" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + all-contributors-cli@6.19.0: version "6.19.0" resolved "https://registry.yarnpkg.com/all-contributors-cli/-/all-contributors-cli-6.19.0.tgz#7e4550973afede2476b62bd159fee6d72a1ad802" @@ -6549,6 +6567,11 @@ ansi-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -7382,6 +7405,11 @@ base64-js@^1.0.2: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== +base64-js@^1.1.2: + version "1.5.1" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + base64-url@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/base64-url/-/base64-url-2.3.3.tgz#645b71455c75109511f27d98450327e455f488ec" @@ -7611,6 +7639,13 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= +brotli@^1.3.3: + version "1.3.3" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/brotli/-/brotli-1.3.3.tgz#7365d8cc00f12cf765d2b2c898716bcf4b604d48" + integrity sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg== + dependencies: + base64-js "^1.1.2" + browser-process-hrtime@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" @@ -9735,6 +9770,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +dasherize@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/dasherize/-/dasherize-2.0.0.tgz#6d809c9cd0cf7bb8952d80fc84fa13d47ddb1308" + integrity sha512-APql/TZ6FdLEpf2z7/X2a2zyqK8juYtqaSVqxw9mYoQ64CXkfU15AeLh8pUszT8+fnYjgm6t0aIYpWKJbnLkuA== + data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -12442,6 +12482,14 @@ gitlog@4.0.0: debug "^4.1.1" tslib "^1.11.1" +gitlog@4.0.8: + version "4.0.8" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/gitlog/-/gitlog-4.0.8.tgz#a255e7d4cb7bc9603afab01c39bd71816c800c20" + integrity sha512-FcTLP7Rc0H1vWXD+J/aj5JS1uiCEBblcYXlcacRAT73N26OMYFFzrBXYmDozmWlV2K7zwK5PrH16/nuRNhqSlQ== + dependencies: + debug "^4.1.1" + tslib "^2.5.0" + gitlog@^4.0.3: version "4.0.4" resolved "https://registry.yarnpkg.com/gitlog/-/gitlog-4.0.4.tgz#8da6c08748dc290eb6c2fc11e3c505fb73715564" @@ -15839,6 +15887,11 @@ lodash.toarray@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + lodash.unescape@4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" @@ -16997,6 +17050,13 @@ node-emoji@^1.10.0: dependencies: lodash.toarray "^4.4.0" +node-fetch@2: + version "2.6.12" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/node-fetch/-/node-fetch-2.6.12.tgz#02eb8e22074018e3d5a83016649d04df0e348fba" + integrity sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g== + dependencies: + whatwg-url "^5.0.0" + node-fetch@2.6.1, node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" @@ -22063,6 +22123,15 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + "string.prototype.matchall@^4.0.0 || ^3.0.1", string.prototype.matchall@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" @@ -22185,6 +22254,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-bom@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" @@ -22618,6 +22694,17 @@ table@^6.0.1: slice-ansi "^4.0.0" string-width "^4.2.0" +table@^6.8.1: + version "6.8.1" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + tapable@1.1.3, tapable@^1.0.0, tapable@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" @@ -23235,6 +23322,11 @@ tslib@^2.3.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== +tslib@^2.5.0: + version "2.6.0" + resolved "https://registry.npmjs.intuit.com:443/artifactory/api/npm/npm-intuit/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3" + integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"