From b3096fbd5076d302d93c2307bf627e12c423e726 Mon Sep 17 00:00:00 2001 From: Justin Beckwith Date: Sun, 12 Jan 2020 21:17:45 -0800 Subject: [PATCH] feat!: use eslint instead of tslint (#400) BREAKING CHANGE: Switch from tslint to eslint. This will impact all lint rules, and tslint specific configuration. --- .cirrus.yml | 12 +- .eslintignore | 2 + .eslintrc.json | 42 + README.md | 4 +- gts-1.1.2.tgz | Bin 0 -> 17782 bytes package-lock.json | 1548 +++++++++++++++----------- package.json | 35 +- src/cli.ts | 44 +- src/format.ts | 108 -- src/index.ts | 18 + src/init.ts | 62 +- src/lint.ts | 98 -- src/util.ts | 36 +- template/index.ts | 29 +- test/fixtures/kitchen/src/server.ts | 2 +- test/{test-kitchen.ts => kitchen.ts} | 35 +- test/test-clean.ts | 6 +- test/test-format.ts | 332 ------ test/test-init.ts | 8 +- test/test-lint.ts | 354 ------ test/test-util.ts | 8 +- tsconfig.json | 5 +- tslint-rules.json | 78 -- tslint.json | 6 - 24 files changed, 1119 insertions(+), 1753 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.json create mode 100644 gts-1.1.2.tgz delete mode 100644 src/format.ts create mode 100644 src/index.ts delete mode 100644 src/lint.ts rename test/{test-kitchen.ts => kitchen.ts} (86%) delete mode 100644 test/test-format.ts delete mode 100644 test/test-lint.ts delete mode 100644 tslint-rules.json delete mode 100644 tslint.json diff --git a/.cirrus.yml b/.cirrus.yml index 13518b55..50e102bd 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,5 +1,5 @@ container: - image: node:10 + image: node:12 windows_task: windows_container: @@ -16,11 +16,19 @@ lint_task: install_script: npm ci test_script: npm run lint +license_task: + install_script: npm ci + test_script: npm run license-check + +system_test_task: + install_script: npm ci + test_script: npm run system-test + test_task: container: matrix: + image: node:13 image: node:12 - image: node:11 image: node:10 image: node:8 install_script: npm ci diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..f0f2a1aa --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +build/ +test/fixtures/ diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..cb20a268 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,42 @@ +{ + "extends": [ + "eslint:recommended", + "plugin:node/recommended", + "prettier" + ], + "plugins": [ + "node", + "prettier" + ], + "rules": { + "prettier/prettier": "error", + "block-scoped-var": "error", + "eqeqeq": "error", + "no-warning-comments": "warn", + "no-var": "error", + "prefer-const": "error" + }, + "overrides": [ + { + "files": "**/*.ts", + "parser": "@typescript-eslint/parser", + "extends": [ + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@typescript-eslint/no-non-null-assertion": "off", + "node/no-missing-import": "off", + "node/no-unsupported-features/es-syntax": "off", + "@typescript-eslint/explicit-function-return-type": "off", + "@typescript-eslint/camelcase": "off", + "node/no-missing-require": "off", + "no-dupe-class-members": "off", + "node/shebang": "off" + }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + } + } + ] +} diff --git a/README.md b/README.md index eac81a78..d43af9c5 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ To borrow from [standardjs][standardjs-url]: - **Catch style issues & programmer errors early**. Save precious code review time by eliminating back-and-forth between reviewer & contributor. - **Opinionated, but not to a fault**. We recommend you use the default configuration, but if you *need* to customize compiler or linter config, you can. -Under the covers, we use [tslint][tslint-url] to enforce the style guide and provide automated fixes, and [prettier][prettier-url] to re-format code. +Under the covers, we use [eslint][eslint-url] to enforce the style guide and provide automated fixes, and [prettier][prettier-url] to re-format code. ## Getting Started @@ -77,4 +77,4 @@ Made with ❤️ by the Google Node.js team. [snyk-image]: https://snyk.io/test/github/google/gts/badge.svg [snyk-url]: https://snyk.io/test/github/google/gts [standardjs-url]: https://www.npmjs.com/package/standard -[tslint-url]: https://palantir.github.io/tslint/ +[eslint-url]: https://eslint.org/ diff --git a/gts-1.1.2.tgz b/gts-1.1.2.tgz new file mode 100644 index 0000000000000000000000000000000000000000..52e7035b41d8dacce5bfbcb3003079b9f24249dc GIT binary patch literal 17782 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 2.1.2 < 3" } }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + }, "ignore-walk": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", @@ -1634,6 +1753,15 @@ "minimatch": "^3.0.4" } }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "import-lazy": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", @@ -1694,6 +1822,12 @@ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -1706,9 +1840,9 @@ } }, "inquirer": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.3.tgz", - "integrity": "sha512-+OiOVeVydu4hnCGLCSX+wedovR/Yzskv9BFqUNNKq9uU2qg7LCcCo3R86S2E7WLo0y/x2pnEZfZe1CoYnORUAw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.1.tgz", + "integrity": "sha512-V1FFQ3TIO15det8PijPLFR9M9baSlnRs9nL7zWu1MNVA2T9YVl9ZbrHJhYs7e9X8jeMZ3lr2JH/rdHFgNCBdYw==", "requires": { "ansi-escapes": "^4.2.1", "chalk": "^2.4.2", @@ -1814,8 +1948,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "3.0.0", @@ -1826,7 +1959,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -1887,10 +2019,9 @@ "dev": true }, "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" }, "is-symbol": { "version": "1.0.3", @@ -1926,8 +2057,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "istanbul-lib-coverage": { "version": "3.0.0", @@ -1969,14 +2099,6 @@ "spdx-correct": "^3.0.0", "spdx-satisfies": "^5.0.0", "strip-json-comments": "^3.0.0" - }, - "dependencies": { - "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", - "dev": true - } } }, "js-tokens": { @@ -2003,6 +2125,16 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -2034,6 +2166,15 @@ "package-json": "^6.3.0" } }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -2065,6 +2206,11 @@ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", "dev": true }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=" + }, "log-symbols": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", @@ -2149,29 +2295,12 @@ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, "make-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", "requires": { "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } } }, "map-obj": { @@ -2195,6 +2324,11 @@ "yargs-parser": "^10.0.0" } }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, "mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", @@ -2308,11 +2442,14 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } }, "emoji-regex": { "version": "7.0.3", @@ -2406,6 +2543,12 @@ "strip-ansi": "^5.1.0" } }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, "supports-color": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", @@ -2415,15 +2558,6 @@ "has-flag": "^3.0.0" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, "wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", @@ -2468,19 +2602,28 @@ "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 + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, "ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=" }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, "nise": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/nise/-/nise-3.0.1.tgz", @@ -2503,6 +2646,14 @@ "requires": { "object.getownpropertydescriptors": "^2.0.3", "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "node-fetch": { @@ -2520,6 +2671,13 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "normalize-path": { @@ -2543,22 +2701,28 @@ "osenv": "^0.1.5", "semver": "^5.6.0", "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", "requires": { - "path-key": "^2.0.0" + "path-key": "^3.0.0" }, "dependencies": { "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" } } }, @@ -2612,6 +2776,19 @@ "mimic-fn": "^2.1.0" } }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -2639,10 +2816,9 @@ "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" }, "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==" }, "p-limit": { "version": "1.3.0", @@ -2674,13 +2850,14 @@ "registry-auth-token": "^4.0.0", "registry-url": "^5.0.0", "semver": "^6.2.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" } }, "parse-json": { @@ -2702,17 +2879,10 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "path-parse": { "version": "1.0.6", @@ -2736,6 +2906,12 @@ "pify": "^3.0.0" } }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, "picomatch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", @@ -2747,6 +2923,11 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", @@ -2757,11 +2938,18 @@ "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==" }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "requires": { + "fast-diff": "^1.1.2" + } + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, "pump": { "version": "3.0.0", @@ -2772,6 +2960,11 @@ "once": "^1.3.1" } }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, "quick-lru": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", @@ -2792,6 +2985,11 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" } } }, @@ -2832,6 +3030,11 @@ "strip-indent": "^2.0.0" } }, + "regexpp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", + "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==" + }, "registry-auth-token": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz", @@ -2862,13 +3065,18 @@ "dev": true }, "resolve": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.2.tgz", - "integrity": "sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", + "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==", "requires": { "path-parse": "^1.0.6" } }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + }, "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", @@ -2921,9 +3129,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" }, "semver-diff": { "version": "3.1.1", @@ -2931,13 +3139,6 @@ "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", "requires": { "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } } }, "set-blocking": { @@ -2947,19 +3148,17 @@ "dev": true }, "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "requires": { - "shebang-regex": "^3.0.0" + "shebang-regex": "^1.0.0" } }, "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "signal-exit": { "version": "3.0.2", @@ -2967,9 +3166,9 @@ "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, "sinon": { - "version": "8.0.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-8.0.4.tgz", - "integrity": "sha512-cFsmgmvsgFb87e7SV7IcekogITlHX2KmlplyI9Pda0FH1Z8Ms/kWbpLs25Idp0m6ZJ3HEEjhaYYXbcTtWWUn4w==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-8.0.2.tgz", + "integrity": "sha512-8W1S7BnCyvk7SK+Xi15B1QAVLuS81G/NGmWefPb31+ly6xI3fXaug/g5oUdfc8+7ruC4Ay51AxuLlYm8diq6kA==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0", @@ -2979,6 +3178,52 @@ "lolex": "^5.1.2", "nise": "^3.0.1", "supports-color": "^7.1.0" + }, + "dependencies": { + "diff": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", + "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", + "dev": true + } + } + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + } } }, "source-map": { @@ -3126,11 +3371,10 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" }, "strip-indent": { "version": "2.0.0", @@ -3138,9 +3382,9 @@ "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=" }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==" }, "supports-color": { "version": "7.1.0", @@ -3150,6 +3394,39 @@ "has-flag": "^4.0.0" } }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, "teeny-request": { "version": "3.11.3", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-3.11.3.tgz", @@ -3177,6 +3454,11 @@ "minimatch": "^3.0.4" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -3226,83 +3508,20 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" }, - "tslint": { - "version": "5.20.1", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", - "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.8.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - } + "tslib": "^1.8.1" } }, - "tslint-config-prettier": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/tslint-config-prettier/-/tslint-config-prettier-1.18.0.tgz", - "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==" - }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "requires": { - "tslib": "^1.8.1" + "prelude-ls": "~1.1.2" } }, "type-detect": { @@ -3363,6 +3582,14 @@ "xdg-basedir": "^4.0.0" } }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -3383,6 +3610,11 @@ "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", "dev": true }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==" + }, "v8-to-istanbul": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.0.1.tgz", @@ -3413,10 +3645,9 @@ } }, "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "requires": { "isexe": "^2.0.0" } @@ -3477,6 +3708,11 @@ "string-width": "^4.0.0" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + }, "wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -3504,6 +3740,14 @@ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "requires": { + "mkdirp": "^0.5.1" + } + }, "write-file-atomic": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.1.tgz", @@ -3526,16 +3770,10 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, "yargs": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.1.0.tgz", - "integrity": "sha512-T39FNN1b6hCW4SOIk1XyTOWxtXdcen0t+XYrysQmChzSipvhBO8Bj0nK1ozAasdk24dNWuMZvr4k24nz+8HHLg==", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.0.2.tgz", + "integrity": "sha512-GH/X/hYt+x5hOat4LMnCqMd8r5Cv78heOMIJn1hr7QPPBqfeC6p89Y78+WB9yGDvfpCvgasfmWLzNzEioOUD9Q==", "dev": true, "requires": { "cliui": "^6.0.0", @@ -3577,9 +3815,9 @@ } }, "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", "dev": true, "requires": { "p-try": "^2.0.0" diff --git a/package.json b/package.json index 28bcb293..ccbf5114 100644 --- a/package.json +++ b/package.json @@ -9,16 +9,12 @@ }, "files": [ "CHANGELOG.md", - "LICENSE", - "README.md", "build/src", - "build/types", "build/template", "prettier.config.js", "tsconfig-google.json", "tsconfig.json", - "tslint-rules.json", - "tslint.json" + ".eslintrc.json" ], "scripts": { "build": "npm run compile", @@ -26,17 +22,14 @@ "codecov": "c8 report --reporter=json && codecov -f coverage/*.json", "compile": "tsc -p .", "postcompile": "ncp template build/template", - "format-check": "prettier --list-different src/*.ts test/*.ts", - "format": "prettier --write src/*.ts test/*.ts", - "lint": "tslint -c tslint.json --project . -t codeFrame", - "lint-fix": "tslint -c tslint.json --project . -t codeFrame --fix", + "lint": "eslint '**/*.ts'", "prepare": "npm run compile", - "test": "c8 mocha build/test", + "test": "c8 mocha build/test/test-*.js", + "system-test": "c8 mocha build/test/kitchen.js", "pretest": "npm run compile", - "posttest": "npm run lint && npm run format-check && npm run license-check", + "presystem-test": "npm run compile", "license-check": "jsgl --local .", - "check": "gts check", - "fix": "gts fix" + "fix": "eslint --fix '**/*.ts'" }, "engines": { "node": ">=8" @@ -45,22 +38,27 @@ "author": "Google Inc.", "license": "Apache-2.0", "dependencies": { + "@typescript-eslint/eslint-plugin": "^2.9.0", + "@typescript-eslint/parser": "^2.9.0", "chalk": "^3.0.0", - "diff": "^4.0.1", + "eslint": "^6.7.1", + "eslint-config-prettier": "^6.7.0", + "eslint-plugin-node": "^10.0.0", + "eslint-plugin-prettier": "^3.1.1", + "execa": "^3.4.0", "inquirer": "^7.0.0", "meow": "^5.0.0", "ncp": "^2.0.0", "prettier": "^1.19.1", "rimraf": "^3.0.0", - "tslint": "^5.12.0", - "tslint-config-prettier": "^1.18.0", "update-notifier": "^4.0.0", "write-file-atomic": "^3.0.0" }, "devDependencies": { "@npm/types": "^1.0.1", + "@types/chai": "^4.2.7", "@types/cross-spawn": "^6.0.0", - "@types/diff": "^4.0.0", + "@types/eslint": "^6.1.3", "@types/fs-extra": "^8.0.0", "@types/inquirer": "^6.0.0", "@types/meow": "^5.0.0", @@ -72,12 +70,13 @@ "@types/sinon": "^7.0.11", "@types/tmp": "^0.1.0", "@types/update-notifier": "^2.2.0", + "@types/write-file-atomic": "^2.1.2", "assert-rejects": "^1.0.0", "c8": "^7.0.0", + "chai": "^4.2.0", "codecov": "^3.0.1", "cross-spawn": "^7.0.0", "fs-extra": "^8.0.0", - "gts": "^1.0.0", "inline-fixtures": "^1.1.0", "js-green-licenses": "^1.0.0", "mocha": "^7.0.0", diff --git a/src/cli.ts b/src/cli.ts index 625cd20d..88d7e071 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,4 +1,5 @@ #!/usr/bin/env node + /** * Copyright 2017 Google Inc. All Rights Reserved. * @@ -14,13 +15,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import * as path from 'path'; import * as meow from 'meow'; import * as updateNotifier from 'update-notifier'; import { init } from './init'; import { clean } from './clean'; import { isYarnUsed } from './util'; +import * as execa from 'execa'; +// eslint-disable-next-line @typescript-eslint/no-var-requires const packageJson = require('../../package.json'); export interface Logger { @@ -105,15 +109,38 @@ async function run(verb: string, files: string[]): Promise { return init(options); } - const lint: VerbFilesFunction = require('./lint').lint; - const format: VerbFilesFunction = require('./format').format; + const flags = Object.assign([], files); + if (flags.length === 0) { + flags.push('**/*.ts', '**/*.js'); + } + switch (verb) { - case 'check': - const passLint = await lint(options, files); - const passFormat = await format(options, files); - return passLint && passFormat; - case 'fix': - return (await lint(options, files, true)) && format(options, files, true); + case 'check': { + try { + await execa('node', ['./node_modules/eslint/bin/eslint', ...flags], { + stdio: 'inherit', + }); + return true; + } catch (e) { + return false; + } + } + case 'fix': { + const fixFlag = options.dryRun ? '--fix-dry-run' : '--fix'; + try { + await execa( + 'node', + ['./node_modules/eslint/bin/eslint', fixFlag, ...flags], + { + stdio: 'inherit', + } + ); + return true; + } catch (e) { + console.error(e); + return false; + } + } case 'clean': return clean(options); default: @@ -130,6 +157,7 @@ if (cli.input.length < 1) { run(cli.input[0], cli.input.slice(1)).then(success => { if (!success) { + // eslint-disable-next-line no-process-exit process.exit(1); } }); diff --git a/src/format.ts b/src/format.ts deleted file mode 100644 index 0e887905..00000000 --- a/src/format.ts +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright 2017 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import * as prettier from 'prettier'; -import * as fs from 'fs'; -import * as diff from 'diff'; - -import { Options } from './cli'; -import { createProgram } from './lint'; - -const PRETTIER_OPTIONS = require('../../prettier.config.js'); - -export async function format( - options: Options, - files: string[] = [], - fix = false -): Promise { - if (options.dryRun && fix) { - options.logger.log('format: skipping auto fix since --dry-run was passed'); - fix = false; - } - - const program = createProgram(options); - // Obtain a list of source files to format. - // We use program.getRootFileNames to get only the files that match the - // include patterns specified in the given tsconfig.json file (as specified - // through options). This is necessary because we only want to format files - // over which the developer has control (i.e. not auto-generated or - // third-party source files). - const srcFiles = - files.length > 0 - ? files - : program.getRootFileNames().filter(f => !f.endsWith('.d.ts')); - - const result = await checkFormat(srcFiles, options, fix); - if (!result) { - options.logger.log('prettier reported errors... run `gts fix` to address.'); - } - return result; -} - -interface FileConfig { - file: string; - config: prettier.Options | null; -} - -async function mapFilesToFileConfigs( - srcFiles: string[] -): Promise { - const configs = await Promise.all( - srcFiles.map(file => prettier.resolveConfig(file)) - ); - return srcFiles.map((file, index) => { - return { file, config: configs[index] }; - }); -} - -/** - * Checks formatting of the given file list. - * - * @param srcFiles list of source files - * @param options gts options - * @param fix true to auto fix the formatting problems - * @returns false if there are still formatting problems - */ -async function checkFormat(srcFiles: string[], options: Options, fix: boolean) { - const configs = await mapFilesToFileConfigs(srcFiles); - - const checks = configs.map(({ file, config }: FileConfig) => { - config = config || PRETTIER_OPTIONS; - config!.filepath = config!.filepath || file; - const contents = fs.readFileSync(file, 'utf8'); - - let formatted: string; - try { - formatted = prettier.format(contents, config!); - } catch (e) { - options.logger.log(`${file}: ${e}`); - return false; - } - - if (contents === formatted) { - return true; - } - if (fix) { - fs.writeFileSync(file, formatted, 'utf8'); - return true; - } - const patch = diff.createPatch(file, contents, formatted); - options.logger.log(patch); - return false; - }); - - return checks.reduce((sum, flag) => sum && flag, true); -} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..916f57c5 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,18 @@ +/** + * Copyright 2019 LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as cfg from '../.eslintrc.json'; +module.exports = cfg; diff --git a/src/init.ts b/src/init.ts index e882007c..657c9989 100644 --- a/src/init.ts +++ b/src/init.ts @@ -33,6 +33,7 @@ import { Options } from './cli'; import { PackageJson } from '@npm/types'; import chalk = require('chalk'); +// eslint-disable-next-line @typescript-eslint/no-var-requires const pkg = require('../../package.json'); const ncpp = util.promisify(ncp); @@ -108,6 +109,7 @@ export async function addScripts( } if (install) { + // eslint-disable-next-line require-atomic-updates packageJson.scripts[script] = scripts[script]; edits = true; } @@ -145,6 +147,7 @@ export async function addDependencies( } if (install) { + // eslint-disable-next-line require-atomic-updates packageJson.devDependencies[dep] = deps[dep]; edits = true; } @@ -175,38 +178,10 @@ async function writePackageJson( options.logger.dir(preview); } -export const TSLINT_CONFIG = { - extends: 'gts/tslint.json', - linterOptions: { - exclude: ['**/*.json'], - }, +export const ESLINT_CONFIG = { + extends: './node_modules/gts/build/src/index.js', }; -async function generateTsLintConfig(options: Options): Promise { - return generateConfigFile( - options, - './tslint.json', - formatJson(TSLINT_CONFIG) - ); -} - -async function generateTsConfig(options: Options): Promise { - const config = formatJson({ - extends: './node_modules/gts/tsconfig-google.json', - compilerOptions: { rootDir: '.', outDir: 'build' }, - include: ['src/**/*.ts', 'test/**/*.ts'], - }); - return generateConfigFile(options, './tsconfig.json', config); -} - -async function generatePrettierConfig(options: Options): Promise { - const style = await read( - path.join(__dirname, '../../prettier.config.js'), - 'utf8' - ); - return generateConfigFile(options, './prettier.config.js', style); -} - async function generateConfigFile( options: Options, filename: string, @@ -245,6 +220,31 @@ async function generateConfigFile( } } +async function generateESLintConfig(options: Options): Promise { + return generateConfigFile( + options, + './.eslintrc.json', + formatJson(ESLINT_CONFIG) + ); +} + +async function generateTsConfig(options: Options): Promise { + const config = formatJson({ + extends: './node_modules/gts/tsconfig-google.json', + compilerOptions: { rootDir: '.', outDir: 'build' }, + include: ['src/**/*.ts', 'test/**/*.ts'], + }); + return generateConfigFile(options, './tsconfig.json', config); +} + +async function generatePrettierConfig(options: Options): Promise { + const style = await read( + path.join(__dirname, '../../prettier.config.js'), + 'utf8' + ); + return generateConfigFile(options, './prettier.config.js', style); +} + export async function installDefaultTemplate( options: Options ): Promise { @@ -309,7 +309,7 @@ export async function init(options: Options): Promise { options.logger.log('No edits needed in package.json.'); } await generateTsConfig(options); - await generateTsLintConfig(options); + await generateESLintConfig(options); await generatePrettierConfig(options); await installDefaultTemplate(options); diff --git a/src/lint.ts b/src/lint.ts deleted file mode 100644 index 812a480d..00000000 --- a/src/lint.ts +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Copyright 2017 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import * as fs from 'fs'; -import * as path from 'path'; -import { Configuration, Linter } from 'tslint'; -import * as ts from 'typescript'; - -import { Options } from './cli'; - -/** - * Run tslint with the default configuration. Returns true on success. - * @param options gts options - * @param files files to run linter on - * @param fix automatically fix linter errors. Ignored when options.dryRun is - * set. - */ -export function lint( - options: Options, - files: string[] = [], - fix = false -): boolean { - if (options.dryRun && fix) { - options.logger.log('lint: skipping auto fix since --dry-run was passed'); - fix = false; - } - - if (files.length > 0) { - // manually provided filenames. - const rcs = files.map(file => { - // Different config files may apply to each file. - const configPath = - Configuration.findConfigurationPath(null, file) || - path.join(options.gtsRootDir, 'tslint.json'); - - const configuration = Configuration.loadConfigurationFromPath( - configPath, - '' - ); - const source = fs.readFileSync(file, 'utf8'); - - const linter = new Linter({ fix, formatter: 'codeFrame' }); - linter.lint(file, source, configuration); - const result = linter.getResult(); - if (result.errorCount || result.warningCount) { - options.logger.log(result.output); - return false; - } - return true; - }); - - return rcs.every(rc => rc); // if all files succeeded. - } else { - // Lint the set of files specified by the typescript program config. - const program = createProgram(options); - files = Linter.getFileNames(program); - - const configPath = fs.existsSync( - path.join(options.targetRootDir, 'tslint.json') - ) - ? path.resolve(options.targetRootDir, 'tslint.json') - : path.resolve(options.gtsRootDir, 'tslint.json'); - - const configuration = Configuration.loadConfigurationFromPath(configPath); - - for (const file of files) { - const sourceFile = program.getSourceFile(file); - if (sourceFile) { - const fileContents = sourceFile.getFullText(); - const linter = new Linter({ fix, formatter: 'codeFrame' }, program); - linter.lint(file, fileContents, configuration); - const result = linter.getResult(); - if (result.errorCount || result.warningCount) { - options.logger.log(result.output); - return false; - } - } - } - return true; - } -} - -export function createProgram(options: Options): ts.Program { - const tsconfigPath = path.join(options.targetRootDir, 'tsconfig.json'); - return Linter.createProgram(tsconfigPath); -} diff --git a/src/util.ts b/src/util.ts index 83469312..f04719c8 100644 --- a/src/util.ts +++ b/src/util.ts @@ -19,10 +19,11 @@ import * as path from 'path'; import * as rimraf from 'rimraf'; import { promisify } from 'util'; import * as ncp from 'ncp'; +import * as writeFileAtomic from 'write-file-atomic'; export const readFilep = promisify(fs.readFile); export const rimrafp = promisify(rimraf); -export const writeFileAtomicp = promisify(require('write-file-atomic')); +export const writeFileAtomicp = promisify(writeFileAtomic); export const ncpp = promisify(ncp.ncp); export interface Bag { @@ -48,22 +49,6 @@ export function nop() { /* empty */ } -/** - * Find the tsconfig.json, read it, and return parsed contents. - * @param rootDir Directory where the tsconfig.json should be found. - * If the tsconfig.json file has an "extends" field hop down the dependency tree - * until it ends or a circular reference is found in which case an error will be - * thrown - */ -export async function getTSConfig( - rootDir: string, - customReadFilep?: ReadFileP -): Promise { - customReadFilep = customReadFilep || readFilep; - const readArr = new Set(); - return getBase('tsconfig.json', customReadFilep, readArr, rootDir); -} - /** * Recursively iterate through the dependency chain until we reach the end of * the dependency chain or encounter a circular reference @@ -100,6 +85,7 @@ async function getBase( readFiles, path.dirname(filePath) ); + // eslint-disable-next-line @typescript-eslint/no-use-before-define contents = combineTSConfig(nextFile, contents); } @@ -155,3 +141,19 @@ export function getPkgManagerCommand(isYarnUsed?: boolean): string { (isYarnUsed ? 'yarn' : 'npm') + (process.platform === 'win32' ? '.cmd' : '') ); } + +/** + * Find the tsconfig.json, read it, and return parsed contents. + * @param rootDir Directory where the tsconfig.json should be found. + * If the tsconfig.json file has an "extends" field hop down the dependency tree + * until it ends or a circular reference is found in which case an error will be + * thrown + */ +export async function getTSConfig( + rootDir: string, + customReadFilep?: ReadFileP +): Promise { + customReadFilep = customReadFilep || readFilep; + const readArr = new Set(); + return getBase('tsconfig.json', customReadFilep, readArr, rootDir); +} diff --git a/template/index.ts b/template/index.ts index dca15f39..827e9e33 100644 --- a/template/index.ts +++ b/template/index.ts @@ -1,16 +1,23 @@ -console.log("Try npm run check/fix!"); +console.log('Try npm run check/fix!'); -const longString = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ut aliquet diam.'; +const longString = + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer ut aliquet diam.'; -const trailing = 'Semicolon' +const trailing = 'Semicolon'; - const why = 'am I tabbed?'; +const why = 'am I tabbed?'; -export function doSomeStuff(withThis: string, andThat: string, andThose: string[]) { - //function on one line - if(!andThose.length) {return false;} - console.log(withThis); - console.log(andThat); - console.dir(andThose); +export function doSomeStuff( + withThis: string, + andThat: string, + andThose: string[] +) { + //function on one line + if (!andThose.length) { + return false; + } + console.log(withThis); + console.log(andThat); + console.dir(andThose); } -// TODO: more examples \ No newline at end of file +// TODO: more examples diff --git a/test/fixtures/kitchen/src/server.ts b/test/fixtures/kitchen/src/server.ts index da0e69a3..f463fff9 100644 --- a/test/fixtures/kitchen/src/server.ts +++ b/test/fixtures/kitchen/src/server.ts @@ -1 +1 @@ - const isThisTypeScript = true +const isThisTypeScript = true diff --git a/test/test-kitchen.ts b/test/kitchen.ts similarity index 86% rename from test/test-kitchen.ts rename to test/kitchen.ts index e58d6056..10474e82 100644 --- a/test/test-kitchen.ts +++ b/test/kitchen.ts @@ -2,10 +2,13 @@ import chalk = require('chalk'); import * as cp from 'child_process'; import * as fs from 'fs-extra'; import * as tmp from 'tmp'; -import * as assert from 'assert'; +import { assert } from 'chai'; import * as path from 'path'; +import { describe, it, before, after } from 'mocha'; -const spawn = require('cross-spawn'); +import spawn = require('cross-spawn'); +import execa = require('execa'); +// eslint-disable-next-line @typescript-eslint/no-var-requires const pkg = require('../../package.json'); const keep = !!process.env.GTS_KEEP_TEMPDIRS; const stagingDir = tmp.dirSync({ keep, unsafeCleanup: true }); @@ -15,8 +18,6 @@ const execOpts = { encoding: 'utf8', }; -console.log(`${chalk.blue(`${__filename} staging area: ${stagingPath}`)}`); - describe('🚰 kitchen sink', () => { const fixturesPath = path.join('test', 'fixtures'); const gtsPath = path.join('node_modules', '.bin', 'gts'); @@ -24,7 +25,7 @@ describe('🚰 kitchen sink', () => { // Create a staging directory with temp fixtures used to test on a fresh application. before(() => { - console.log('running before hook.'); + console.log(`${chalk.blue(`${__filename} staging area: ${stagingPath}`)}`); cp.execSync('npm pack'); const tarball = `${pkg.name}-${pkg.version}.tgz`; fs.renameSync(tarball, 'gts.tgz'); @@ -32,8 +33,6 @@ describe('🚰 kitchen sink', () => { console.log('moving packed tar to ', targetPath); fs.moveSync('gts.tgz', targetPath); fs.copySync(fixturesPath, path.join(stagingPath, path.sep)); - console.log(fs.readdirSync(stagingPath)); - console.log(fs.readdirSync(path.join(stagingPath, 'kitchen'))); }); // CLEAN UP - remove the staging directory when done. after('cleanup staging', () => { @@ -60,7 +59,7 @@ describe('🚰 kitchen sink', () => { // Ensure config files got generated. fs.accessSync(path.join(kitchenPath, 'tsconfig.json')); - fs.accessSync(path.join(kitchenPath, 'tslint.json')); + fs.accessSync(path.join(kitchenPath, '.eslintrc.json')); fs.accessSync(path.join(kitchenPath, 'prettier.config.js')); // Compilation shouldn't have happened. Hence no `build` directory. @@ -120,23 +119,19 @@ describe('🚰 kitchen sink', () => { ); assert.ok( fs - .readFileSync(path.join(kitchenPath, 'tslint.json'), 'utf8') + .readFileSync(path.join(kitchenPath, '.eslintrc.json'), 'utf8') .endsWith('\n') ); }); - it('should check before fix', () => { - assert.throws( - () => { - cp.execSync('npm run check', execOpts); - }, - // tslint:disable-next-line no-any - (err: any) => { - assert.strictEqual(err.status, 1); - assert.ok(err.stdout.includes('prettier reported errors')); - return true; - } + it('should check before fix', async () => { + const res = await execa( + 'npm', + ['run', 'check'], + Object.assign({}, { reject: false }, execOpts) ); + assert.strictEqual(res.exitCode, 1); + assert.include(res.stdout, 'assigned a value but'); }); it('should fix', () => { diff --git a/test/test-clean.ts b/test/test-clean.ts index 85bc5521..9b8f0b09 100644 --- a/test/test-clean.ts +++ b/test/test-clean.ts @@ -19,13 +19,13 @@ import * as fs from 'fs'; import * as path from 'path'; import { clean } from '../src/clean'; -import { Options } from '../src/cli'; import { nop } from '../src/util'; import { withFixtures } from 'inline-fixtures'; +import { describe, it } from 'mocha'; describe('clean', () => { - const OPTIONS: Options = { + const OPTIONS = { gtsRootDir: path.resolve(__dirname, '../..'), targetRootDir: './', dryRun: false, @@ -35,6 +35,7 @@ describe('clean', () => { }; it('should gracefully error if tsconfig is missing', () => { + // eslint-disable-next-line node/no-unsupported-features/node-builtins return assert.rejects(() => withFixtures({}, async () => { await clean(OPTIONS); @@ -60,6 +61,7 @@ describe('clean', () => { }); it('should ensure that outDir is local to targetRoot', () => { + // eslint-disable-next-line node/no-unsupported-features/node-builtins return assert.rejects(() => withFixtures( { diff --git a/test/test-format.ts b/test/test-format.ts deleted file mode 100644 index 59964180..00000000 --- a/test/test-format.ts +++ /dev/null @@ -1,332 +0,0 @@ -/** - * Copyright 2017 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; - -import { Options } from '../src/cli'; -import * as format from '../src/format'; -import { nop } from '../src/util'; - -import { withFixtures } from 'inline-fixtures'; - -describe('format', () => { - const BAD_CODE = 'export const foo = [ "2" ];'; - const GOOD_CODE = "export const foo = ['2'];\n"; - const CODE_WITH_TABS = `module.exports = { -\treallyLongIdentified: 4, -\tanotherSuperLongIdentifier, -\tthisCannotFitOnTheSameLine -};\n`; - const PRETTIER_FORMAT_MESSAGE = - 'prettier reported errors... run `gts fix` to address.'; - - const OPTIONS: Options = { - gtsRootDir: path.resolve(__dirname, '../..'), - targetRootDir: './', - dryRun: false, - yes: false, - no: false, - logger: { log: console.log, error: console.error, dir: nop }, - }; - - it('format should return true for well-formatted files', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': GOOD_CODE, - }, - async () => { - const result = await format.format(OPTIONS, [], false); - assert.strictEqual(result, true); - } - ); - }); - - it('format should return false for ill-formatted files', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': BAD_CODE, - }, - async () => { - const result = await format.format(OPTIONS, [], false); - assert.strictEqual(result, false); - } - ); - }); - - it('format should only look in root files', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': "import { foo } from './b';\n", - 'b.ts': BAD_CODE, - }, - async () => { - const result = await format.format(OPTIONS, [], false); - assert.strictEqual(result, true); - } - ); - }); - - it('format should auto fix problems', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': BAD_CODE, - }, - async fixturesDir => { - const result = await format.format(OPTIONS, [], true); - assert.strictEqual(result, true); - const contents = fs.readFileSync( - path.join(fixturesDir, 'a.ts'), - 'utf8' - ); - assert.deepStrictEqual(contents, GOOD_CODE); - } - ); - }); - - it('format should format files listed in tsconfig.files', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': GOOD_CODE, - 'b.ts': BAD_CODE, - }, - async () => { - const okay = await format.format(OPTIONS); - assert.strictEqual(okay, true); - } - ); - }); - - it('format should format *.ts files when no files or include has been specified', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({}), - 'a.ts': GOOD_CODE, - 'b.ts': BAD_CODE, - }, - async () => { - const okay = await format.format(OPTIONS); - assert.strictEqual(okay, false); - } - ); - }); - - it('format files listed in tsconfig.files when empty list is provided', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': BAD_CODE, - 'b.ts': BAD_CODE, - }, - async fixturesDir => { - const okay = await format.format(OPTIONS, [], true); - assert.strictEqual(okay, true); - const contents = fs.readFileSync( - path.join(fixturesDir, 'a.ts'), - 'utf8' - ); - assert.deepStrictEqual(contents, GOOD_CODE); - } - ); - }); - - it('skip files listed in exclude', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ exclude: ['b.*'] }), - 'a.ts': GOOD_CODE, - 'b.ts': BAD_CODE, - }, - async () => { - const okay = await format.format(OPTIONS); - assert.strictEqual(okay, true); - } - ); - }); - - it('format globs listed in include', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ include: ['dirb/*'] }), - dira: { 'a.ts': GOOD_CODE }, - dirb: { 'b.ts': BAD_CODE }, - }, - async () => { - const okay = await format.format(OPTIONS); - assert.strictEqual(okay, false); - } - ); - }); - - it('format should not auto fix on dry-run', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': BAD_CODE, - }, - async fixturesDir => { - const optionsWithDryRun = Object.assign({}, OPTIONS, { dryRun: true }); - const okay = await format.format(optionsWithDryRun, [], true); - assert.strictEqual(okay, false); - const contents = fs.readFileSync( - path.join(fixturesDir, 'a.ts'), - 'utf8' - ); - assert.deepStrictEqual(contents, BAD_CODE); - } - ); - }); - - it('format should return false on code with tabs', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['tabs.ts'] }), - 'tabs.ts': CODE_WITH_TABS, - }, - async () => { - const result = await format.format(OPTIONS, [], false); - assert.strictEqual(result, false); - } - ); - }); - - it('format should use user provided prettier.config.js', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['tabs.ts'] }), - 'prettier.config.js': `module.exports = { useTabs: true }`, - 'tabs.ts': CODE_WITH_TABS, - }, - async () => { - const result = await format.format(OPTIONS, [], false); - assert.strictEqual(result, true); - } - ); - }); - - it('format should use user provided .prettierrc', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['tabs.ts'] }), - '.prettierrc': `useTabs: true\n`, - 'tabs.ts': CODE_WITH_TABS, - }, - async () => { - const result = await format.format(OPTIONS, [], false); - assert.strictEqual(result, true); - } - ); - }); - - it('format should prefer the files parameter over options', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': BAD_CODE, - 'good.ts': GOOD_CODE, - }, - async () => { - const result = await format.format(OPTIONS, ['good.ts'], false); - assert.strictEqual(result, true); - } - ); - }); - - it('format should print suggestions for fixes for ill-formatted file', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': BAD_CODE, - }, - async () => { - let output = ''; - const newLogger = Object.assign({}, OPTIONS.logger, { - log: (n: string) => { - output += n; - }, - }); - const options = Object.assign({}, OPTIONS, { logger: newLogger }); - - await format.format(options, [], false); - assert.notStrictEqual(output.search(PRETTIER_FORMAT_MESSAGE), -1); - assert.notStrictEqual(output.indexOf("+export const foo = ['2'];"), -1); - assert.notStrictEqual( - output.indexOf('-export const foo = [ "2" ];'), - -1 - ); - } - ); - }); - - it('formatting output should display unicode characters correctly', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': "//🦄 This is a comment 🌷🏳️‍🌈 — /\nconst variable = '5'", - }, - async () => { - let output = ''; - const newLogger = Object.assign({}, OPTIONS.logger, { - log: (n: string) => { - output += n; - }, - }); - const options = Object.assign({}, OPTIONS, { logger: newLogger }); - - await format.format(options, [], false); - assert.notStrictEqual(output.search(PRETTIER_FORMAT_MESSAGE), -1); - assert.notStrictEqual( - output.indexOf('//🦄 This is a comment 🌷🏳️‍🌈 —'), - -1 - ); - assert.notStrictEqual(output.indexOf("const variable = '5'"), -1); - } - ); - }); - - // Files that cannot be formatted should be left untouched. - it('format should leave the kitty unharmed', () => { - const KITTY = ` - /\\**/\\ - ( o_o )_) - ,(u u ,), - {}{}{}{}{}{}`; - - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': BAD_CODE, - 'kitty.kitty': KITTY, - }, - async fixturesDir => { - const result = await format.format(OPTIONS, ['kitty.kitty'], true); - assert.strictEqual(result, false); // Well structured JS, the kitty is not. - // Well structured or not, the kitty should be left alone. - const contents = fs.readFileSync( - path.join(fixturesDir, 'kitty.kitty'), - 'utf8' - ); - assert.deepStrictEqual(contents, KITTY); - } - ); - }); -}); diff --git a/test/test-init.ts b/test/test-init.ts index af281f7d..35f63295 100644 --- a/test/test-init.ts +++ b/test/test-init.ts @@ -20,13 +20,13 @@ import * as assert from 'assert'; import * as fs from 'fs'; import * as path from 'path'; import { accessSync } from 'fs'; -import { nop, readJsonp as readJson, DefaultPackage } from '../src/util'; -import { Options } from '../src/cli'; import { PackageJson } from '@npm/types'; import { withFixtures, Fixtures } from 'inline-fixtures'; -import * as init from '../src/init'; +import { describe, it, beforeEach, afterEach } from 'mocha'; -const assertRejects = require('assert-rejects'); +import { nop, readJsonp as readJson, DefaultPackage } from '../src/util'; +import { Options } from '../src/cli'; +import * as init from '../src/init'; const OPTIONS: Options = { gtsRootDir: path.resolve(__dirname, '../..'), diff --git a/test/test-lint.ts b/test/test-lint.ts deleted file mode 100644 index 05ce0dd8..00000000 --- a/test/test-lint.ts +++ /dev/null @@ -1,354 +0,0 @@ -/** - * Copyright 2017 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import * as assert from 'assert'; -import * as fs from 'fs'; -import * as path from 'path'; - -import { Options } from '../src/cli'; -import { TSLINT_CONFIG } from '../src/init'; -import * as lint from '../src/lint'; -import * as format from '../src/format'; -import { nop } from '../src/util'; - -import { withFixtures } from 'inline-fixtures'; - -describe('lint', () => { - const OPTIONS: Options = { - gtsRootDir: path.resolve(__dirname, '../..'), - targetRootDir: './', - dryRun: false, - yes: false, - no: false, - logger: { log: nop, error: nop, dir: nop }, - }; - - const BAD_CODE = `throw 'hello world';`; - const GOOD_CODE = `throw new Error('hello world');`; - - // missing semicolon, array-type simple. - const FIXABLE_CODE = 'const x : Array = [];'; - const FIXABLE_CODE_FIXED = 'const x : string[] = [];'; - - it('createProgram should return an object', () => { - return withFixtures({ 'tsconfig.json': '{}' }, async () => { - const program = lint.createProgram(OPTIONS); - assert.ok(program); - }); - }); - - it('lint should return true on good code', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': GOOD_CODE, - }, - async () => { - const okay = lint.lint(OPTIONS); - assert.strictEqual(okay, true); - } - ); - }); - - it('lint should return false on bad code', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': BAD_CODE, - }, - async () => { - const okay = lint.lint(OPTIONS); - assert.strictEqual(okay, false); - } - ); - }); - - it('lint should auto fix fixable errors', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': FIXABLE_CODE, - }, - async fixturesDir => { - const okay = lint.lint(OPTIONS, [], true); - assert.strictEqual(okay, true); - const contents = fs.readFileSync( - path.join(fixturesDir, 'a.ts'), - 'utf8' - ); - assert.deepStrictEqual(contents, FIXABLE_CODE_FIXED); - } - ); - }); - - it('lint should not auto fix on dry-run', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': FIXABLE_CODE, - }, - async fixturesDir => { - const optionsWithDryRun = Object.assign({}, OPTIONS, { dryRun: true }); - const okay = lint.lint(optionsWithDryRun, [], true); - assert.strictEqual(okay, false); - const contents = fs.readFileSync( - path.join(fixturesDir, 'a.ts'), - 'utf8' - ); - assert.deepStrictEqual(contents, FIXABLE_CODE); - } - ); - }); - - it('lint should lint files listed in tsconfig.files', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': GOOD_CODE, - 'b.ts': BAD_CODE, - }, - async () => { - const okay = lint.lint(OPTIONS); - assert.strictEqual(okay, true); - } - ); - }); - - it('lint should lint *.ts files when no files or include has been specified', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({}), - 'a.ts': GOOD_CODE, - 'b.ts': BAD_CODE, - }, - async () => { - const okay = lint.lint(OPTIONS); - assert.strictEqual(okay, false); - } - ); - }); - - it('lint should lint files listed in tsconfig.files when empty list is provided', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': FIXABLE_CODE, - 'b.ts': BAD_CODE, - }, - async fixturesDir => { - const okay = lint.lint(OPTIONS, [], true); - assert.strictEqual(okay, true); - const contents = fs.readFileSync( - path.join(fixturesDir, 'a.ts'), - 'utf8' - ); - assert.deepStrictEqual(contents, FIXABLE_CODE_FIXED); - } - ); - }); - - it('lint should not lint files listed in exclude', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ exclude: ['b.*'] }), - 'a.ts': GOOD_CODE, - 'b.ts': BAD_CODE, - }, - async () => { - const okay = lint.lint(OPTIONS); - assert.strictEqual(okay, true); - } - ); - }); - - it('lint should lint globs listed in include', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ include: ['dirb/*'] }), - dira: { 'a.ts': GOOD_CODE }, - dirb: { 'b.ts': BAD_CODE }, - }, - async () => { - const okay = lint.lint(OPTIONS); - assert.strictEqual(okay, false); - } - ); - }); - - it('lint should lint only specified files', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({}), - dira: { 'a.ts': GOOD_CODE }, - dirb: { 'b.ts': BAD_CODE }, - }, - async () => { - const aOkay = lint.lint(OPTIONS, ['dira/a.ts']); - assert.strictEqual(aOkay, true); - const bOkay = lint.lint(OPTIONS, ['dirb/b.ts']); - assert.strictEqual(bOkay, false); - } - ); - }); - - it('lint should throw for unrecognized files', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({}), - 'a.ts': GOOD_CODE, - }, - async () => { - assert.throws(() => { - lint.lint(OPTIONS, ['z.ts']); - }); - } - ); - }); - - it('lint should prefer user config file over default', async () => { - const CUSTOM_LINT_CODE = 'debugger;'; - - // By default the above should fail lint. - await withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'a.ts': CUSTOM_LINT_CODE, - }, - async () => { - const okay = lint.lint(OPTIONS); - assert.strictEqual(okay, false); - } - ); - - // User should be able to override the default config. - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ files: ['a.ts'] }), - 'tslint.json': JSON.stringify({}), - 'a.ts': CUSTOM_LINT_CODE, - }, - async () => { - const okay = lint.lint(OPTIONS); - assert.strictEqual(okay, true); - } - ); - }); - - it('lint for specific files should use file-specific config', () => { - const CODE_WITH_PARSEINT = 'parseInt(42);'; - let logBuffer = ''; - const optionsWithLog = Object.assign({}, OPTIONS, { - logger: { - log: (...args: string[]) => { - logBuffer += args.join(' '); - }, - error: nop, - dir: nop, - }, - }); - return withFixtures( - { - dira: { - 'a.ts': CODE_WITH_PARSEINT, - // no tslint, so default should apply. - }, - dirb: { 'b.ts': CODE_WITH_PARSEINT, 'tslint.json': JSON.stringify({}) }, - }, - async () => { - const okay = lint.lint(optionsWithLog, ['dira/a.ts', 'dirb/b.ts']); - assert.strictEqual(okay, false); - assert.ok(/dira\/a\.ts/.test(logBuffer)); - assert.ok(!/dirb\/b\.ts/.test(logBuffer)); - } - ); - }); - - it('should not conflict with format', async () => { - const FIXTURE = { - 'tsconfig.json': JSON.stringify({ files: ['far.ts'] }), - 'far.ts': `export function far( - ceiling: string, - vines: string, - sailed: number, - ocean: number, - tumbled: string, -): string { - return 'where the wild things are'; -} -`, - }; - - // tslint should not complain about the trailing comma in functions, - // and let prettier complain. - await withFixtures(FIXTURE, async () => { - const lintOkay = await lint.lint(OPTIONS, [], false); - assert.strictEqual(lintOkay, true); - const formatOkay = await format.format(OPTIONS, [], false); - assert.strictEqual(formatOkay, false); - }); - - const fixtureWithPrettierConfig = { - ...FIXTURE, - 'prettier.config.js': `module.exports = { - singleQuote: true, - trailingComma: 'all', -};`, - }; - - // Both the linter and the formatter should be okay with this. - await withFixtures(fixtureWithPrettierConfig, async () => { - const lintOkay = await lint.lint(OPTIONS, [], false); - assert.strictEqual(lintOkay, true); - const formatOkay = await format.format(OPTIONS, [], false); - assert.strictEqual(formatOkay, true); - }); - }); - - it('should handle json files correctly resolveJsonModule', () => { - return withFixtures( - { - 'tsconfig.json': JSON.stringify({ - include: ['src'], - compilerOptions: { - module: 'commonjs', - resolveJsonModule: true, - esModuleInterop: true, - }, - }), - 'tslint.json': JSON.stringify(TSLINT_CONFIG), - node_modules: { - gts: { - 'tslint-rules.json': fs.readFileSync('tslint-rules.json', 'utf8'), - 'tslint.json': fs.readFileSync('tslint.json', 'utf8'), - }, - }, - src: { - 'a.ts': `import settings from "./test.json";`, - 'test.json': JSON.stringify({ - dry: false, - debug: false, - }), - }, - }, - async () => { - const okay = lint.lint(OPTIONS); - assert.strictEqual(okay, true); - } - ); - }); - - // TODO: test for when tsconfig.json is missing. -}); diff --git a/test/test-util.ts b/test/test-util.ts index d6af8a45..b4998c9b 100644 --- a/test/test-util.ts +++ b/test/test-util.ts @@ -15,8 +15,8 @@ */ import * as assert from 'assert'; import * as path from 'path'; -import { accessSync, PathLike, readFileSync } from 'fs'; - +import { PathLike } from 'fs'; +import { describe, it } from 'mocha'; import { ConfigFile, getTSConfig, @@ -24,8 +24,6 @@ import { getPkgManagerCommand, } from '../src/util'; -import { withFixtures, Fixtures } from 'inline-fixtures'; - /** * Creates a fake promisified readFile function from a map * @param myMap contains a filepath as the key and a ConfigFile object as the @@ -80,6 +78,7 @@ describe('util', () => { myMap.set(PATH_TO_CONFIG2, FAKE_CONFIG2); myMap.set(PATH_TO_CONFIG3, FAKE_CONFIG3); + // eslint-disable-next-line node/no-unsupported-features/node-builtins return assert.rejects( () => getTSConfig(FAKE_DIRECTORY, createFakeReadFilep(myMap)), Error, @@ -159,6 +158,7 @@ describe('util', () => { it('function throws an error when reading a file that does not exist', () => { const myMap = new Map(); + // eslint-disable-next-line node/no-unsupported-features/node-builtins return assert.rejects( () => getTSConfig(FAKE_DIRECTORY, createFakeReadFilep(myMap)), Error, diff --git a/tsconfig.json b/tsconfig.json index b643ac98..dfb3be02 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,8 @@ "extends": "./tsconfig-google.json", "compilerOptions": { "rootDir": ".", - "outDir": "build" + "outDir": "build", + "resolveJsonModule": true }, "include": [ "src/**/*.ts", @@ -12,4 +13,4 @@ "test/fixtures/**/*.*", "template/**/*.*", ] -} \ No newline at end of file +} diff --git a/tslint-rules.json b/tslint-rules.json deleted file mode 100644 index 234de72c..00000000 --- a/tslint-rules.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "rules": { - "array-type": [true, "array-simple"], - "arrow-return-shorthand": true, - "ban": [true, - {"name": ["it", "skip"]}, - {"name": ["it", "only"]}, - {"name": ["it", "async", "skip"]}, - {"name": ["it", "async", "only"]}, - {"name": ["describe", "skip"]}, - {"name": ["describe", "only"]}, - {"name": "parseInt", "message": "tsstyle#type-coercion"}, - {"name": "parseFloat", "message": "tsstyle#type-coercion"}, - {"name": "Array", "message": "tsstyle#array-constructor"}, - {"name": ["*", "innerText"], "message": "Use .textContent instead. tsstyle#browser-oddities"} - ], - "ban-ts-ignore": true, - "ban-types": [true, - ["Object", "Use {} instead."], - ["String", "Use 'string' instead."], - ["Number", "Use 'number' instead."], - ["Boolean", "Use 'boolean' instead."] - ], - "class-name": true, - "curly": [true, "ignore-same-line"], - "deprecation": true, - "forin": true, - "interface-name": [true, "never-prefix"], - "interface-over-type-literal": true, - "jsdoc-format": true, - "label-position": true, - "member-access": [true, "no-public"], - "new-parens": true, - "no-angle-bracket-type-assertion": true, - "no-any": true, - "no-arg": true, - "no-conditional-assignment": true, - "no-construct": true, - "no-debugger": true, - "no-default-export": true, - "no-duplicate-variable": true, - "no-inferrable-types": true, - "no-namespace": [true, "allow-declarations"], - "no-reference": true, - "no-string-throw": true, - "no-return-await": true, - "no-unsafe-finally": true, - "no-unused-expression": true, - "no-var-keyword": true, - "object-literal-shorthand": true, - "only-arrow-functions": [true, "allow-declarations", "allow-named-functions"], - "prefer-const": true, - "radix": true, - "semicolon": [true, "always", "ignore-bound-class-methods"], - "switch-default": true, - "trailing-comma": [ - true, - { - "multiline": { - "objects": "always", - "arrays": "always", - "functions": "never", - "typeLiterals": "ignore" - }, - "esSpecCompliant": true - } - ], - "triple-equals": [true, "allow-null-check"], - "use-isnan": true, - "variable-name": [ - true, - "check-format", - "ban-keywords", - "allow-leading-underscore", - "allow-trailing-underscore" - ] - } -} diff --git a/tslint.json b/tslint.json deleted file mode 100644 index e6584553..00000000 --- a/tslint.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": [ - "./tslint-rules.json", - "tslint-config-prettier" - ] -} \ No newline at end of file