diff --git a/.eslintrc.json b/.eslintrc.json index a21b4ee..46aa64e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,6 @@ { "plugins": ["jest", "@typescript-eslint"], - "extends": ["plugin:github/es6"], + "extends": ["plugin:github/recommended"], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 9, @@ -13,6 +13,11 @@ "jest/globals": true }, "rules": { - "no-console": "off" + "no-console": "off", + "eslint-comments/no-use": "off", + "import/no-namespace": "off", + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": "error", + "camelcase": "off" } } diff --git a/src/SizeLimit.spec.ts b/__tests__/SizeLimit.test.ts similarity index 77% rename from src/SizeLimit.spec.ts rename to __tests__/SizeLimit.test.ts index bb9c0d8..96cd0dc 100644 --- a/src/SizeLimit.spec.ts +++ b/__tests__/SizeLimit.test.ts @@ -1,8 +1,8 @@ -import SizeLimit from "./SizeLimit"; +import SizeLimitParser from "../src/SizeLimitParser"; describe("SizeLimit", () => { test("should parse size-limit output", () => { - const limit = new SizeLimit(); + const parser = new SizeLimitParser(); const output = JSON.stringify([ { name: "dist/index.js", @@ -13,7 +13,7 @@ describe("SizeLimit", () => { } ]); - expect(limit.parseResults(output)).toEqual({ + expect(parser.parse(output)).toEqual({ "dist/index.js": { name: "dist/index.js", loading: 2.1658984375, @@ -25,7 +25,7 @@ describe("SizeLimit", () => { }); test("should parse size-limit without times output", () => { - const limit = new SizeLimit(); + const parser = new SizeLimitParser(); const output = JSON.stringify([ { name: "dist/index.js", @@ -34,7 +34,7 @@ describe("SizeLimit", () => { } ]); - expect(limit.parseResults(output)).toEqual({ + expect(parser.parse(output)).toEqual({ "dist/index.js": { name: "dist/index.js", size: 110894 @@ -43,7 +43,7 @@ describe("SizeLimit", () => { }); test("should format size-limit results", () => { - const limit = new SizeLimit(); + const parser = new SizeLimitParser(); const base = { "dist/index.js": { name: "dist/index.js", @@ -63,8 +63,8 @@ describe("SizeLimit", () => { } }; - expect(limit.formatResults(base, current)).toEqual([ - SizeLimit.TIME_RESULTS_HEADER, + expect(parser.diff(base, current)).toEqual([ + SizeLimitParser.TIME_RESULTS_HEADER, [ "dist/index.js", "98.53 KB (-9.92% 🔽)", @@ -76,7 +76,7 @@ describe("SizeLimit", () => { }); test("should format size-limit without times results", () => { - const limit = new SizeLimit(); + const parser = new SizeLimitParser(); const base = { "dist/index.js": { name: "dist/index.js", @@ -90,14 +90,14 @@ describe("SizeLimit", () => { } }; - expect(limit.formatResults(base, current)).toEqual([ - SizeLimit.SIZE_RESULTS_HEADER, + expect(parser.diff(base, current)).toEqual([ + SizeLimitParser.SIZE_RESULTS_HEADER, ["dist/index.js", "98.53 KB (-9.92% 🔽)"] ]); }); test("should format size-limit with new section", () => { - const limit = new SizeLimit(); + const parser = new SizeLimitParser(); const base = { "dist/index.js": { name: "dist/index.js", @@ -115,15 +115,15 @@ describe("SizeLimit", () => { } }; - expect(limit.formatResults(base, current)).toEqual([ - SizeLimit.SIZE_RESULTS_HEADER, + expect(parser.diff(base, current)).toEqual([ + SizeLimitParser.SIZE_RESULTS_HEADER, ["dist/index.js", "98.53 KB (-9.92% 🔽)"], ["dist/new.js", "98.53 KB (+100% 🔺)"] ]); }); test("should format size-limit with deleted section", () => { - const limit = new SizeLimit(); + const parser = new SizeLimitParser(); const base = { "dist/index.js": { name: "dist/index.js", @@ -137,8 +137,8 @@ describe("SizeLimit", () => { } }; - expect(limit.formatResults(base, current)).toEqual([ - SizeLimit.SIZE_RESULTS_HEADER, + expect(parser.diff(base, current)).toEqual([ + SizeLimitParser.SIZE_RESULTS_HEADER, ["dist/index.js", "0 B (-100%)"], ["dist/new.js", "98.53 KB (+100% 🔺)"] ]); diff --git a/dist/index.js b/dist/index.js index be7df37..178c791 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2007,22 +2007,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) { Object.defineProperty(exports, "__esModule", { value: true }); const core_1 = __webpack_require__(470); const github_1 = __webpack_require__(469); -// @ts-ignore -const markdown_table_1 = __importDefault(__webpack_require__(366)); -const Term_1 = __importDefault(__webpack_require__(733)); const SizeLimit_1 = __importDefault(__webpack_require__(617)); -const SIZE_LIMIT_URL = "https://github.com/ai/size-limit"; -const SIZE_LIMIT_HEADING = `## [size-limit](${SIZE_LIMIT_URL}) report`; -function fetchPreviousComment(octokit, repo, pr) { - return __awaiter(this, void 0, void 0, function* () { - // TODO: replace with octokit.issues.listComments when upgraded to v17 - const commentList = yield octokit.paginate("GET /repos/:owner/:repo/issues/:issue_number/comments", Object.assign(Object.assign({}, repo), { - // eslint-disable-next-line camelcase - issue_number: pr.number })); - const sizeLimitComment = commentList.find(comment => comment.body.startsWith(SIZE_LIMIT_HEADING)); - return !sizeLimitComment ? null : sizeLimitComment; - }); -} +const SizeLimitParser_1 = __importDefault(__webpack_require__(502)); +const SizeLimitReporter_1 = __importDefault(__webpack_require__(722)); function run() { return __awaiter(this, void 0, void 0, function* () { try { @@ -2035,47 +2022,21 @@ function run() { const skipStep = core_1.getInput("skip_step"); const buildScript = core_1.getInput("build_script"); const octokit = new github_1.GitHub(token); - const term = new Term_1.default(); - const limit = new SizeLimit_1.default(); - const { status, output } = yield term.execSizeLimit(null, skipStep, buildScript); - const { output: baseOutput } = yield term.execSizeLimit(pr.base.ref, null, buildScript); - let base; - let current; + const parser = new SizeLimitParser_1.default(); + const limit = new SizeLimit_1.default(parser); + const reporter = new SizeLimitReporter_1.default(octokit); + const { status, results } = yield limit.exec(null, skipStep, buildScript); + const { results: baseResults } = yield limit.exec(pr.base.ref, null, buildScript); + const isInvalid = status > 0; + const diffResults = parser.diff(baseResults, results); try { - base = limit.parseResults(baseOutput); - current = limit.parseResults(output); + yield reporter.comment(repo, pr.number, isInvalid, diffResults); } catch (error) { - console.log("Error parsing size-limit output. The output should be a json."); - throw error; - } - const body = [ - SIZE_LIMIT_HEADING, - markdown_table_1.default(limit.formatResults(base, current)) - ].join("\r\n"); - const sizeLimitComment = yield fetchPreviousComment(octokit, repo, pr); - if (!sizeLimitComment) { - try { - yield octokit.issues.createComment(Object.assign(Object.assign({}, repo), { - // eslint-disable-next-line camelcase - issue_number: pr.number, body })); - } - catch (error) { - console.log("Error creating comment. This can happen for PR's originating from a fork without write permissions."); - } - } - else { - try { - yield octokit.issues.updateComment(Object.assign(Object.assign({}, repo), { - // eslint-disable-next-line camelcase - comment_id: sizeLimitComment.id, body })); - } - catch (error) { - console.log("Error updating comment. This can happen for PR's originating from a fork without write permissions."); - } + console.log("Error posting comment. This can happen for PR's originating from a fork without write permissions."); } - if (status > 0) { - core_1.setFailed("Size limit has been exceeded."); + if (isInvalid) { + throw new Error("Size limit has been exceeded."); } } catch (error) { @@ -8249,6 +8210,112 @@ function resolveCommand(parsed) { module.exports = resolveCommand; +/***/ }), + +/***/ 502: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +// @ts-ignore +const bytes_1 = __importDefault(__webpack_require__(63)); +class SizeLimitParser { + formatBytes(size) { + return bytes_1.default.format(size, { unitSeparator: " " }); + } + formatTime(seconds = 0) { + if (seconds >= 1) { + return `${Math.ceil(seconds * 10) / 10} s`; + } + return `${Math.ceil(seconds * 1000)} ms`; + } + formatChange(base = 0, current = 0) { + if (current === 0) { + return "-100%"; + } + const value = ((current - base) / current) * 100; + const formatted = (Math.sign(value) * Math.ceil(Math.abs(value) * 100)) / 100; + if (value > 0) { + return `+${formatted}% 🔺`; + } + if (value === 0) { + return `${formatted}%`; + } + return `${formatted}% 🔽`; + } + formatLine(value, change) { + return `${value} (${change})`; + } + formatSizeResult(name, base, current) { + return [ + name, + this.formatLine(this.formatBytes(current.size), this.formatChange(base.size, current.size)) + ]; + } + formatTimeResult(name, base, current) { + return [ + name, + this.formatLine(this.formatBytes(current.size), this.formatChange(base.size, current.size)), + this.formatLine(this.formatTime(current.loading), this.formatChange(base.loading, current.loading)), + this.formatLine(this.formatTime(current.running), this.formatChange(base.running, current.running)), + this.formatTime(current.total) + ]; + } + parse(output) { + const results = JSON.parse(output); + return results.reduce((current, result) => { + let time = {}; + if (result.loading !== undefined && result.running !== undefined) { + const loading = +result.loading; + const running = +result.running; + time = { + running, + loading, + total: loading + running + }; + } + return Object.assign(Object.assign({}, current), { [result.name]: Object.assign({ name: result.name, size: +result.size }, time) }); + }, {}); + } + diff(base, current) { + const empty = { + name: "-", + size: 0, + running: 0, + loading: 0, + total: 0 + }; + const names = [...new Set([...Object.keys(base), ...Object.keys(current)])]; + const isSize = names.some((name) => current[name] && current[name].total === undefined); + const header = isSize + ? SizeLimitParser.SIZE_RESULTS_HEADER + : SizeLimitParser.TIME_RESULTS_HEADER; + const fields = names.map((name) => { + const baseResult = base[name] || empty; + const currentResult = current[name] || empty; + if (isSize) { + return this.formatSizeResult(name, baseResult, currentResult); + } + return this.formatTimeResult(name, baseResult, currentResult); + }); + return [header, ...fields]; + } +} +SizeLimitParser.SIZE_RESULTS_HEADER = ["Path", "Size"]; +SizeLimitParser.TIME_RESULTS_HEADER = [ + "Path", + "Size", + "Loading time (3g)", + "Running time (snapdragon)", + "Total time" +]; +exports.default = SizeLimitParser; + + /***/ }), /***/ 510: @@ -9237,102 +9304,64 @@ module.exports = require("events"); "use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -// @ts-ignore -const bytes_1 = __importDefault(__webpack_require__(63)); -const EmptyResult = { - name: "-", - size: 0, - running: 0, - loading: 0, - total: 0 -}; +const exec_1 = __webpack_require__(986); +const has_yarn_1 = __importDefault(__webpack_require__(931)); +const INSTALL_STEP = "install"; +const BUILD_STEP = "build"; class SizeLimit { - formatBytes(size) { - return bytes_1.default.format(size, { unitSeparator: " " }); - } - formatTime(seconds) { - if (seconds >= 1) { - return `${Math.ceil(seconds * 10) / 10} s`; - } - return `${Math.ceil(seconds * 1000)} ms`; - } - formatChange(base = 0, current = 0) { - if (current === 0) { - return "-100%"; - } - const value = ((current - base) / current) * 100; - const formatted = (Math.sign(value) * Math.ceil(Math.abs(value) * 100)) / 100; - if (value > 0) { - return `+${formatted}% 🔺`; - } - if (value === 0) { - return `${formatted}%`; - } - return `${formatted}% 🔽`; - } - formatLine(value, change) { - return `${value} (${change})`; - } - formatSizeResult(name, base, current) { - return [ - name, - this.formatLine(this.formatBytes(current.size), this.formatChange(base.size, current.size)) - ]; + constructor(parser) { + this.parser = parser; } - formatTimeResult(name, base, current) { - return [ - name, - this.formatLine(this.formatBytes(current.size), this.formatChange(base.size, current.size)), - this.formatLine(this.formatTime(current.loading), this.formatChange(base.loading, current.loading)), - this.formatLine(this.formatTime(current.running), this.formatChange(base.running, current.running)), - this.formatTime(current.total) - ]; - } - parseResults(output) { - const results = JSON.parse(output); - return results.reduce((current, result) => { - let time = {}; - if (result.loading !== undefined && result.running !== undefined) { - const loading = +result.loading; - const running = +result.running; - time = { - running, - loading, - total: loading + running - }; + exec(ref, skipStep, buildScript) { + return __awaiter(this, void 0, void 0, function* () { + const manager = has_yarn_1.default() ? "yarn" : "npm"; + let output = ""; + if (ref) { + try { + yield exec_1.exec(`git fetch origin ${ref} --depth=1`); + } + catch (error) { + console.log("Fetch failed", error.message); + } + yield exec_1.exec(`git checkout -f ${ref}`); } - return Object.assign(Object.assign({}, current), { [result.name]: Object.assign({ name: result.name, size: +result.size }, time) }); - }, {}); - } - formatResults(base, current) { - const names = [...new Set([...Object.keys(base), ...Object.keys(current)])]; - const isSize = names.some((name) => current[name] && current[name].total === undefined); - const header = isSize - ? SizeLimit.SIZE_RESULTS_HEADER - : SizeLimit.TIME_RESULTS_HEADER; - const fields = names.map((name) => { - const baseResult = base[name] || EmptyResult; - const currentResult = current[name] || EmptyResult; - if (isSize) { - return this.formatSizeResult(name, baseResult, currentResult); + if (skipStep !== INSTALL_STEP && skipStep !== BUILD_STEP) { + yield exec_1.exec(`${manager} install`); } - return this.formatTimeResult(name, baseResult, currentResult); + if (skipStep !== BUILD_STEP) { + const script = buildScript || "build"; + yield exec_1.exec(`${manager} run ${script}`); + } + const status = yield exec_1.exec("npx size-limit --json", [], { + windowsVerbatimArguments: true, + ignoreReturnCode: true, + listeners: { + stdout: (data) => { + output += data.toString(); + } + } + }); + const results = this.parser.parse(output); + return { + status, + results + }; }); - return [header, ...fields]; } } -SizeLimit.SIZE_RESULTS_HEADER = ["Path", "Size"]; -SizeLimit.TIME_RESULTS_HEADER = [ - "Path", - "Size", - "Loading time (3g)", - "Running time (snapdragon)", - "Total time" -]; exports.default = SizeLimit; @@ -10452,7 +10481,7 @@ module.exports = (promise, onFinally) => { /***/ }), -/***/ 733: +/***/ 722: /***/ (function(__unusedmodule, exports, __webpack_require__) { "use strict"; @@ -10470,48 +10499,50 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -const exec_1 = __webpack_require__(986); -const has_yarn_1 = __importDefault(__webpack_require__(931)); -const INSTALL_STEP = "install"; -const BUILD_STEP = "build"; -class Term { - execSizeLimit(branch, skipStep, buildScript) { +const markdown_table_1 = __importDefault(__webpack_require__(366)); +class SizeLimitReporter { + constructor(octokit) { + this.octokit = octokit; + } + getBody(isInvalid, diffResults) { + return [ + SizeLimitReporter.HEADING, + `**Status:** ${isInvalid ? "❌" : "✅"}`, + `
`, + `Toggle table`, + "

", + "", + markdown_table_1.default(diffResults), + "", + "

", + `
` + ].join("\r\n"); + } + fetchPrevious(repo, issueNumber) { return __awaiter(this, void 0, void 0, function* () { - const manager = has_yarn_1.default() ? "yarn" : "npm"; - let output = ""; - if (branch) { - try { - yield exec_1.exec(`git fetch origin ${branch} --depth=1`); - } - catch (error) { - console.log("Fetch failed", error.message); - } - yield exec_1.exec(`git checkout -f ${branch}`); - } - if (skipStep !== INSTALL_STEP && skipStep !== BUILD_STEP) { - yield exec_1.exec(`${manager} install`); - } - if (skipStep !== BUILD_STEP) { - const script = buildScript || "build"; - yield exec_1.exec(`${manager} run ${script}`); + const comments = yield this.octokit.paginate("GET /repos/:owner/:repo/issues/:issue_number/comments", Object.assign(Object.assign({}, repo), { issue_number: issueNumber })); + return comments.find(comment => comment.body.startsWith(SizeLimitReporter.HEADING)); + }); + } + create(repo, issueNumber, body) { + return this.octokit.issues.createComment(Object.assign(Object.assign({}, repo), { issue_number: issueNumber, body })); + } + update(repo, commentId, body) { + return this.octokit.issues.updateComment(Object.assign(Object.assign({}, repo), { comment_id: commentId, body })); + } + comment(repo, issueNumber, isInvalid, diffResults) { + return __awaiter(this, void 0, void 0, function* () { + const body = this.getBody(isInvalid, diffResults); + const comment = yield this.fetchPrevious(repo, issueNumber); + if (comment) { + return this.update(repo, comment.id, body); } - const status = yield exec_1.exec("npx size-limit --json", [], { - windowsVerbatimArguments: true, - ignoreReturnCode: true, - listeners: { - stdout: (data) => { - output += data.toString(); - } - } - }); - return { - status, - output - }; + return this.create(repo, issueNumber, body); }); } } -exports.default = Term; +SizeLimitReporter.HEADING = "## size-limit report 📦"; +exports.default = SizeLimitReporter; /***/ }), diff --git a/globals.d.ts b/globals.d.ts new file mode 100644 index 0000000..d2787f8 --- /dev/null +++ b/globals.d.ts @@ -0,0 +1 @@ +declare module "markdown-table"; diff --git a/jest.config.js b/jest.config.js index bffcfff..faabcb3 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,10 +1,8 @@ -// @ts-nocheck - module.exports = { clearMocks: true, moduleFileExtensions: ["js", "ts"], testEnvironment: "node", - testMatch: ["**/*.spec.ts"], + testMatch: ["**/*.test.ts"], testRunner: "jest-circus/runner", transform: { "^.+\\.ts$": "ts-jest" diff --git a/package-lock.json b/package-lock.json index 9a4f8a5..852a860 100644 --- a/package-lock.json +++ b/package-lock.json @@ -196,16 +196,6 @@ "regenerator-runtime": "^0.13.4" } }, - "@babel/runtime-corejs3": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.8.7.tgz", - "integrity": "sha512-sc7A+H4I8kTd7S61dgB9RomXu/C+F4IrRr4Ytze4dnfx7AXEpCrejSNpjx7vq6y/Bak9S6Kbk65a/WgMLtg43Q==", - "dev": true, - "requires": { - "core-js-pure": "^3.0.0", - "regenerator-runtime": "^0.13.4" - } - }, "@babel/template": { "version": "7.8.6", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", @@ -619,30 +609,30 @@ } }, "@size-limit/file": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@size-limit/file/-/file-4.3.1.tgz", - "integrity": "sha512-rWCUP8Q9jKBKmUecYo9L/mvGtLQsgQm5kVWASsbjXBnE2N8R9TxdiSg85Dmejm9Ivy5tT+wjGntd6an2wOLyNQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@size-limit/file/-/file-4.5.1.tgz", + "integrity": "sha512-/NqXm0hypfPmLO4EhfQXMoIJ+gq+zePTrlWZAJ0usCuhYY89iZMvPR4FokGgAO8+JizNMoK4mjLgIRzuOcS2wg==", "dev": true, "requires": { - "semver": "7.1.3" + "semver": "7.3.2" }, "dependencies": { "semver": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz", - "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true } } }, "@size-limit/time": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@size-limit/time/-/time-4.3.1.tgz", - "integrity": "sha512-VqkVpwzVpBJRO79juHSYr/GNSuWbf/Q3pcIJdWqvwWDTTfPsgKpPf53PoouTON5OKc82namA/l7u7dDlrgL74g==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@size-limit/time/-/time-4.5.1.tgz", + "integrity": "sha512-Fncqx+g4fOzz5CavmNgLIl59R7KnEysNzUgUVWkVLPj/534H/1u28CR/qgNwtRZSseCcFqOLONCPMT6ilRNxKQ==", "dev": true, "requires": { - "estimo": "^2.0.2", - "react": "^16.13.0" + "estimo": "^2.0.4", + "react": "^16.13.1" } }, "@types/babel__core": { @@ -738,6 +728,12 @@ "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", "dev": true }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, "@types/mime-types": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz", @@ -777,86 +773,97 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.13.0.tgz", - "integrity": "sha512-WQHCozMnuNADiqMtsNzp96FNox5sOVpU8Xt4meaT4em8lOG1SrOv92/mUbEHQVh90sldKSfcOc/I0FOb/14G1g==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.4.0.tgz", + "integrity": "sha512-wfkpiqaEVhZIuQRmudDszc01jC/YR7gMSxa6ulhggAe/Hs0KVIuo9wzvFiDbG3JD5pRFQoqnf4m7REDsUvBnMQ==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "1.13.0", - "eslint-utils": "^1.3.1", + "@typescript-eslint/experimental-utils": "3.4.0", + "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", - "regexpp": "^2.0.1", - "tsutils": "^3.7.0" + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" }, "dependencies": { - "@typescript-eslint/experimental-utils": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", - "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "1.13.0", - "eslint-scope": "^4.0.0" + "ms": "^2.1.1" } }, - "@typescript-eslint/typescript-estree": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", - "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", - "dev": true, - "requires": { - "lodash.unescape": "4.0.1", - "semver": "5.5.0" - } + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true } } }, "@typescript-eslint/experimental-utils": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.23.0.tgz", - "integrity": "sha512-OswxY59RcXH3NNPmq+4Kis2CYZPurRU6mG5xPcn24CjFyfdVli5mySwZz/g/xDbJXgDsYqNGq7enV0IziWGXVQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.4.0.tgz", + "integrity": "sha512-rHPOjL43lOH1Opte4+dhC0a/+ks+8gOBwxXnyrZ/K4OTAChpSjP76fbI8Cglj7V5GouwVAGaK+xVwzqTyE/TPw==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.23.0", - "eslint-scope": "^5.0.0" + "@typescript-eslint/typescript-estree": "3.4.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" }, "dependencies": { "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", "dev": true, "requires": { "esrecurse": "^4.1.0", "estraverse": "^4.1.1" } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } } } }, "@typescript-eslint/parser": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.23.0.tgz", - "integrity": "sha512-k61pn/Nepk43qa1oLMiyqApC6x5eP5ddPz6VUYXCAuXxbmRLqkPYzkFRKl42ltxzB2luvejlVncrEpflgQoSUg==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.4.0.tgz", + "integrity": "sha512-ZUGI/de44L5x87uX5zM14UYcbn79HSXUR+kzcqU42gH0AgpdB/TjuJy3m4ezI7Q/jk3wTQd755mxSDLhQP79KA==", "dev": true, "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "2.23.0", - "@typescript-eslint/typescript-estree": "2.23.0", + "@typescript-eslint/experimental-utils": "3.4.0", + "@typescript-eslint/typescript-estree": "3.4.0", "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/typescript-estree": { - "version": "2.23.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.23.0.tgz", - "integrity": "sha512-pmf7IlmvXdlEXvE/JWNNJpEvwBV59wtJqA8MLAxMKLXNKVRC3HZBXR/SlZLPWTCcwOSg9IM7GeRSV3SIerGVqw==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.4.0.tgz", + "integrity": "sha512-zKwLiybtt4uJb4mkG5q2t6+W7BuYx2IISiDNV+IY68VfoGwErDx/RfVI7SWL4gnZ2t1A1ytQQwZ+YOJbHHJ2rw==", "dev": true, "requires": { "debug": "^4.1.1", @@ -864,7 +871,7 @@ "glob": "^7.1.6", "is-glob": "^4.0.1", "lodash": "^4.17.15", - "semver": "^6.3.0", + "semver": "^7.3.2", "tsutils": "^3.17.1" }, "dependencies": { @@ -884,9 +891,9 @@ "dev": true }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true } } @@ -989,16 +996,6 @@ "sprintf-js": "~1.0.2" } }, - "aria-query": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz", - "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=", - "dev": true, - "requires": { - "ast-types-flow": "0.0.7", - "commander": "^2.11.0" - } - }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -1077,12 +1074,6 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "ast-types-flow": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", - "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=", - "dev": true - }, "astral-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", @@ -1124,26 +1115,6 @@ "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", "dev": true }, - "axobject-query": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.2.tgz", - "integrity": "sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ==", - "dev": true - }, - "babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - } - }, "babel-jest": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", @@ -1360,6 +1331,12 @@ "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=" }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -1556,12 +1533,6 @@ "delayed-stream": "~1.0.0" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -1607,12 +1578,6 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, - "core-js-pure": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz", - "integrity": "sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw==", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1632,24 +1597,6 @@ "yaml": "^1.7.2" } }, - "cross-fetch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-2.2.2.tgz", - "integrity": "sha1-pH/09/xxLauo9qaVoRyUhEDUVyM=", - "dev": true, - "requires": { - "node-fetch": "2.1.2", - "whatwg-fetch": "2.0.4" - }, - "dependencies": { - "node-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz", - "integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U=", - "dev": true - } - } - }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -1677,12 +1624,6 @@ "cssom": "0.3.x" } }, - "damerau-levenshtein": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", - "integrity": "sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug==", - "dev": true - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -2017,18 +1958,18 @@ } }, "eslint-config-prettier": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-4.3.0.tgz", - "integrity": "sha512-sZwhSTHVVz78+kYD3t5pCWSYEdVSBR0PXnwjDRsUs8ytIrK8PLXw+6FKp8r3Z7rx4ZszdetWlXYKOHoUrrwPlA==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.11.0.tgz", + "integrity": "sha512-oB8cpLWSAjOVFEJhhyMZh6NOEOtBVziaqdDQ86+qhDHFbZXoRTM7pNSvFRfW/W/L/LrQ38C99J5CGuRBBzBsdA==", "dev": true, "requires": { "get-stdin": "^6.0.0" } }, "eslint-import-resolver-node": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", - "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", "dev": true, "requires": { "debug": "^2.6.9", @@ -2036,9 +1977,9 @@ } }, "eslint-module-utils": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", - "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", "dev": true, "requires": { "debug": "^2.6.9", @@ -2100,130 +2041,51 @@ } }, "eslint-plugin-eslint-comments": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.1.2.tgz", - "integrity": "sha512-QexaqrNeteFfRTad96W+Vi4Zj1KFbkHHNMMaHZEYcovKav6gdomyGzaxSDSL3GoIyUOo078wRAdYlu1caiauIQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", + "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5", "ignore": "^5.0.5" } }, - "eslint-plugin-flowtype": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-4.6.0.tgz", - "integrity": "sha512-W5hLjpFfZyZsXfo5anlu7HM970JBDqbEshAJUkeczP6BFCIfJXuiIBQXyberLRtOStT0OGPF8efeTbxlHk4LpQ==", - "dev": true, - "requires": { - "lodash": "^4.17.15" - } - }, "eslint-plugin-github": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-2.0.0.tgz", - "integrity": "sha512-bG8rnKk8wCEN4dnKYx4kMCxeFaA2Rtxb0Sh5xAvR1aQKukuqtcp7XjJ+q38LJpC0twYWtiYeBEuJoy0cCh2whw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-github/-/eslint-plugin-github-4.0.1.tgz", + "integrity": "sha512-DkiME1DhBSd4ZarVKiF2qnlSg934UMiMFpo0FKHahSxeiCiAR1pd8Xfv/a64TDxs/mfLwuBZZXf/BM5UsWNyEg==", "dev": true, "requires": { - "@typescript-eslint/eslint-plugin": "^1.3.0", - "@typescript-eslint/parser": "^1.3.0", - "babel-eslint": ">=8.2.0", - "eslint-config-prettier": "^4.0.0", + "@typescript-eslint/eslint-plugin": ">=2.25.0", + "@typescript-eslint/parser": ">=2.25.0", + "eslint-config-prettier": ">=6.10.1", "eslint-plugin-eslint-comments": ">=3.0.1", - "eslint-plugin-flowtype": ">=2.49.3", - "eslint-plugin-graphql": ">=3.0.1", - "eslint-plugin-import": ">=2.11.0", - "eslint-plugin-jest": ">=21.15.0", - "eslint-plugin-jsx-a11y": ">=6.0.0", - "eslint-plugin-prettier": ">=2.6.0", - "eslint-plugin-react": ">=7.7.0", - "eslint-plugin-relay": ">=1.0.0", + "eslint-plugin-import": ">=2.20.1", + "eslint-plugin-prettier": ">=3.1.2", "eslint-rule-documentation": ">=1.0.0", - "inquirer": "^6.0.0", "prettier": ">=1.12.0", - "read-pkg-up": "^4.0.0", - "svg-element-attributes": "^1.2.1" - }, - "dependencies": { - "@typescript-eslint/parser": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.13.0.tgz", - "integrity": "sha512-ITMBs52PCPgLb2nGPoeT4iU3HdQZHcPaZVw+7CsFagRJHUhyeTgorEwHXhFf3e7Evzi8oujKNpHc8TONth8AdQ==", - "dev": true, - "requires": { - "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "1.13.0", - "@typescript-eslint/typescript-estree": "1.13.0", - "eslint-visitor-keys": "^1.0.0" - }, - "dependencies": { - "@typescript-eslint/experimental-utils": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", - "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "1.13.0", - "eslint-scope": "^4.0.0" - } - }, - "@typescript-eslint/typescript-estree": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", - "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", - "dev": true, - "requires": { - "lodash.unescape": "4.0.1", - "semver": "5.5.0" - } - } - } - }, - "eslint-plugin-jest": { - "version": "23.8.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.8.2.tgz", - "integrity": "sha512-xwbnvOsotSV27MtAe7s8uGWOori0nUsrXh2f1EnpmXua8sDfY6VZhHAhHg2sqK7HBNycRQExF074XSZ7DvfoFg==", - "dev": true, - "requires": { - "@typescript-eslint/experimental-utils": "^2.5.0" - } - }, - "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - } - } - }, - "eslint-plugin-graphql": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-graphql/-/eslint-plugin-graphql-3.1.1.tgz", - "integrity": "sha512-VNu2AipS8P1BAnE/tcJ2EmBWjFlCnG+1jKdUlFNDQjocWZlFiPpMu9xYNXePoEXK+q+jG51M/6PdhOjEgJZEaQ==", - "dev": true, - "requires": { - "graphql-config": "^2.0.1", - "lodash": "^4.11.1" + "svg-element-attributes": ">=1.3.1" } }, "eslint-plugin-import": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", - "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", + "version": "2.21.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.21.2.tgz", + "integrity": "sha512-FEmxeGI6yaz+SnEB6YgNHlQK1Bs2DKLM+YF+vuTk5H8J9CLbJLtlPvRFgZZ2+sXiKAlN5dpdlrWOjK8ZoZJpQA==", "dev": true, "requires": { - "array-includes": "^3.0.3", - "array.prototype.flat": "^1.2.1", + "array-includes": "^3.1.1", + "array.prototype.flat": "^1.2.3", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.1", + "eslint-import-resolver-node": "^0.3.3", + "eslint-module-utils": "^2.6.0", "has": "^1.0.3", "minimatch": "^3.0.4", - "object.values": "^1.1.0", + "object.values": "^1.1.1", "read-pkg-up": "^2.0.0", - "resolve": "^1.12.0" + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" }, "dependencies": { "doctrine": { @@ -2329,6 +2191,15 @@ "find-up": "^2.0.0", "read-pkg": "^2.0.0" } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, @@ -2370,78 +2241,15 @@ } } }, - "eslint-plugin-jsx-a11y": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.3.tgz", - "integrity": "sha512-CawzfGt9w83tyuVekn0GDPU9ytYtxyxyFZ3aSWROmnRRFQFT2BiPJd7jvRdzNDi6oLWaS2asMeYSNMjWTV4eNg==", - "dev": true, - "requires": { - "@babel/runtime": "^7.4.5", - "aria-query": "^3.0.0", - "array-includes": "^3.0.3", - "ast-types-flow": "^0.0.7", - "axobject-query": "^2.0.2", - "damerau-levenshtein": "^1.0.4", - "emoji-regex": "^7.0.2", - "has": "^1.0.3", - "jsx-ast-utils": "^2.2.1" - } - }, "eslint-plugin-prettier": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz", - "integrity": "sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz", + "integrity": "sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==", "dev": true, "requires": { "prettier-linter-helpers": "^1.0.0" } }, - "eslint-plugin-react": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz", - "integrity": "sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ==", - "dev": true, - "requires": { - "array-includes": "^3.1.1", - "doctrine": "^2.1.0", - "has": "^1.0.3", - "jsx-ast-utils": "^2.2.3", - "object.entries": "^1.1.1", - "object.fromentries": "^2.0.2", - "object.values": "^1.1.1", - "prop-types": "^15.7.2", - "resolve": "^1.15.1", - "semver": "^6.3.0", - "string.prototype.matchall": "^4.0.2", - "xregexp": "^4.3.0" - }, - "dependencies": { - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "eslint-plugin-relay": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-relay/-/eslint-plugin-relay-1.7.0.tgz", - "integrity": "sha512-JmAMQFr9CxXFLo5BppdN/sleofrE1J/cERIgkFqnYdTq0KAeUNGnz3jO41cqcp1y92/D+KJdmEKFsPfnqnDByQ==", - "dev": true, - "requires": { - "graphql": "^14.0.0 | ^15.0.0-rc.1" - } - }, "eslint-rule-documentation": { "version": "1.0.23", "resolved": "https://registry.npmjs.org/eslint-rule-documentation/-/eslint-rule-documentation-1.0.23.tgz", @@ -2509,15 +2317,15 @@ } }, "estimo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estimo/-/estimo-2.0.2.tgz", - "integrity": "sha512-kMWfSqqQzKryrwS/E6rxR95l+HJAUrIo+NYnOD/6nvbaSBj5/uiQer+5VVkN0l7NFZBbcjgq0hH2wAytptHkUQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/estimo/-/estimo-2.0.4.tgz", + "integrity": "sha512-to1uzlbJwvTO0WEMXsmTP4TC/FiUMEOoF0twuEviuIe8zLrwyijkukGH3pJ3i9ZOExp+ldLE1rhXePOftzUbFQ==", "dev": true, "requires": { "nanoid": "^2.1.11", - "puppeteer-core": "^2.1.0", + "puppeteer-core": "^2.1.1", "tracium": "^0.2.1", - "yargs": "^15.1.0" + "yargs": "^15.3.0" }, "dependencies": { "ansi-regex": { @@ -2640,9 +2448,9 @@ } }, "yargs": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.0.tgz", - "integrity": "sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA==", + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", "dev": true, "requires": { "cliui": "^6.0.0", @@ -2655,13 +2463,13 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.0" + "yargs-parser": "^18.1.1" } }, "yargs-parser": { - "version": "18.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.0.tgz", - "integrity": "sha512-o/Jr6JBOv6Yx3pL+5naWSoIA2jJ+ZkMYQG/ie9qFbukBe4uzmBatlXFOiu/tNKRWEtyf+n5w7jc/O16ufqOTdQ==", + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -2861,15 +2669,26 @@ } }, "extract-zip": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz", - "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", + "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", "dev": true, "requires": { - "concat-stream": "1.6.2", - "debug": "2.6.9", - "mkdirp": "0.5.1", - "yauzl": "2.4.1" + "concat-stream": "^1.6.2", + "debug": "^2.6.9", + "mkdirp": "^0.5.4", + "yauzl": "^2.10.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } } }, "extsprintf": { @@ -2980,9 +2799,9 @@ } }, "fd-slicer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", - "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", "dev": true, "requires": { "pend": "~1.2.0" @@ -3779,44 +3598,6 @@ "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true }, - "graphql": { - "version": "15.0.0-rc.2", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-15.0.0-rc.2.tgz", - "integrity": "sha512-X9ZybETBiZ5zndyXm/Yn3dd0nJqiCNZ7w06lnd0zMiCtBR/KQGgxJmnf47Y/P/Fy7JXM4QDF+MeeoH724yc3DQ==", - "dev": true - }, - "graphql-config": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-2.2.1.tgz", - "integrity": "sha512-U8+1IAhw9m6WkZRRcyj8ZarK96R6lQBQ0an4lp76Ps9FyhOXENC5YQOxOFGm5CxPrX2rD0g3Je4zG5xdNJjwzQ==", - "dev": true, - "requires": { - "graphql-import": "^0.7.1", - "graphql-request": "^1.5.0", - "js-yaml": "^3.10.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.4" - } - }, - "graphql-import": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/graphql-import/-/graphql-import-0.7.1.tgz", - "integrity": "sha512-YpwpaPjRUVlw2SN3OPljpWbVRWAhMAyfSba5U47qGMOSsPLi2gYeJtngGpymjm9nk57RFWEpjqwh4+dpYuFAPw==", - "dev": true, - "requires": { - "lodash": "^4.17.4", - "resolve-from": "^4.0.0" - } - }, - "graphql-request": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-1.8.2.tgz", - "integrity": "sha512-dDX2M+VMsxXFCmUX0Vo0TopIZIX4ggzOtiCsThgtrKR4niiaagsGTDIHj3fsOMFETpa064vzovI+4YV4QnMbcg==", - "dev": true, - "requires": { - "cross-fetch": "2.2.2" - } - }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", @@ -4063,17 +3844,6 @@ } } }, - "internal-slot": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", - "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", - "dev": true, - "requires": { - "es-abstract": "^1.17.0-next.1", - "has": "^1.0.3", - "side-channel": "^1.0.2" - } - }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -4967,16 +4737,6 @@ "verror": "1.10.0" } }, - "jsx-ast-utils": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz", - "integrity": "sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==", - "dev": true, - "requires": { - "array-includes": "^3.0.3", - "object.assign": "^4.1.0" - } - }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -5209,9 +4969,9 @@ } }, "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", "dev": true }, "mime-db": { @@ -5484,30 +5244,6 @@ "object-keys": "^1.0.11" } }, - "object.entries": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", - "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, - "object.fromentries": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", - "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - } - }, "object.getownpropertydescriptors": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", @@ -5886,9 +5622,9 @@ "dev": true }, "prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", + "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", "dev": true }, "prettier-linter-helpers": { @@ -6014,9 +5750,9 @@ "dev": true }, "react": { - "version": "16.13.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.13.0.tgz", - "integrity": "sha512-TSavZz2iSLkq5/oiE7gnFzmURKZMltmi193rm5HEoUDAXpzT9Kzw6oNZnGoai/4+fUnm7FqS5dwgUL34TujcWQ==", + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", + "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", "dev": true, "requires": { "loose-envify": "^1.1.0", @@ -6108,16 +5844,6 @@ "safe-regex": "^1.1.0" } }, - "regexp.prototype.flags": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", - "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -6397,16 +6123,6 @@ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", "dev": true }, - "side-channel": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", - "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", - "dev": true, - "requires": { - "es-abstract": "^1.17.0-next.1", - "object-inspect": "^1.7.0" - } - }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -6864,20 +6580,6 @@ "strip-ansi": "^5.1.0" } }, - "string.prototype.matchall": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", - "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "has-symbols": "^1.0.1", - "internal-slot": "^1.0.2", - "regexp.prototype.flags": "^1.3.0", - "side-channel": "^1.0.2" - } - }, "string.prototype.trimleft": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", @@ -7122,6 +6824,29 @@ "yargs-parser": "10.x" } }, + "tsconfig-paths": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", + "integrity": "sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, "tslib": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", @@ -7346,12 +7071,6 @@ "iconv-lite": "0.4.24" } }, - "whatwg-fetch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz", - "integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng==", - "dev": true - }, "whatwg-mimetype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", @@ -7448,15 +7167,6 @@ "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", "dev": true }, - "xregexp": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz", - "integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==", - "dev": true, - "requires": { - "@babel/runtime-corejs3": "^7.8.3" - } - }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", @@ -7520,12 +7230,13 @@ } }, "yauzl": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", - "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "dev": true, "requires": { - "fd-slicer": "~1.0.1" + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" } } } diff --git a/package.json b/package.json index a4a4244..29efb67 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,11 @@ "license": "ISC", "scripts": { "format": "prettier --write **/*.ts", + "format-check": "prettier --check **/*.ts", "lint": "eslint src/**/*.ts", - "test": "jest", "build": "ncc build src/main.ts -o dist", - "size-build": "npm run build", - "size": "npm run size-build && size-limit" + "test": "jest", + "size": "npm run build && size-limit" }, "size-limit": [ { @@ -28,21 +28,22 @@ "markdown-table": "^2.0.0" }, "devDependencies": { - "@size-limit/file": "^4.3.1", - "@size-limit/time": "^4.3.1", "@types/jest": "^24.0.23", "@types/node": "^12.7.12", - "@typescript-eslint/parser": "^2.8.0", + "@typescript-eslint/parser": "^3.1.0", "@zeit/ncc": "^0.22.1", "eslint": "^5.16.0", - "eslint-plugin-github": "^2.0.0", + "eslint-plugin-prettier": "^3.1.3", + "eslint-plugin-github": "^4.0.1", "eslint-plugin-jest": "^22.21.0", "jest": "^24.9.0", "jest-circus": "^24.9.0", "js-yaml": "^3.13.1", - "prettier": "^1.19.1", - "size-limit": "^4.3.1", + "prettier": "^2.0.4", "ts-jest": "^24.2.0", - "typescript": "^3.6.4" + "typescript": "^3.6.4", + "size-limit": "^4.3.1", + "@size-limit/file": "^4.3.1", + "@size-limit/time": "^4.3.1" } } diff --git a/src/SizeLimit.ts b/src/SizeLimit.ts index 15f0c50..073cf66 100644 --- a/src/SizeLimit.ts +++ b/src/SizeLimit.ts @@ -1,159 +1,61 @@ -// @ts-ignore -import bytes from "bytes"; +import { exec } from "@actions/exec"; +import hasYarn from "has-yarn"; +import SizeLimitParser, { Result } from "./SizeLimitParser"; -interface IResult { - name: string; - size: number; - running?: number; - loading?: number; - total?: number; -} - -const EmptyResult = { - name: "-", - size: 0, - running: 0, - loading: 0, - total: 0 -}; +const INSTALL_STEP = "install"; +const BUILD_STEP = "build"; class SizeLimit { - static SIZE_RESULTS_HEADER = ["Path", "Size"]; - - static TIME_RESULTS_HEADER = [ - "Path", - "Size", - "Loading time (3g)", - "Running time (snapdragon)", - "Total time" - ]; + parser: SizeLimitParser; - private formatBytes(size: number): string { - return bytes.format(size, { unitSeparator: " " }); + constructor(parser: SizeLimitParser) { + this.parser = parser; } - private formatTime(seconds: number): string { - if (seconds >= 1) { - return `${Math.ceil(seconds * 10) / 10} s`; - } + async exec( + ref?: string | null, + skipStep?: string | null, + buildScript?: string | null + ): Promise<{ status: number; results: { [name: string]: Result } }> { + const manager = hasYarn() ? "yarn" : "npm"; + let output = ""; - return `${Math.ceil(seconds * 1000)} ms`; - } + if (ref) { + try { + await exec(`git fetch origin ${ref} --depth=1`); + } catch (error) { + console.log("Fetch failed", error.message); + } - private formatChange(base: number = 0, current: number = 0): string { - if (current === 0) { - return "-100%"; + await exec(`git checkout -f ${ref}`); } - const value = ((current - base) / current) * 100; - const formatted = - (Math.sign(value) * Math.ceil(Math.abs(value) * 100)) / 100; - - if (value > 0) { - return `+${formatted}% 🔺`; + if (skipStep !== INSTALL_STEP && skipStep !== BUILD_STEP) { + await exec(`${manager} install`); } - if (value === 0) { - return `${formatted}%`; + if (skipStep !== BUILD_STEP) { + const script = buildScript || "build"; + await exec(`${manager} run ${script}`); } - return `${formatted}% 🔽`; - } - - private formatLine(value: string, change: string) { - return `${value} (${change})`; - } - - private formatSizeResult( - name: string, - base: IResult, - current: IResult - ): Array { - return [ - name, - this.formatLine( - this.formatBytes(current.size), - this.formatChange(base.size, current.size) - ) - ]; - } - - private formatTimeResult( - name: string, - base: IResult, - current: IResult - ): Array { - return [ - name, - this.formatLine( - this.formatBytes(current.size), - this.formatChange(base.size, current.size) - ), - this.formatLine( - this.formatTime(current.loading), - this.formatChange(base.loading, current.loading) - ), - this.formatLine( - this.formatTime(current.running), - this.formatChange(base.running, current.running) - ), - this.formatTime(current.total) - ]; - } - - parseResults(output: string): { [name: string]: IResult } { - const results = JSON.parse(output); - - return results.reduce( - (current: { [name: string]: IResult }, result: any) => { - let time = {}; - - if (result.loading !== undefined && result.running !== undefined) { - const loading = +result.loading; - const running = +result.running; - - time = { - running, - loading, - total: loading + running - }; + const status = await exec("npx size-limit --json", [], { + windowsVerbatimArguments: true, + ignoreReturnCode: true, + listeners: { + stdout: (data: Buffer) => { + output += data.toString(); } - - return { - ...current, - [result.name]: { - name: result.name, - size: +result.size, - ...time - } - }; - }, - {} - ); - } - - formatResults( - base: { [name: string]: IResult }, - current: { [name: string]: IResult } - ): Array> { - const names = [...new Set([...Object.keys(base), ...Object.keys(current)])]; - const isSize = names.some( - (name: string) => current[name] && current[name].total === undefined - ); - const header = isSize - ? SizeLimit.SIZE_RESULTS_HEADER - : SizeLimit.TIME_RESULTS_HEADER; - const fields = names.map((name: string) => { - const baseResult = base[name] || EmptyResult; - const currentResult = current[name] || EmptyResult; - - if (isSize) { - return this.formatSizeResult(name, baseResult, currentResult); } - return this.formatTimeResult(name, baseResult, currentResult); }); - return [header, ...fields]; + const results = this.parser.parse(output); + + return { + status, + results + }; } } + export default SizeLimit; diff --git a/src/SizeLimitParser.ts b/src/SizeLimitParser.ts new file mode 100644 index 0000000..86fe1da --- /dev/null +++ b/src/SizeLimitParser.ts @@ -0,0 +1,159 @@ +// @ts-ignore +import bytes from "bytes"; + +export interface Result { + name: string; + size: number; + running?: number; + loading?: number; + total?: number; +} + +class SizeLimitParser { + static SIZE_RESULTS_HEADER = ["Path", "Size"]; + + static TIME_RESULTS_HEADER = [ + "Path", + "Size", + "Loading time (3g)", + "Running time (snapdragon)", + "Total time" + ]; + + private formatBytes(size: number): string { + return bytes.format(size, { unitSeparator: " " }); + } + + private formatTime(seconds: number = 0): string { + if (seconds >= 1) { + return `${Math.ceil(seconds * 10) / 10} s`; + } + + return `${Math.ceil(seconds * 1000)} ms`; + } + + private formatChange(base: number = 0, current: number = 0): string { + if (current === 0) { + return "-100%"; + } + + const value = ((current - base) / current) * 100; + const formatted = + (Math.sign(value) * Math.ceil(Math.abs(value) * 100)) / 100; + + if (value > 0) { + return `+${formatted}% 🔺`; + } + + if (value === 0) { + return `${formatted}%`; + } + + return `${formatted}% 🔽`; + } + + private formatLine(value: string, change: string) { + return `${value} (${change})`; + } + + private formatSizeResult( + name: string, + base: Result, + current: Result + ): Array { + return [ + name, + this.formatLine( + this.formatBytes(current.size), + this.formatChange(base.size, current.size) + ) + ]; + } + + private formatTimeResult( + name: string, + base: Result, + current: Result + ): Array { + return [ + name, + this.formatLine( + this.formatBytes(current.size), + this.formatChange(base.size, current.size) + ), + this.formatLine( + this.formatTime(current.loading), + this.formatChange(base.loading, current.loading) + ), + this.formatLine( + this.formatTime(current.running), + this.formatChange(base.running, current.running) + ), + this.formatTime(current.total) + ]; + } + + parse(output: string): { [name: string]: Result } { + const results = JSON.parse(output); + + return results.reduce( + (current: { [name: string]: Result }, result: any) => { + let time = {}; + + if (result.loading !== undefined && result.running !== undefined) { + const loading = +result.loading; + const running = +result.running; + + time = { + running, + loading, + total: loading + running + }; + } + + return { + ...current, + [result.name]: { + name: result.name, + size: +result.size, + ...time + } + }; + }, + {} + ); + } + + diff( + base: { [name: string]: Result }, + current: { [name: string]: Result } + ): Array> { + const empty = { + name: "-", + size: 0, + running: 0, + loading: 0, + total: 0 + }; + const names = [...new Set([...Object.keys(base), ...Object.keys(current)])]; + const isSize = names.some( + (name: string) => current[name] && current[name].total === undefined + ); + const header = isSize + ? SizeLimitParser.SIZE_RESULTS_HEADER + : SizeLimitParser.TIME_RESULTS_HEADER; + + const fields = names.map((name: string) => { + const baseResult = base[name] || empty; + const currentResult = current[name] || empty; + + if (isSize) { + return this.formatSizeResult(name, baseResult, currentResult); + } + return this.formatTimeResult(name, baseResult, currentResult); + }); + + return [header, ...fields]; + } +} +export default SizeLimitParser; diff --git a/src/SizeLimitReporter.ts b/src/SizeLimitReporter.ts new file mode 100644 index 0000000..9f139fc --- /dev/null +++ b/src/SizeLimitReporter.ts @@ -0,0 +1,86 @@ +import { GitHub } from "@actions/github"; +import table from "markdown-table"; + +class SizeLimitReporter { + octokit: GitHub; + + static HEADING = "## size-limit report 📦"; + + constructor(octokit: GitHub) { + this.octokit = octokit; + } + + getBody(isInvalid: boolean, diffResults: Array>): string { + return [ + SizeLimitReporter.HEADING, + `**Status:** ${isInvalid ? "❌" : "✅"}`, + `
`, + `Toggle table`, + "

", + "", + table(diffResults), + "", + "

", + `
` + ].join("\r\n"); + } + + async fetchPrevious( + repo: { owner: string; repo: string }, + issueNumber: number + ) { + const comments = await this.octokit.paginate( + "GET /repos/:owner/:repo/issues/:issue_number/comments", + { + ...repo, + issue_number: issueNumber + } + ); + + return comments.find(comment => + comment.body.startsWith(SizeLimitReporter.HEADING) + ); + } + + create( + repo: { owner: string; repo: string }, + issueNumber: number, + body: string + ) { + return this.octokit.issues.createComment({ + ...repo, + issue_number: issueNumber, + body + }); + } + + update( + repo: { owner: string; repo: string }, + commentId: number, + body: string + ) { + return this.octokit.issues.updateComment({ + ...repo, + comment_id: commentId, + body + }); + } + + async comment( + repo: { owner: string; repo: string }, + issueNumber: number, + isInvalid: boolean, + diffResults: Array> + ) { + const body = this.getBody(isInvalid, diffResults); + const comment = await this.fetchPrevious(repo, issueNumber); + + if (comment) { + return this.update(repo, comment.id, body); + } + + return this.create(repo, issueNumber, body); + } +} + +export default SizeLimitReporter; diff --git a/src/Term.ts b/src/Term.ts deleted file mode 100644 index e9fa040..0000000 --- a/src/Term.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { exec } from "@actions/exec"; -import hasYarn from "has-yarn"; - -const INSTALL_STEP = "install"; -const BUILD_STEP = "build"; - -class Term { - async execSizeLimit( - branch?: string, - skipStep?: string, - buildScript?: string - ): Promise<{ status: number; output: string }> { - const manager = hasYarn() ? "yarn" : "npm"; - let output = ""; - - if (branch) { - try { - await exec(`git fetch origin ${branch} --depth=1`); - } catch (error) { - console.log("Fetch failed", error.message); - } - - await exec(`git checkout -f ${branch}`); - } - - if (skipStep !== INSTALL_STEP && skipStep !== BUILD_STEP) { - await exec(`${manager} install`); - } - - if (skipStep !== BUILD_STEP) { - const script = buildScript || "build"; - await exec(`${manager} run ${script}`); - } - - const status = await exec("npx size-limit --json", [], { - windowsVerbatimArguments: true, - ignoreReturnCode: true, - listeners: { - stdout: (data: Buffer) => { - output += data.toString(); - } - } - }); - - return { - status, - output - }; - } -} - -export default Term; diff --git a/src/main.ts b/src/main.ts index 2601d23..daf888c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,33 +1,8 @@ import { getInput, setFailed } from "@actions/core"; import { context, GitHub } from "@actions/github"; -// @ts-ignore -import table from "markdown-table"; -import Term from "./Term"; import SizeLimit from "./SizeLimit"; - -const SIZE_LIMIT_URL = "https://github.com/ai/size-limit"; -const SIZE_LIMIT_HEADING = `## [size-limit](${SIZE_LIMIT_URL}) report`; - -async function fetchPreviousComment( - octokit: GitHub, - repo: { owner: string; repo: string }, - pr: { number: number } -) { - // TODO: replace with octokit.issues.listComments when upgraded to v17 - const commentList = await octokit.paginate( - "GET /repos/:owner/:repo/issues/:issue_number/comments", - { - ...repo, - // eslint-disable-next-line camelcase - issue_number: pr.number - } - ); - - const sizeLimitComment = commentList.find(comment => - comment.body.startsWith(SIZE_LIMIT_HEADING) - ); - return !sizeLimitComment ? null : sizeLimitComment; -} +import SizeLimitParser from "./SizeLimitParser"; +import SizeLimitReporter from "./SizeLimitReporter"; async function run() { try { @@ -44,70 +19,29 @@ async function run() { const skipStep = getInput("skip_step"); const buildScript = getInput("build_script"); const octokit = new GitHub(token); - const term = new Term(); - const limit = new SizeLimit(); + const parser = new SizeLimitParser(); + const limit = new SizeLimit(parser); + const reporter = new SizeLimitReporter(octokit); - const { status, output } = await term.execSizeLimit( - null, - skipStep, - buildScript - ); - const { output: baseOutput } = await term.execSizeLimit( + const { status, results } = await limit.exec(null, skipStep, buildScript); + const { results: baseResults } = await limit.exec( pr.base.ref, null, buildScript ); - - let base; - let current; + const isInvalid = status > 0; + const diffResults = parser.diff(baseResults, results); try { - base = limit.parseResults(baseOutput); - current = limit.parseResults(output); + await reporter.comment(repo, pr.number, isInvalid, diffResults); } catch (error) { console.log( - "Error parsing size-limit output. The output should be a json." + "Error posting comment. This can happen for PR's originating from a fork without write permissions." ); - throw error; - } - - const body = [ - SIZE_LIMIT_HEADING, - table(limit.formatResults(base, current)) - ].join("\r\n"); - - const sizeLimitComment = await fetchPreviousComment(octokit, repo, pr); - - if (!sizeLimitComment) { - try { - await octokit.issues.createComment({ - ...repo, - // eslint-disable-next-line camelcase - issue_number: pr.number, - body - }); - } catch (error) { - console.log( - "Error creating comment. This can happen for PR's originating from a fork without write permissions." - ); - } - } else { - try { - await octokit.issues.updateComment({ - ...repo, - // eslint-disable-next-line camelcase - comment_id: sizeLimitComment.id, - body - }); - } catch (error) { - console.log( - "Error updating comment. This can happen for PR's originating from a fork without write permissions." - ); - } } - if (status > 0) { - setFailed("Size limit has been exceeded."); + if (isInvalid) { + throw new Error("Size limit has been exceeded."); } } catch (error) { setFailed(error.message); diff --git a/tsconfig.json b/tsconfig.json index 9202d50..f6e7cb5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,10 +4,9 @@ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "outDir": "./lib", /* Redirect output structure to the directory. */ "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - "strict": false, /* Enable all strict type-checking options. */ + "strict": true, /* Enable all strict type-checking options. */ "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - "moduleResolution": "node" + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ }, - "exclude": ["node_modules", "**/*.spec.ts"] + "exclude": ["node_modules", "**/*.test.ts"] }