diff --git a/.circleci/config.yml b/.circleci/config.yml index bf213296e58126..4800524d7fca3b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -181,7 +181,10 @@ jobs: command: cd packages/material-ui-system && yarn build - persist_to_workspace: root: . - paths: packages/*/build + paths: + - packages/*/build + # rollup snapshot + - packages/material-ui/size-snapshot.json test_browser: <<: *defaults steps: @@ -228,17 +231,11 @@ jobs: - *install_js - attach_workspace: at: /tmp/workspace - - run: - name: Inspect - command: du -a /tmp/workspace - run: name: Restore build command: | sudo apt install -y rsync rsync -a /tmp/workspace/ . - - run: - name: Inspect - command: du -a packages/ # Netlify already do it for us but we need to check the size. - run: name: Can we build the docs? @@ -247,18 +244,19 @@ jobs: name: Create a size snapshot command: yarn size:snapshot # downloaded by aws lambda to s3 bucket - # lambda allowes us to limit this to mui-org branches only while hiding credentials - # that would allow write access to s3 + # lambda allowes us to limit this to mui-org-branches-only while hiding credentials + # that allow write access to s3 - store_artifacts: path: size-snapshot.json - run: name: Possibly persist size snapshot command: | - if [ $CIRCLE_BRANCH ~= ^pull/ ]; then - echo "pull request; do not persist the size snapshot" - else + if [ -z "$CI_PULL_REQUEST" ]; then echo "no pull request; lets persist the size snapshot" curl -X PUT --header "x-api-key: $CIRCLE_AWS_API_KEY" https://t6nulys5kl.execute-api.us-east-1.amazonaws.com/v1/persist-size-snapshot?build-id=$CIRCLE_BUILD_NUM + else + echo "pull request; let's run dangerJS" + yarn danger ci fi workflows: version: 2 diff --git a/dangerfile.js b/dangerfile.js new file mode 100644 index 00000000000000..83de94c7ec4cad --- /dev/null +++ b/dangerfile.js @@ -0,0 +1,175 @@ +// inspire by reacts dangerfile +// danger has to be the first thing required! +const { danger, markdown } = require('danger'); +const { exec } = require('child_process'); +const { loadComparison } = require('./scripts/sizeSnapshot'); + +const parsedSizeChangeThreshold = 300; +const gzipSizeChangeThreshold = 100; + +/** + * executes a git subcommand + * @param {any} args + */ +function git(args) { + return new Promise((resolve, reject) => { + exec(`git ${args}`, (err, stdout) => { + if (err) { + reject(err); + } else { + resolve(stdout.trim()); + } + }); + }); +} + +const upstreamRemote = 'danger-upstream'; + +async function cleanup() { + await git(`remote remove ${upstreamRemote}`); +} + +function createComparisonFilter(parsedThreshold, gzipThreshold) { + return ([, { parsed, gzip }]) => { + return ( + Math.abs(parsed.absoluteDiff) >= parsedThreshold || + Math.abs(gzip.absoluteDiff) >= gzipThreshold + ); + }; +} + +/** + * checks if the bundle is of a package e.b. `@material-ui/core` but not + * `@material-ui/core/Paper` + * @param {[string]} comparison entry + */ +function isPackageComparison([bundle]) { + return /^@[\w-]+\/[\w-]+$/.test(bundle); +} + +/** + * Generates a user-readable string from a percentage change + * @param {number} change + * @param {string} goodEmoji emoji on reduction + * @param {string} badEmooji emoji on increase + */ +function addPercent(change, goodEmoji = '', badEmooji = ':small_red_triangle_down:') { + if (!Number.isFinite(change)) { + // When a new package is created + return 'n/a'; + } + const formatted = (change * 100).toFixed(2); + if (/^-|^0(?:\.0+)$/.test(formatted)) { + return `${goodEmoji}${formatted}%`; + } + return `${badEmooji}:+${formatted}%`; +} + +/** + * Generates a Markdown table + * @param {string[]} headers + * @param {string[][]} body + */ +function generateMDTable(headers, body) { + const tableHeaders = [headers.join(' | '), headers.map(() => ' --- ').join(' | ')]; + + const tablebody = body.map(r => r.join(' | ')); + return `${tableHeaders.join('\n')}\n${tablebody.join('\n')}`; +} + +function generateEmphasizedChange([bundle, { parsed, gzip }]) { + // increase might be a bug fix which is a nice thing. reductions are always nice + const changeParsed = addPercent(parsed.relativeDiff, ':heart_eyes:', ''); + const changeGzip = addPercent(gzip.relativeDiff, ':heart_eyes:', ''); + + return `**${bundle}**: parsed: ${changeParsed}, gzip: ${changeGzip}`; +} + +async function run() { + // Use git locally to grab the commit which represents the place + // where the branches differ + const upstreamRepo = danger.github.pr.base.repo.full_name; + const upstreamRef = danger.github.pr.base.ref; + try { + await git(`remote add ${upstreamRemote} https://github.com/${upstreamRepo}.git`); + } catch (err) { + // ignore if it already exist for local testing + } + await git(`fetch ${upstreamRemote}`); + const mergeBaseCommit = await git(`merge-base HEAD ${upstreamRemote}/${upstreamRef}`); + + const commitRange = `${mergeBaseCommit}...${danger.github.pr.head.sha}`; + + const comparison = await loadComparison(mergeBaseCommit, upstreamRef); + const results = Object.entries(comparison.bundles); + const anyResultsChanges = results.filter(createComparisonFilter(1, 1)); + + if (anyResultsChanges.length > 0) { + markdown('This PR introduced some changes to the bundle size.'); + + const importantChanges = results + .filter(createComparisonFilter(parsedSizeChangeThreshold, gzipSizeChangeThreshold)) + .filter(isPackageComparison) + .map(generateEmphasizedChange); + + // have to guard against empty strings + if (importantChanges.length > 0) { + markdown(importantChanges.join('\n')); + } + + const detailsTable = generateMDTable( + [ + 'bundle', + 'parsed diff', + 'gzip diff', + 'prev parsed', + 'current parsed', + 'prev gzip', + 'current gzip', + ], + results.map(([bundle, { parsed, gzip }]) => { + return [ + bundle, + addPercent(parsed.relativeDiff), + addPercent(gzip.relativeDiff), + parsed.previous, + parsed.current, + gzip.previous, + gzip.current, + ]; + }), + ); + + const details = ` +
+ Details of bundle changes. + +

Comparing: ${commitRange}

+ + ${detailsTable} + +
`; + + markdown(details); + } else { + // this can later be removed to reduce PR noise. It is kept for now for debug + // purposes only. DangerJS will swallow console.logs if completes successfully + markdown(`No bundle size changes comparing ${commitRange}`); + } +} + +(async () => { + try { + await run(); + } catch (err) { + console.error(err); + } + + try { + await cleanup(); + } catch (err) { + console.error(err); + // unhandled promise rejects exit with 0 + process.exit(1); + } +})(); diff --git a/package.json b/package.json index 9cb461c7bafc26..80bf17aa6685a8 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,7 @@ "cross-env": "^5.1.1", "css-loader": "^2.0.0", "css-mediaquery": "^0.1.2", + "danger": "^7.0.12", "date-fns": "2.0.0-alpha.21", "doctrine": "^3.0.0", "downshift": "^3.0.0", diff --git a/packages/material-ui/.size-snapshot.json b/packages/material-ui/.size-snapshot.json deleted file mode 100644 index f7abcf3dba3449..00000000000000 --- a/packages/material-ui/.size-snapshot.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "build/umd/material-ui.production.min.js": { - "bundled": 924000, - "minified": 343392, - "gzipped": 90640 - } -} diff --git a/packages/material-ui/scripts/rollup.config.js b/packages/material-ui/scripts/rollup.config.js index aa5add25dcf8e6..a5e81d6f64adfb 100644 --- a/packages/material-ui/scripts/rollup.config.js +++ b/packages/material-ui/scripts/rollup.config.js @@ -58,7 +58,7 @@ export default [ commonjs(commonjsOptions), nodeGlobals(), // Wait for https://github.com/cssinjs/jss/pull/893 replace({ 'process.env.NODE_ENV': JSON.stringify('production') }), - sizeSnapshot(), + sizeSnapshot({ snapshotPath: 'size-snapshot.json' }), uglify(), ], }, diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 00000000000000..204a62c4fd961d --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,3 @@ +# material-ui scripts + +Top level files are scripts, everything below modules \ No newline at end of file diff --git a/scripts/createSizeSnapshot.js b/scripts/createSizeSnapshot.js index 12a2d04eeeecf9..658a00c9bba775 100644 --- a/scripts/createSizeSnapshot.js +++ b/scripts/createSizeSnapshot.js @@ -128,7 +128,7 @@ async function getSizeLimitBundles() { } async function run() { - const rollupBundles = [path.join(workspaceRoot, 'packages/material-ui/.size-snapshot.json')]; + const rollupBundles = [path.join(workspaceRoot, 'packages/material-ui/size-snapshot.json')]; const sizeLimitBundles = await getSizeLimitBundles(); const bundleSizes = fromEntries( diff --git a/scripts/sizeSnapshot/index.js b/scripts/sizeSnapshot/index.js new file mode 100644 index 00000000000000..bd7dc7516776a1 --- /dev/null +++ b/scripts/sizeSnapshot/index.js @@ -0,0 +1,3 @@ +const loadComparison = require('./loadComparison'); + +module.exports = { loadComparison }; diff --git a/scripts/sizeSnapshot/loadComparison.js b/scripts/sizeSnapshot/loadComparison.js new file mode 100644 index 00000000000000..d84d63ea176e4a --- /dev/null +++ b/scripts/sizeSnapshot/loadComparison.js @@ -0,0 +1,79 @@ +/** + * `snapshots` always refer to size snapshots in this file + */ +const fse = require('fs-extra'); +const path = require('path'); +const fetch = require('node-fetch'); + +const artifactServer = 'https://s3.eu-central-1.amazonaws.com/eps1lon-material-ui'; + +async function loadCurrentSnapshot() { + return fse.readJSON(path.join(__dirname, '../../size-snapshot.json')); +} + +/** + * @param {string} commitId the sha of a commit + * @param {string} ref the branch containing that commit + */ +async function loadSnapshot(commitId, ref = 'master') { + const response = await fetch(`${artifactServer}/artifacts/${ref}/${commitId}/size-snapshot.json`); + return response.json(); +} + +function flatten(array) { + return array.reduce((acc, entry) => acc.concat(entry), []); +} + +function fromEntries(entries) { + return entries.reduce((acc, [key, value]) => { + acc[key] = value; + return acc; + }, []); +} + +function uniqueKeys(...objects) { + return Array.from(new Set(flatten(objects.map(Object.keys)))); +} + +const nullSnapshot = { gzip: Number.NaN, parsed: Number.NaN }; + +module.exports = async function loadComparison(parrentId, ref) { + const [currentSnapshot, previousSnapshot] = await Promise.all([ + loadCurrentSnapshot(), + // silence non existing snapshots + loadSnapshot(parrentId, ref).catch(() => ({})), + ]); + + const bundleKeys = uniqueKeys(currentSnapshot, previousSnapshot); + + const bundles = fromEntries( + bundleKeys.map(bundle => { + const currentSize = currentSnapshot[bundle] || nullSnapshot; + const previousSize = previousSnapshot[bundle] || nullSnapshot; + + return [ + bundle, + { + parsed: { + previous: previousSize.parsed, + current: currentSize.parsed, + absoluteDiff: currentSize.parsed - previousSize.parsed, + relativeDiff: currentSize.parsed / previousSize.parsed - 1, + }, + gzip: { + previous: previousSize.gzip, + current: currentSize.gzip, + absoluteDiff: currentSize.gzip - previousSize.gzip, + relativeDiff: currentSize.gzip / previousSize.gzip - 1, + }, + }, + ]; + }), + ); + + return { + previous: parrentId, + current: 'HEAD', + bundles, + }; +}; diff --git a/yarn.lock b/yarn.lock index 8d9bd5b71f7116..6ce7257c214ec0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -724,7 +724,7 @@ "@babel/helper-regex" "^7.0.0" regexpu-core "^4.1.3" -"@babel/polyfill@^7.0.0": +"@babel/polyfill@^7.0.0", "@babel/polyfill@^7.2.5": version "7.2.5" resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.2.5.tgz#6c54b964f71ad27edddc567d065e57e87ed7fa7d" integrity sha512-8Y/t3MWThtMLYr0YNC/Q76tqN1w30+b0uQMeFUYauG2UGTR19zyUtFrAzT23zNtBxPp+LbE5E/nwV/q/r3y6ug== @@ -1757,6 +1757,21 @@ node-fetch "^2.3.0" universal-user-agent "^2.0.1" +"@octokit/rest@^16.14.1": + version "16.16.0" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.16.0.tgz#b686407d34c756c3463f8a7b1e42aa035a504306" + integrity sha512-Q6L5OwQJrdJ188gLVmUHLKNXBoeCU0DynKPYW8iZQQoGNGws2hkP/CePVNlzzDgmjuv7o8dCrJgecvDcIHccTA== + dependencies: + "@octokit/request" "2.3.0" + before-after-hook "^1.2.0" + btoa-lite "^1.0.0" + lodash.get "^4.4.2" + lodash.set "^4.3.2" + lodash.uniq "^4.5.0" + octokit-pagination-methods "^1.1.0" + universal-user-agent "^2.0.0" + url-template "^2.0.8" + "@octokit/rest@^16.15.0": version "16.15.0" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.15.0.tgz#648a88d5de055bcf38976709c5b2bdf1227b926f" @@ -3156,6 +3171,11 @@ buffer-alloc@^1.2.0: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + buffer-es6@^4.9.3: version "4.9.3" resolved "https://registry.yarnpkg.com/buffer-es6/-/buffer-es6-4.9.3.tgz#f26347b82df76fd37e18bcb5288c4970cfd5c404" @@ -4496,6 +4516,43 @@ damerau-levenshtein@^1.0.4: resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz#03191c432cb6eea168bb77f3a55ffdccb8978514" integrity sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ= +danger@^7.0.12: + version "7.0.12" + resolved "https://registry.yarnpkg.com/danger/-/danger-7.0.12.tgz#bba12a496adcc7a1e30619404bc13a3c6d9ba915" + integrity sha512-pew8vsBs2bitXt5upLuvfEAqvVuvzLoo/BjX7ysGI3yXQ8X7vrESo1/gGRvkA4uaDEoDq7LaBR4xhxfqxk9fog== + dependencies: + "@babel/polyfill" "^7.2.5" + "@octokit/rest" "^16.14.1" + chalk "^2.3.0" + commander "^2.18.0" + debug "^4.1.1" + get-stdin "^6.0.0" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + hyperlinker "^1.0.0" + jsome "^2.3.25" + json5 "^2.1.0" + jsonpointer "^4.0.1" + jsonwebtoken "^8.4.0" + lodash.find "^4.6.0" + lodash.includes "^4.3.0" + lodash.isobject "^3.0.2" + lodash.keys "^4.0.8" + memfs-or-file-map-to-github-branch "^1.1.0" + node-cleanup "^2.1.2" + node-fetch "^2.3.0" + override-require "^1.1.1" + p-limit "^2.1.0" + parse-diff "^0.5.1" + parse-git-config "^2.0.3" + parse-github-url "^1.0.2" + parse-link-header "^1.0.1" + pinpoint "^1.1.0" + readline-sync "^1.4.9" + require-from-string "^2.0.2" + rfc6902 "^3.0.1" + supports-hyperlinks "^1.0.1" + dargs@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" @@ -4597,7 +4654,7 @@ decamelize-keys@^1.0.0: decamelize "^1.1.0" map-obj "^1.0.0" -decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0: +decamelize@^1.1.0, decamelize@^1.1.1, decamelize@^1.1.2, decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= @@ -4984,6 +5041,13 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +ecdsa-sig-formatter@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz#1c595000f04a8897dfb85000892a0f4c33af86c3" + integrity sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM= + dependencies: + safe-buffer "^5.0.1" + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -6111,6 +6175,11 @@ fs-access@^1.0.0: dependencies: null-check "^1.0.0" +fs-exists-sync@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" + integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= + fs-extra@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950" @@ -6291,6 +6360,15 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +git-config-path@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/git-config-path/-/git-config-path-1.0.1.tgz#6d33f7ed63db0d0e118131503bab3aca47d54664" + integrity sha1-bTP37WPbDQ4RgTFQO6s6ykfVRmQ= + dependencies: + extend-shallow "^2.0.1" + fs-exists-sync "^0.1.0" + homedir-polyfill "^1.0.0" + git-raw-commits@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5" @@ -6593,6 +6671,11 @@ has-cors@1.1.0: resolved "https://registry.yarnpkg.com/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -6711,7 +6794,7 @@ home-or-tmp@^3.0.0: resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-3.0.0.tgz#57a8fe24cf33cdd524860a15821ddc25c86671fb" integrity sha1-V6j+JM8zzdUkhgoVgh3cJchmcfs= -homedir-polyfill@^1.0.1: +homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" integrity sha1-TCu8inWJmP7r9e1oWA921GdotLw= @@ -6844,6 +6927,11 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +hyperlinker@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hyperlinker/-/hyperlinker-1.0.0.tgz#23dc9e38a206b208ee49bc2d6c8ef47027df0c0e" + integrity sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ== + hyphenate-style-name@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48" @@ -7003,7 +7091,7 @@ inherits@2.0.1: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= -ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: +ini@^1.3.2, ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== @@ -7053,6 +7141,11 @@ invariant@^2.2.1, invariant@^2.2.2, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= + invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" @@ -7673,6 +7766,15 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= +jsome@^2.3.25: + version "2.5.0" + resolved "https://registry.yarnpkg.com/jsome/-/jsome-2.5.0.tgz#5e417eef4341ffeb83ee8bfa9265b36d56fe49ed" + integrity sha1-XkF+70NB/+uD7ov6kmWzbVb+Se0= + dependencies: + chalk "^2.3.0" + json-stringify-safe "^5.0.1" + yargs "^11.0.0" + json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" @@ -7749,6 +7851,26 @@ jsonparse@^1.2.0: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= +jsonpointer@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= + +jsonwebtoken@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz#8757f7b4cb7440d86d5e2f3becefa70536c8e46a" + integrity sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg== + dependencies: + jws "^3.1.5" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -7939,6 +8061,23 @@ just-extend@^4.0.2: resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.0.2.tgz#f3f47f7dfca0f989c55410a7ebc8854b07108afc" integrity sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw== +jwa@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.2.0.tgz#606da70c1c6d425cad329c77c99f2df2a981489a" + integrity sha512-Grku9ZST5NNQ3hqNUodSkDfEBqAmGA1R8yiyPHOnLzEKI0GaCQC/XhFmsheXYuXzFQJdILbh+lYBiliqG5R/Vg== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.10" + safe-buffer "^5.0.1" + +jws@^3.1.5: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.1.tgz#d79d4216a62c9afa0a3d5e8b5356d75abdeb2be5" + integrity sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g== + dependencies: + jwa "^1.2.0" + safe-buffer "^5.0.1" + karma-browserstack-launcher@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/karma-browserstack-launcher/-/karma-browserstack-launcher-1.4.0.tgz#22f92e969d2db6cfc00e578708bda39378d5f2ab" @@ -8084,6 +8223,13 @@ launch-editor@2.2.1: chalk "^2.3.0" shell-quote "^1.6.1" +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= + dependencies: + invert-kv "^1.0.0" + lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" @@ -8247,6 +8393,11 @@ lodash.escape@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98" integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg= +lodash.find@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.find/-/lodash.find-4.6.0.tgz#cb0704d47ab71789ffa0de8b97dd926fb88b13b1" + integrity sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E= + lodash.flattendeep@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" @@ -8257,11 +8408,51 @@ lodash.get@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= + lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + +lodash.isobject@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-3.0.2.tgz#3c8fb8d5b5bf4bf90ae06e14f2a530a4ed935e1d" + integrity sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0= + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= + +lodash.keys@^4.0.8: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-4.2.0.tgz#a08602ac12e4fb83f91fc1fb7a360a4d9ba35205" + integrity sha1-oIYCrBLk+4P5H8H7ejYKTZujUgU= + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -8277,6 +8468,11 @@ lodash.omit@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz#6eb19ae5a1ee1dd9df0b969e66ce0b7fa30b5e60" integrity sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA= +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" @@ -8568,6 +8764,13 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= + dependencies: + mimic-fn "^1.0.0" + mem@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.1.0.tgz#aeb9be2d21f47e78af29e4ac5978e8afa2ca5b8a" @@ -8577,6 +8780,11 @@ mem@^4.0.0: mimic-fn "^1.0.0" p-is-promise "^2.0.0" +memfs-or-file-map-to-github-branch@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/memfs-or-file-map-to-github-branch/-/memfs-or-file-map-to-github-branch-1.1.2.tgz#9d46c02481b7eca8e5ee8a94f170b7e0138cad67" + integrity sha512-D2JKK2DTuVYQqquBWco3K6UfSVyVwmd58dgNqh+TgxHOZdTmR8I130gjMbVCkemDl/EzqDA62417cJxKL3/FFA== + memoize-one@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-4.1.0.tgz#a2387c58c03fff27ca390c31b764a79addf3f906" @@ -9093,6 +9301,11 @@ nise@^1.4.8: path-to-regexp "^1.7.0" text-encoding "^0.6.4" +node-cleanup@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c" + integrity sha1-esGavSl+Caf3KnFUXZUbUX5N3iw= + node-dir@^0.1.10, node-dir@^0.1.17: version "0.1.17" resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5" @@ -9599,6 +9812,15 @@ os-homedir@^1.0.0, os-homedir@^1.0.1: resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + os-locale@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" @@ -9638,6 +9860,11 @@ output-file-sync@^2.0.0: is-plain-obj "^1.1.0" mkdirp "^0.5.1" +override-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/override-require/-/override-require-1.1.1.tgz#6ae22fadeb1f850ffb0cf4c20ff7b87e5eb650df" + integrity sha1-auIvresfhQ/7DPTCD/e4fl62UN8= + p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" @@ -9660,7 +9887,7 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0: +p-limit@^2.0.0, p-limit@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.1.0.tgz#1d5a0d20fb12707c758a655f6bbc4386b5930d68" integrity sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g== @@ -9806,11 +10033,30 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-diff@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/parse-diff/-/parse-diff-0.5.1.tgz#18b3e82a0765ac1c8796e3854e475073a691c4fb" + integrity sha512-/qXjo9x/pFa5bVk/ZXaJD0yr3Tf3Yp6MWWMr4vnUmumDrE0yoE6YDH2A8vmcCD/Ko3tW2o0X+zGYh2zMLXshsg== + +parse-git-config@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/parse-git-config/-/parse-git-config-2.0.3.tgz#6fb840d4a956e28b971c97b33a5deb73a6d5b6bb" + integrity sha512-Js7ueMZOVSZ3tP8C7E3KZiHv6QQl7lnJ+OkbxoaFazzSa2KyEHqApfGbU3XboUgUnq4ZuUmskUpYKTNx01fm5A== + dependencies: + expand-tilde "^2.0.2" + git-config-path "^1.0.1" + ini "^1.3.5" + parse-github-repo-url@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" integrity sha1-nn2LslKmy2ukJZUGC3v23z28H1A= +parse-github-url@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-github-url/-/parse-github-url-1.0.2.tgz#242d3b65cbcdda14bb50439e3242acf6971db395" + integrity sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw== + parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -9836,6 +10082,13 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-link-header@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-link-header/-/parse-link-header-1.0.1.tgz#bedfe0d2118aeb84be75e7b025419ec8a61140a7" + integrity sha1-vt/g0hGK64S+deewJUGeyKYRQKc= + dependencies: + xtend "~4.0.1" + parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -10030,6 +10283,11 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= +pinpoint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pinpoint/-/pinpoint-1.1.0.tgz#0cf7757a6977f1bf7f6a32207b709e377388e874" + integrity sha1-DPd1eml38b9/ajIge3CeN3OI6HQ= + pirates@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.0.tgz#850b18781b4ac6ec58a43c9ed9ec5fe6796addbd" @@ -11183,6 +11441,11 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +readline-sync@^1.4.9: + version "1.4.9" + resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.9.tgz#3eda8e65f23cd2a17e61301b1f0003396af5ecda" + integrity sha1-PtqOZfI80qF+YTAbHwADOWr17No= + recast@^0.16.0, recast@^0.16.1: version "0.16.2" resolved "https://registry.yarnpkg.com/recast/-/recast-0.16.2.tgz#3796ebad5fe49ed85473b479cd6df554ad725dc2" @@ -11593,6 +11856,11 @@ retry@^0.10.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= +rfc6902@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/rfc6902/-/rfc6902-3.0.1.tgz#03a3d38329dbc266fbc92aa7fc14546d7839e89f" + integrity sha512-a4t5OlaOgAejBg48/lkyQMcV6EWpljjSjmXAtSXLhw83x1OhlcVGLMLf//GoUSpHsWt8x/7oxaf5FEGM9QH/iQ== + rfdc@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.2.tgz#e6e72d74f5dc39de8f538f65e00c36c18018e349" @@ -12587,7 +12855,7 @@ supports-color@^2.0.0: resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= -supports-color@^5.3.0, supports-color@^5.5.0: +supports-color@^5.0.0, supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -12601,6 +12869,14 @@ supports-color@^6.0.0, supports-color@^6.1.0: dependencies: has-flag "^3.0.0" +supports-hyperlinks@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz#71daedf36cc1060ac5100c351bb3da48c29c0ef7" + integrity sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw== + dependencies: + has-flag "^2.0.0" + supports-color "^5.0.0" + svgo@^1.0.0, svgo@^1.0.5: version "1.1.1" resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.1.1.tgz#12384b03335bcecd85cfa5f4e3375fed671cb985" @@ -13868,6 +14144,11 @@ xtend@~2.1.1: dependencies: object-keys "~0.4.0" +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= + "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" @@ -13891,6 +14172,31 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + integrity sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc= + dependencies: + camelcase "^4.1.0" + +yargs@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" + integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^9.0.2" + yargs@^12.0.0, yargs@^12.0.1, yargs@^12.0.4, yargs@^12.0.5: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"