diff --git a/.changeset/brave-fishes-develop.md b/.changeset/brave-fishes-develop.md new file mode 100644 index 0000000..e90949d --- /dev/null +++ b/.changeset/brave-fishes-develop.md @@ -0,0 +1,7 @@ +--- +"@arethetypeswrong/core": minor +"@arethetypeswrong/cli": minor +--- + +- New problem kind: **Internal resolution error** indicates that an import in one of the package’s type declaration files failed to resolve. Either this indicates that runtime resolution errors will occur, or (more likely) the types misrepresent the contents of the JavaScript files. +- Significant API changes. Most significantly, problems are returned as part of `checkPackage`, and `summarizeProblems`/`getSummarizedProblems` have been replaced by a collection of utilities for grouping and filtering problems. diff --git a/package-lock.json b/package-lock.json index 9fb35ae..cb357f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1125,6 +1125,90 @@ "ci-info": "^3.1.0" } }, + "node_modules/@types/marked": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-5.0.0.tgz", + "integrity": "sha512-YcZe50jhltsCq7rc9MNZC/4QB/OnA2Pd6hrOSTOFajtabN+38slqgDDCeE/0F83SjkKBQcsZUj7VLWR0H5cKRA==", + "dev": true + }, + "node_modules/@types/marked-terminal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/marked-terminal/-/marked-terminal-3.1.3.tgz", + "integrity": "sha512-dKgOLKlI5zFb2jTbRcyQqbdrHxeU74DCOkVIZtsoB2sc1ctXZ1iB2uxG2jjAuzoLdvwHP065ijN6Q8HecWdWYg==", + "dev": true, + "dependencies": { + "@types/marked": "^3", + "chalk": "^2.4.1" + } + }, + "node_modules/@types/marked-terminal/node_modules/@types/marked": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-3.0.3.tgz", + "integrity": "sha512-ZgAr847Wl68W+B0sWH7F4fDPxTzerLnRuUXjUpp1n4NjGSs8hgPAjAp7NQIXblG34MXTrf5wWkAK8PVJ2LIlVg==", + "dev": true + }, + "node_modules/@types/marked-terminal/node_modules/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==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@types/marked-terminal/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@types/marked-terminal/node_modules/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==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@types/marked-terminal/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@types/marked-terminal/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@types/marked-terminal/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", @@ -1187,6 +1271,31 @@ "node": ">=6" } }, + "node_modules/ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "dependencies": { + "type-fest": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.11.1.tgz", + "integrity": "sha512-aCuRNRERRVh33lgQaJRlUxZqzfhzwTrsE98Mc3o3VXqmiaQdHacgUtJ0esp+7MvZ92qhtzKPeusaX6vIEcoreA==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1209,6 +1318,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==" + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1365,6 +1479,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1799,7 +1925,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -2624,6 +2749,11 @@ "node": ">=8" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.startcase": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", @@ -2653,6 +2783,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/marked": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.0.tgz", + "integrity": "sha512-z3/nBe7aTI8JDszlYLk7dDVNpngjw0o1ZJtrA9kIfkkHcIF+xH7mO23aISl4WxP83elU+MFROgahqdpd05lMEQ==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/marked-terminal": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", + "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", + "dependencies": { + "ansi-escapes": "^6.2.0", + "cardinal": "^2.1.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", + "node-emoji": "^1.11.0", + "supports-hyperlinks": "^2.3.0" + }, + "engines": { + "node": ">=14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/meow": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz", @@ -2765,6 +2936,14 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/node-fetch": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", @@ -3227,6 +3406,14 @@ "node": ">=8" } }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "dependencies": { + "esprima": "~4.0.0" + } + }, "node_modules/regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -3670,6 +3857,18 @@ "node": ">=8" } }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -4455,12 +4654,16 @@ "@arethetypeswrong/core": "0.0.8", "chalk": "^4.1.2", "cli-table3": "^0.6.3", - "commander": "^10.0.1" + "commander": "^10.0.1", + "marked": "^5.1.0", + "marked-terminal": "^5.2.0" }, "bin": { "attw": "dist/index.js" }, "devDependencies": { + "@types/marked": "^5.0.0", + "@types/marked-terminal": "^3.1.3", "@types/node": "^20.2.5", "@types/node-fetch": "^2.6.4", "typescript": "^5.0.0-dev.20230207" @@ -4509,9 +4712,11 @@ "dependencies": { "@arethetypeswrong/core": "file:../core", "immer": "^9.0.21", + "marked": "^5.1.0", "nprogress": "^0.2.0" }, "devDependencies": { + "@types/marked": "^5.0.0", "@types/nprogress": "^0.2.0", "esbuild": "^0.17.4", "vite": "^4.0.4" @@ -4528,11 +4733,15 @@ "version": "file:packages/cli", "requires": { "@arethetypeswrong/core": "0.0.8", + "@types/marked": "^5.0.0", + "@types/marked-terminal": "^3.1.3", "@types/node": "^20.2.5", "@types/node-fetch": "^2.6.4", "chalk": "^4.1.2", "cli-table3": "^0.6.3", "commander": "^10.0.1", + "marked": "^5.1.0", + "marked-terminal": "^5.2.0", "typescript": "^5.0.0-dev.20230207" }, "dependencies": { @@ -4567,9 +4776,11 @@ "version": "file:packages/web", "requires": { "@arethetypeswrong/core": "file:../core", + "@types/marked": "^5.0.0", "@types/nprogress": "^0.2.0", "esbuild": "^0.17.4", "immer": "^9.0.21", + "marked": "^5.1.0", "nprogress": "^0.2.0", "vite": "^4.0.4" } @@ -5381,6 +5592,80 @@ "ci-info": "^3.1.0" } }, + "@types/marked": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-5.0.0.tgz", + "integrity": "sha512-YcZe50jhltsCq7rc9MNZC/4QB/OnA2Pd6hrOSTOFajtabN+38slqgDDCeE/0F83SjkKBQcsZUj7VLWR0H5cKRA==", + "dev": true + }, + "@types/marked-terminal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/marked-terminal/-/marked-terminal-3.1.3.tgz", + "integrity": "sha512-dKgOLKlI5zFb2jTbRcyQqbdrHxeU74DCOkVIZtsoB2sc1ctXZ1iB2uxG2jjAuzoLdvwHP065ijN6Q8HecWdWYg==", + "dev": true, + "requires": { + "@types/marked": "^3", + "chalk": "^2.4.1" + }, + "dependencies": { + "@types/marked": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-3.0.3.tgz", + "integrity": "sha512-ZgAr847Wl68W+B0sWH7F4fDPxTzerLnRuUXjUpp1n4NjGSs8hgPAjAp7NQIXblG34MXTrf5wWkAK8PVJ2LIlVg==", + "dev": true + }, + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "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": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", @@ -5439,6 +5724,21 @@ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", "dev": true }, + "ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "requires": { + "type-fest": "^3.0.0" + }, + "dependencies": { + "type-fest": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.11.1.tgz", + "integrity": "sha512-aCuRNRERRVh33lgQaJRlUxZqzfhzwTrsE98Mc3o3VXqmiaQdHacgUtJ0esp+7MvZ92qhtzKPeusaX6vIEcoreA==" + } + } + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -5452,6 +5752,11 @@ "color-convert": "^2.0.1" } }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -5569,6 +5874,15 @@ "quick-lru": "^4.0.1" } }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -5907,8 +6221,7 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "extendable-error": { "version": "0.1.7", @@ -6505,6 +6818,11 @@ "p-locate": "^4.1.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.startcase": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", @@ -6525,6 +6843,31 @@ "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", "dev": true }, + "marked": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.0.tgz", + "integrity": "sha512-z3/nBe7aTI8JDszlYLk7dDVNpngjw0o1ZJtrA9kIfkkHcIF+xH7mO23aISl4WxP83elU+MFROgahqdpd05lMEQ==" + }, + "marked-terminal": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", + "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", + "requires": { + "ansi-escapes": "^6.2.0", + "cardinal": "^2.1.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", + "node-emoji": "^1.11.0", + "supports-hyperlinks": "^2.3.0" + }, + "dependencies": { + "chalk": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", + "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==" + } + } + }, "meow": { "version": "6.1.1", "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.1.tgz", @@ -6604,6 +6947,14 @@ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "dev": true }, + "node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "requires": { + "lodash": "^4.17.21" + } + }, "node-fetch": { "version": "2.6.8", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", @@ -6916,6 +7267,14 @@ "strip-indent": "^3.0.0" } }, + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "requires": { + "esprima": "~4.0.0" + } + }, "regenerator-runtime": { "version": "0.13.11", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", @@ -7255,6 +7614,15 @@ "has-flag": "^4.0.0" } }, + "supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + } + }, "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", diff --git a/packages/cli/package.json b/packages/cli/package.json index cc304ed..0efd420 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -38,6 +38,8 @@ }, "type": "module", "devDependencies": { + "@types/marked": "^5.0.0", + "@types/marked-terminal": "^3.1.3", "@types/node": "^20.2.5", "@types/node-fetch": "^2.6.4", "typescript": "^5.0.0-dev.20230207" @@ -46,6 +48,8 @@ "@arethetypeswrong/core": "0.0.8", "chalk": "^4.1.2", "cli-table3": "^0.6.3", - "commander": "^10.0.1" + "commander": "^10.0.1", + "marked": "^5.1.0", + "marked-terminal": "^5.2.0" } } diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 64d2326..36e924d 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -11,6 +11,7 @@ import { createRequire } from "module"; import * as render from "./render/index.js"; import { readConfig } from "./readConfig.js"; import { problemFlags } from "./problemUtils.js"; +import { groupProblemsByKind } from "@arethetypeswrong/core/utils"; const packageJson = createRequire(import.meta.url)("../package.json"); const version = packageJson.version; @@ -67,7 +68,7 @@ particularly ESM-related module resolution issues.` process.env.FORCE_COLOR = "0"; } - let analysis: core.Analysis; + let analysis: core.CheckResult; if (opts.fromNpm) { try { const result = core.parsePackageSpec(fileName); @@ -95,36 +96,31 @@ particularly ESM-related module resolution issues.` if (opts.format === "json") { const result = { analysis } as { - analysis: core.Analysis; + analysis: core.CheckResult; problems?: Partial>; }; - if (analysis.containsTypes) { - result.problems = core.groupByKind(core.getProblems(analysis)); + if (analysis.types) { + result.problems = groupProblemsByKind(analysis.problems); } console.log(JSON.stringify(result)); - if ( - analysis.containsTypes && - core.getProblems(analysis).some((problem) => !opts.ignoreRules?.includes(problem.kind)) - ) + if (analysis.types && analysis.problems.some((problem) => !opts.ignoreRules?.includes(problem.kind))) process.exit(1); return; } console.log(); - if (analysis.containsTypes) { + if (analysis.types) { await render.typed(analysis, opts); - if ( - analysis.containsTypes && - core.getProblems(analysis).some((problem) => !opts.ignoreRules?.includes(problem.kind)) - ) - process.exit(1); + if (analysis.types && analysis.problems.some((problem) => !opts.ignoreRules?.includes(problem.kind))) { + process.exitCode = 1; + } } else { - render.untyped(analysis as core.UntypedAnalysis); + render.untyped(analysis as core.UntypedResult); } }); diff --git a/packages/cli/src/problemUtils.ts b/packages/cli/src/problemUtils.ts index 6bdf3b4..a8b7624 100644 --- a/packages/cli/src/problemUtils.ts +++ b/packages/cli/src/problemUtils.ts @@ -11,55 +11,8 @@ export const problemFlags: Record = { FallbackCondition: "fallback-condition", CJSOnlyExportsDefault: "cjs-only-exports-default", FalseExportDefault: "false-export-default", - UnexpectedESMSyntax: "unexpected-esm-syntax", - UnexpectedCJSSyntax: "unexpected-cjs-syntax", -}; - -export const problemEmoji: Record = { - Wildcard: "❓", - NoResolution: "πŸ’€", - UntypedResolution: "🚫", - FalseCJS: "🎭", - FalseESM: "πŸ‘Ί", - CJSResolvesToESM: "⚠️", - FallbackCondition: "πŸ›", - CJSOnlyExportsDefault: "🀨", - FalseExportDefault: "❗️", - UnexpectedESMSyntax: "🚭", - UnexpectedCJSSyntax: "🚱", -}; - -export const withEmoji: Record = { - Wildcard: `${problemEmoji.Wildcard} Unable to check`, - NoResolution: `${problemEmoji.NoResolution} Failed to resolve`, - UntypedResolution: `${problemEmoji.UntypedResolution} No types`, - FalseCJS: `${problemEmoji.FalseCJS} Masquerading as CJS`, - FalseESM: `${problemEmoji.FalseESM} Masquerading as ESM`, - CJSResolvesToESM: `${problemEmoji.CJSResolvesToESM} ESM (dynamic import only)`, - FallbackCondition: `${problemEmoji.FallbackCondition} Used fallback condition`, - CJSOnlyExportsDefault: `${problemEmoji.CJSOnlyExportsDefault} CJS default export`, - FalseExportDefault: `${problemEmoji.FalseExportDefault} Incorrect default export`, - UnexpectedESMSyntax: `${problemEmoji.UnexpectedESMSyntax} Unexpected ESM syntax`, - UnexpectedCJSSyntax: `${problemEmoji.UnexpectedCJSSyntax} Unexpected CJS syntax`, -}; - -export const noEmoji: Record = { - Wildcard: `Unable to check`, - NoResolution: `Failed to resolve`, - UntypedResolution: `No types`, - FalseCJS: `Masquerading as CJS`, - FalseESM: `Masquerading as ESM`, - CJSResolvesToESM: `ESM (dynamic import only)`, - FallbackCondition: `Used fallback condition`, - CJSOnlyExportsDefault: `CJS default export`, - FalseExportDefault: `Incorrect default export`, - UnexpectedESMSyntax: `Unexpected ESM syntax`, - UnexpectedCJSSyntax: `Unexpected CJS syntax`, -}; - -export const problemShortDescriptions = { - emoji: withEmoji, - noEmoji: noEmoji, + UnexpectedModuleSyntax: "unexpected-module-syntax", + InternalResolutionError: "internal-resolution-error", }; export const resolutionKinds: Record = { diff --git a/packages/cli/src/render/typed.ts b/packages/cli/src/render/typed.ts index fe3f97f..ef0f0b3 100644 --- a/packages/cli/src/render/typed.ts +++ b/packages/cli/src/render/typed.ts @@ -1,18 +1,25 @@ import * as core from "@arethetypeswrong/core"; -import { allResolutionKinds } from "@arethetypeswrong/core/utils"; -import Table, { type GenericTable, type HorizontalTableRow } from "cli-table3"; +import { allResolutionKinds, groupProblemsByKind } from "@arethetypeswrong/core/utils"; import chalk from "chalk"; +import Table, { type GenericTable, type HorizontalTableRow } from "cli-table3"; +import { marked } from "marked"; -import { moduleKinds, problemEmoji, resolutionKinds, problemShortDescriptions, problemFlags } from "../problemUtils.js"; +import { filterProblems, problemAffectsEntrypoint, problemKindInfo } from "@arethetypeswrong/core/problems"; import type { Opts } from "../index.js"; +import { moduleKinds, problemFlags, resolutionKinds } from "../problemUtils.js"; import { tableFlipped } from "./tableFlipped.js"; - -export async function typed(analysis: core.TypedAnalysis, opts: Opts) { - const problems = core - .getProblems(analysis) - .filter((problem) => !opts.ignoreRules || !opts.ignoreRules.includes(problem.kind)); - - const subpaths = Object.keys(analysis.entrypointResolutions); +import TerminalRenderer from "marked-terminal"; + +export async function typed(analysis: core.Analysis, opts: Opts) { + const problems = analysis.problems.filter((problem) => !opts.ignoreRules || !opts.ignoreRules.includes(problem.kind)); + const grouped = groupProblemsByKind(problems); + const subpaths = Object.keys(analysis.entrypoints); + marked.setOptions({ + // @ts-expect-error the types are wrong (haha) + renderer: new TerminalRenderer(), + mangle: false, + headerIds: false, + }); if (opts.ignoreRules && opts.ignoreRules.length) { console.log( @@ -25,23 +32,18 @@ export async function typed(analysis: core.TypedAnalysis, opts: Opts) { } if (opts.summary) { - const summaries = core.summarizeProblems(problems, analysis); - const defaultSummary = !opts.emoji ? " No problems found" : " No problems found 🌟"; - const summaryTexts = summaries.map((summary) => { - return summary.messages - .map((message) => { - const messageText = message.messageText.split(". ").join(".\n "); - if (!opts.emoji) return ` ${messageText}`; - return ` ${problemEmoji[summary.kind]} ${messageText}`; - }) - .join("\n"); + const defaultSummary = marked(!opts.emoji ? " No problems found" : " No problems found 🌟"); + const summaryTexts = Object.keys(grouped).map((kind) => { + const emoji = opts.emoji ? `${problemKindInfo[kind as core.ProblemKind].emoji} ` : ""; + const description = marked(problemKindInfo[kind as core.ProblemKind].description); + return `${emoji}${description}`; }); - console.log((summaryTexts.join("\n\n") || defaultSummary) + "\n"); + console.log(summaryTexts.join("") || defaultSummary); } const entrypoints = subpaths.map((s) => { - const hasProblems = problems.some((p) => p.entrypoint === s); + const hasProblems = problems.some((p) => problemAffectsEntrypoint(p, s, analysis)); const color = hasProblems ? "redBright" : "greenBright"; if (s === ".") return chalk.bold[color](`"${analysis.packageName}"`); @@ -60,22 +62,21 @@ export async function typed(analysis: core.TypedAnalysis, opts: Opts) { row = row.concat( allResolutionKinds.map((kind) => { - const problemsForCell = problems.filter( - (problem) => problem.entrypoint === subpath && problem.resolutionKind === kind + const problemsForCell = groupProblemsByKind( + filterProblems(problems, analysis, { entrypoint: subpath, resolutionKind: kind }) ); - - const resolution = analysis.entrypointResolutions[subpath][kind].resolution; - - const descriptions = problemShortDescriptions[!opts.emoji ? "noEmoji" : "emoji"]; - - if (problemsForCell.length) { - return problemsForCell.map((problem) => descriptions[problem.kind]).join("\n"); + const resolution = analysis.entrypoints[subpath].resolutions[kind].resolution; + const kinds = Object.keys(problemsForCell) as core.ProblemKind[]; + if (kinds.length) { + return kinds + .map( + (kind) => (opts.emoji ? `${problemKindInfo[kind].emoji} ` : "") + problemKindInfo[kind].shortDescription + ) + .join("\n"); } const jsonResult = !opts.emoji ? "OK (JSON)" : "🟒 (JSON)"; - const moduleResult = (!opts.emoji ? "OK " : "🟒 ") + moduleKinds[resolution?.moduleKind?.detectedKind || ""]; - return resolution?.isJson ? jsonResult : moduleResult; }) ); @@ -96,22 +97,21 @@ export async function typed(analysis: core.TypedAnalysis, opts: Opts) { row = row.concat( subpaths.map((subpath) => { - const problemsForCell = problems.filter( - (problem) => problem.entrypoint === subpath && problem.resolutionKind === kind + const problemsForCell = groupProblemsByKind( + filterProblems(problems, analysis, { entrypoint: subpath, resolutionKind: kind }) ); - - const resolution = analysis.entrypointResolutions[subpath][kind].resolution; - - const descriptions = problemShortDescriptions[!opts.emoji ? "noEmoji" : "emoji"]; - - if (problemsForCell.length) { - return problemsForCell.map((problem) => descriptions[problem.kind]).join("\n"); + const resolution = analysis.entrypoints[subpath].resolutions[kind].resolution; + const kinds = Object.keys(problemsForCell) as core.ProblemKind[]; + if (kinds.length) { + return kinds + .map( + (kind) => (opts.emoji ? `${problemKindInfo[kind].emoji} ` : "") + problemKindInfo[kind].shortDescription + ) + .join("\n"); } const jsonResult = !opts.emoji ? "OK (JSON)" : "🟒 (JSON)"; - const moduleResult = (!opts.emoji ? "OK " : "🟒 ") + moduleKinds[resolution?.moduleKind?.detectedKind || ""]; - return resolution?.isJson ? jsonResult : moduleResult; }) ); diff --git a/packages/cli/src/render/untyped.ts b/packages/cli/src/render/untyped.ts index 8c986b7..819c1b6 100644 --- a/packages/cli/src/render/untyped.ts +++ b/packages/cli/src/render/untyped.ts @@ -1,5 +1,5 @@ import * as core from "@arethetypeswrong/core"; -export function untyped(analysis: core.UntypedAnalysis) { +export function untyped(analysis: core.UntypedResult) { console.log("This package does not contain types.\nDetails: ", analysis); } diff --git a/packages/cli/test/snapshots/@reduxjs__toolkit@2.0.0-beta.0.tgz.md b/packages/cli/test/snapshots/@reduxjs__toolkit@2.0.0-beta.0.tgz.md new file mode 100644 index 0000000..ac37ebd --- /dev/null +++ b/packages/cli/test/snapshots/@reduxjs__toolkit@2.0.0-beta.0.tgz.md @@ -0,0 +1,28 @@ +# @reduxjs__toolkit@2.0.0-beta.0.tgz + +``` +$ attw @reduxjs__toolkit@2.0.0-beta.0.tgz + + +🎭 Import resolved to a CommonJS type declaration file, but an ESM JavaScript file. + +πŸ₯΄ Import found in a type declaration file failed to resolve. Either this indicates that runtime resolution errors will occur, or (more likely) the types misrepresent the contents of the JavaScript files. + + +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ β”‚ "@reduxjs/toolkit/package.json" β”‚ "@reduxjs/toolkit" β”‚ "@reduxjs/toolkit/react" β”‚ "@reduxjs/toolkit/query" β”‚ "@reduxjs/toolkit/query/react" β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ node10 β”‚ 🟒 (JSON) β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ node16 (from CJS) β”‚ 🟒 (JSON) β”‚ 🟒 (CJS) β”‚ πŸ₯΄ Internal resolution error β”‚ 🟒 (CJS) β”‚ πŸ₯΄ Internal resolution error β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ node16 (from ESM) β”‚ 🟒 (JSON) β”‚ 🎭 Masquerading as CJS β”‚ 🎭 Masquerading as CJS β”‚ 🎭 Masquerading as CJS β”‚ 🎭 Masquerading as CJS β”‚ +β”‚ β”‚ β”‚ β”‚ πŸ₯΄ Internal resolution error β”‚ β”‚ πŸ₯΄ Internal resolution error β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ bundler β”‚ 🟒 (JSON) β”‚ 🟒 β”‚ πŸ₯΄ Internal resolution error β”‚ 🟒 β”‚ πŸ₯΄ Internal resolution error β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + + +``` + +Exit code: 1 \ No newline at end of file diff --git a/packages/cli/test/snapshots/@vitejs__plugin-react@3.1.0.tgz.md b/packages/cli/test/snapshots/@vitejs__plugin-react@3.1.0.tgz.md index 827eb9e..e136640 100644 --- a/packages/cli/test/snapshots/@vitejs__plugin-react@3.1.0.tgz.md +++ b/packages/cli/test/snapshots/@vitejs__plugin-react@3.1.0.tgz.md @@ -4,7 +4,8 @@ $ attw @vitejs__plugin-react@3.1.0.tgz - 🎭 Imports of the package under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `"type": "module"`) resolved to CJS types, but ESM implementations. +🎭 Import resolved to a CommonJS type declaration file, but an ESM JavaScript file. + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "@vitejs/plugin-react" β”‚ diff --git a/packages/cli/test/snapshots/ajv@8.12.0.tgz.md b/packages/cli/test/snapshots/ajv@8.12.0.tgz.md index ca9f1c7..9d48dde 100644 --- a/packages/cli/test/snapshots/ajv@8.12.0.tgz.md +++ b/packages/cli/test/snapshots/ajv@8.12.0.tgz.md @@ -4,9 +4,8 @@ $ attw ajv@8.12.0.tgz - ❗️ The types resolved at the package use `export default` where the implementation appears to use `module.exports =`. - Node treats a default import of these constructs from an ES module differently, so these types will make TypeScript under the `node16` resolution mode think an extra `.default` property access is required, but that will likely fail at runtime in Node. - These types should use `export =` instead of `export default`. +❗️ The resolved types use export default where the JavaScript file appears to use module.exports =. This will cause TypeScript under the node16 module mode to think an extra .default property access is required, but that will likely fail at runtime. These types should use export = instead of export default. + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "ajv" β”‚ diff --git a/packages/cli/test/snapshots/astring@1.8.6.tgz.md b/packages/cli/test/snapshots/astring@1.8.6.tgz.md index cecf896..7676014 100644 --- a/packages/cli/test/snapshots/astring@1.8.6.tgz.md +++ b/packages/cli/test/snapshots/astring@1.8.6.tgz.md @@ -4,7 +4,8 @@ $ attw astring@1.8.6.tgz - 🎭 Imports of the package under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `"type": "module"`) resolved to CJS types, but ESM implementations. +🎭 Import resolved to a CommonJS type declaration file, but an ESM JavaScript file. + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "astring" β”‚ diff --git a/packages/cli/test/snapshots/axios@1.4.0.tgz.md b/packages/cli/test/snapshots/axios@1.4.0.tgz.md index ecd2101..3770839 100644 --- a/packages/cli/test/snapshots/axios@1.4.0.tgz.md +++ b/packages/cli/test/snapshots/axios@1.4.0.tgz.md @@ -4,27 +4,28 @@ $ attw axios@1.4.0.tgz - ❓ Wildcards cannot yet be analyzed by this tool. +❓ Wildcard subpaths cannot yet be analyzed by this tool. - πŸ’€ Imports of multiple entrypoints under the `node10` module resolution setting failed to resolve. +πŸ’€ Import failed to resolve to type declarations or JavaScript files. - 🚫 Imports of multiple entrypoints under the `node16` module resolution setting when the importing module is CJS (its extension is `.cts` or `.cjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that does not contain `"type": "module"`) resolved to JavaScript files, but no types. - 🚫 Imports of multiple entrypoints under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `"type": "module"`) resolved to JavaScript files, but no types. - 🚫 Imports of multiple entrypoints under the `bundler` module resolution setting resolved to JavaScript files, but no types. +❌ Import resolved to JavaScript files, but no type declarations were found. + +⚠️ A require call resolved to an ESM JavaScript file, which is an error in Node and some bundlers. CommonJS consumers will need to use a dynamic import. - ⚠️ Imports of multiple entrypoints resolved to ES modules from a CJS importing module. - CJS modules in Node will only be able to access this entrypoint with a dynamic import. β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "axios" β”‚ "axios/unsafe/*" β”‚ "axios/unsafe/core/settle.js" β”‚ "axios/unsafe/core/buildFullPath… β”‚ "axios/unsafe/helpers/isAbsolute… β”‚ "axios/unsafe/helpers/buildURL.j… β”‚ "axios/unsafe/helpers/combineURL… β”‚ "axios/unsafe/adapters/http.js" β”‚ "axios/unsafe/adapters/xhr.js" β”‚ "axios/unsafe/utils.js" β”‚ "axios/package.json" β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ node10 β”‚ 🟒 β”‚ ❓ Unable to check β”‚ πŸ’€ Failed to resolve β”‚ πŸ’€ Failed to resolve β”‚ πŸ’€ Failed to resolve β”‚ πŸ’€ Failed to resolve β”‚ πŸ’€ Failed to resolve β”‚ πŸ’€ Failed to resolve β”‚ πŸ’€ Failed to resolve β”‚ πŸ’€ Failed to resolve β”‚ 🟒 (JSON) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ ❓ Unable to check β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🟒 (JSON) β”‚ +β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ ❓ Unable to check β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ 🟒 (JSON) β”‚ β”‚ β”‚ β”‚ β”‚ ⚠️ ESM (dynamic import only) β”‚ ⚠️ ESM (dynamic import only) β”‚ ⚠️ ESM (dynamic import only) β”‚ ⚠️ ESM (dynamic import only) β”‚ ⚠️ ESM (dynamic import only) β”‚ ⚠️ ESM (dynamic import only) β”‚ ⚠️ ESM (dynamic import only) β”‚ ⚠️ ESM (dynamic import only) β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node16 (from ESM) β”‚ 🟒 (ESM) β”‚ ❓ Unable to check β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🚫 No types β”‚ 🟒 (JSON) β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€οΏ½ +β”‚ node16 (from ESM) β”‚ 🟒 (ESM) β”‚ ❓ Unable to check β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ 🟒 (JSON) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ bundler β”‚ 🟒 β”‚ ❓ Unable to check β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ 🟒 (JSON) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ``` diff --git a/packages/cli/test/snapshots/commander@10.0.1.tgz.md b/packages/cli/test/snapshots/commander@10.0.1.tgz.md index 7f2fc47..aeb30a4 100644 --- a/packages/cli/test/snapshots/commander@10.0.1.tgz.md +++ b/packages/cli/test/snapshots/commander@10.0.1.tgz.md @@ -4,24 +4,24 @@ $ attw commander@10.0.1.tgz - 🎭 Imports of `"commander"` under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `"type": "module"`) resolved to CJS types, but ESM implementations. +🎭 Import resolved to a CommonJS type declaration file, but an ESM JavaScript file. - 🚫 Imports of `"commander/esm.mjs"` under all module resolution settings resolved to JavaScript files, but no types. +❌ Import resolved to JavaScript files, but no type declarations were found. + +⚠️ A require call resolved to an ESM JavaScript file, which is an error in Node and some bundlers. CommonJS consumers will need to use a dynamic import. - ⚠️ Imports of `"commander/esm.mjs"` resolved to ES modules from a CJS importing module. - CJS modules in Node will only be able to access this entrypoint with a dynamic import. β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "commander" β”‚ "commander/esm.mjs" β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node10 β”‚ 🟒 β”‚ 🚫 No types β”‚ +β”‚ node10 β”‚ 🟒 β”‚ ❌ No types β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ 🚫 No types β”‚ +β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ ❌ No types β”‚ β”‚ β”‚ β”‚ ⚠️ ESM (dynamic import only) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node16 (from ESM) β”‚ 🎭 Masquerading as CJS β”‚ 🚫 No types β”‚ +β”‚ node16 (from ESM) β”‚ 🎭 Masquerading as CJS β”‚ ❌ No types β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ bundler β”‚ 🟒 β”‚ 🚫 No types β”‚ +β”‚ bundler β”‚ 🟒 β”‚ ❌ No types β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ diff --git a/packages/cli/test/snapshots/ejs@3.1.9.tgz.md b/packages/cli/test/snapshots/ejs@3.1.9.tgz.md index 3b8b20e..946286b 100644 --- a/packages/cli/test/snapshots/ejs@3.1.9.tgz.md +++ b/packages/cli/test/snapshots/ejs@3.1.9.tgz.md @@ -5,7 +5,7 @@ $ attw ejs@3.1.9.tgz This package does not contain types. -Details: { packageName: 'ejs', packageVersion: '3.1.9', containsTypes: false } +Details: { packageName: 'ejs', packageVersion: '3.1.9', types: false } ``` diff --git a/packages/cli/test/snapshots/hexoid@1.0.0.tgz.md b/packages/cli/test/snapshots/hexoid@1.0.0.tgz.md index ac37c35..b476c4e 100644 --- a/packages/cli/test/snapshots/hexoid@1.0.0.tgz.md +++ b/packages/cli/test/snapshots/hexoid@1.0.0.tgz.md @@ -4,9 +4,8 @@ $ attw hexoid@1.0.0.tgz - ❗️ The types resolved at the package use `export default` where the implementation appears to use `module.exports =`. - Node treats a default import of these constructs from an ES module differently, so these types will make TypeScript under the `node16` resolution mode think an extra `.default` property access is required, but that will likely fail at runtime in Node. - These types should use `export =` instead of `export default`. +❗️ The resolved types use export default where the JavaScript file appears to use module.exports =. This will cause TypeScript under the node16 module mode to think an extra .default property access is required, but that will likely fail at runtime. These types should use export = instead of export default. + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "hexoid" β”‚ diff --git a/packages/cli/test/snapshots/klona@2.0.6.tgz.md b/packages/cli/test/snapshots/klona@2.0.6.tgz.md index bacdc68..56ad38b 100644 --- a/packages/cli/test/snapshots/klona@2.0.6.tgz.md +++ b/packages/cli/test/snapshots/klona@2.0.6.tgz.md @@ -4,7 +4,8 @@ $ attw klona@2.0.6.tgz - 🎭 Imports of multiple entrypoints under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `"type": "module"`) resolved to CJS types, but ESM implementations. +🎭 Import resolved to a CommonJS type declaration file, but an ESM JavaScript file. + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "klona" β”‚ "klona/json" β”‚ "klona/lite" β”‚ "klona/full" β”‚ "klona/package.json" β”‚ diff --git a/packages/cli/test/snapshots/node-html-parser@6.1.5.tgz.md b/packages/cli/test/snapshots/node-html-parser@6.1.5.tgz.md index d5a44f9..0e81529 100644 --- a/packages/cli/test/snapshots/node-html-parser@6.1.5.tgz.md +++ b/packages/cli/test/snapshots/node-html-parser@6.1.5.tgz.md @@ -4,19 +4,19 @@ $ attw node-html-parser@6.1.5.tgz - 🀨 The CJS module resolved at the package under contains a simulated `export default` with an `__esModule` marker, but no top-level `module.exports`. - Node does not respect the `__esModule` marker, so accessing the intended default export will require a `.default` property access in Node from an ES module. +🀨 CommonJS module simulates a default export with exports.default and exports.__esModule, but does not also set module.exports for compatibility with Node. Node, and some bundlers under certain conditions (https://andrewbranch.github.io/interop-test/#synthesizing-default-exports-for-cjs-modules), do not respect the __esModule marker, so accessing the intended default export will require a .default property access on the default import. + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "node-html-parser" β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node10 β”‚ 🟒 β”‚ +β”‚ node10 β”‚ 🀨 CJS default export β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ +β”‚ node16 (from CJS) β”‚ 🀨 CJS default export β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ node16 (from ESM) β”‚ 🀨 CJS default export β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ bundler β”‚ 🟒 β”‚ +β”‚ bundler β”‚ 🀨 CJS default export β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ diff --git a/packages/cli/test/snapshots/postcss@8.4.21.tgz.md b/packages/cli/test/snapshots/postcss@8.4.21.tgz.md index 0d228cd..17a6e6c 100644 --- a/packages/cli/test/snapshots/postcss@8.4.21.tgz.md +++ b/packages/cli/test/snapshots/postcss@8.4.21.tgz.md @@ -4,21 +4,28 @@ $ attw postcss@8.4.21.tgz - 🎭 Imports of `"postcss"` under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `"type": "module"`) resolved to CJS types, but ESM implementations. +🎭 Import resolved to a CommonJS type declaration file, but an ESM JavaScript file. - πŸ› Imports of `"postcss"` under resolution modes that use the `import` condition in package.json `"exports"` resolved through a conditional package.json export, but only after failing to resolve through an earlier condition. - This behavior is a TypeScript bug (https://github.com/microsoft/TypeScript/issues/50762) and should not be relied upon. +πŸ› Import resolved to types through a conditional package.json export, but only after failing to resolve through an earlier condition. This behavior is a TypeScript bug (https://github.com/microsoft/TypeScript/issues/50762). It may misrepresent the runtime behavior of this import and should not be relied upon. - ❗️ The types resolved at multiple entrypoints use `export default` where the implementation appears to use `module.exports =`. - Node treats a default import of these constructs from an ES module differently, so these types will make TypeScript under the `node16` resolution mode think an extra `.default` property access is required, but that will likely fail at runtime in Node. - These types should use `export =` instead of `export default`. +❗️ The resolved types use export default where the JavaScript file appears to use module.exports =. This will cause TypeScript under the node16 module mode to think an extra .default property access is required, but that will likely fail at runtime. These types should use export = instead of export default. + +❌ Import resolved to JavaScript files, but no type declarations were found. - 🚫 Imports of multiple entrypoints under all module resolution settings resolved to JavaScript files, but no types. β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "postcss" β”‚ "postcss/lib/at-rule" β”‚ "postcss/lib/comment" β”‚ "postcss/lib/container" β”‚ "postcss/lib/css-syntax-error" β”‚ "postcss/lib/declaration" β”‚ "postcss/lib/fromJSON" β”‚ "postcss/lib/input" β”‚ "postcss/lib/lazy-result" β”‚ "postcss/lib/no-work-result" β”‚ "postcss/lib/list" β”‚ "postcss/lib/map-generator" β”‚ "postcss/lib/node" β”‚ "postcss/lib/parse" β”‚ "postcss/lib/parser" β”‚ "postcss/lib/postcss" β”‚ "postcss/lib/previous-map" β”‚ "postcss/lib/processor" β”‚ "postcss/lib/result" β”‚ "postcss/lib/root" β”‚ "postcss/lib/rule" β”‚ "postcss/lib/stringifier" β”‚ "postcss/lib/stringify" β”‚ "postcss/lib/symbols" β”‚ "postcss/lib/terminal-highlight" β”‚ "postcss/lib/tokenize" β”‚ "postcss/lib/warn-once" β”‚ "postcss/lib/warning" β”‚ "postcss/package.json" β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node10 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🚫 No types β”‚ 🟒 β”‚ 🟒 β”‚ 🚫 No types β”‚ 🟒 οΏ½ +β”‚ node10 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ ❌ No types β”‚ 🟒 β”‚ 🟒 β”‚ ❌ No types β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ 🟒 β”‚ 🟒 (JSON) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ ❌ No types β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ ❌ No types β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ 🟒 (CJS) β”‚ 🟒 (JSON) β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ node16 (from ESM) β”‚ 🎭 Masquerading as CJS β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❌ No types β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❌ No types β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❗️ Incorrect default export β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❗️ Incorrect default export β”‚ 🟒 (JSON) β”‚ +β”‚ β”‚ πŸ› Used fallback condition β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ bundler β”‚ πŸ› Used fallback condition β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ ❌ No types β”‚ 🟒 β”‚ 🟒 β”‚ ❌ No types β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ ❌ No types β”‚ 🟒 β”‚ 🟒 (JSON) β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ``` diff --git a/packages/cli/test/snapshots/react-chartjs-2@5.2.0.tgz.md b/packages/cli/test/snapshots/react-chartjs-2@5.2.0.tgz.md index f845d3d..65a9732 100644 --- a/packages/cli/test/snapshots/react-chartjs-2@5.2.0.tgz.md +++ b/packages/cli/test/snapshots/react-chartjs-2@5.2.0.tgz.md @@ -4,10 +4,10 @@ $ attw react-chartjs-2@5.2.0.tgz - πŸ‘Ί Imports of the package under the `node16` module resolution setting when the importing module is CJS (its extension is `.cts` or `.cjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that does not contain `"type": "module"`) resolved to ESM types, but CJS implementations. +πŸ‘Ί Import resolved to an ESM type declaration file, but a CommonJS JavaScript file. + +⚠️ A require call resolved to an ESM JavaScript file, which is an error in Node and some bundlers. CommonJS consumers will need to use a dynamic import. - ⚠️ Imports of the package resolved to ES modules from a CJS importing module. - CJS modules in Node will only be able to access this entrypoint with a dynamic import. β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "react-chartjs-2" β”‚ diff --git a/packages/cli/test/snapshots/rfdc@1.3.0.tgz.md b/packages/cli/test/snapshots/rfdc@1.3.0.tgz.md index c3c7b7b..0099594 100644 --- a/packages/cli/test/snapshots/rfdc@1.3.0.tgz.md +++ b/packages/cli/test/snapshots/rfdc@1.3.0.tgz.md @@ -4,18 +4,19 @@ $ attw rfdc@1.3.0.tgz - 🚫 Imports of `"rfdc/default"` under all module resolution settings resolved to JavaScript files, but no types. +❌ Import resolved to JavaScript files, but no type declarations were found. + β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "rfdc" β”‚ "rfdc/default" β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node10 β”‚ 🟒 β”‚ 🚫 No types β”‚ +β”‚ node10 β”‚ 🟒 β”‚ ❌ No types β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ 🚫 No types β”‚ +β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ ❌ No types β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node16 (from ESM) β”‚ 🟒 (CJS) β”‚ 🚫 No types β”‚ +β”‚ node16 (from ESM) β”‚ 🟒 (CJS) β”‚ ❌ No types β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ bundler β”‚ 🟒 β”‚ 🚫 No types β”‚ +β”‚ bundler β”‚ 🟒 β”‚ ❌ No types β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ diff --git a/packages/cli/test/snapshots/vue@3.3.4.tgz.md b/packages/cli/test/snapshots/vue@3.3.4.tgz.md index d0d9fbc..321a838 100644 --- a/packages/cli/test/snapshots/vue@3.3.4.tgz.md +++ b/packages/cli/test/snapshots/vue@3.3.4.tgz.md @@ -4,29 +4,27 @@ $ attw vue@3.3.4.tgz - 🎭 Imports of multiple entrypoints under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `"type": "module"`) resolved to CJS types, but ESM implementations. +🎭 Import resolved to a CommonJS type declaration file, but an ESM JavaScript file. - πŸ’€ Imports of `"vue/jsx-dev-runtime"` under the `node10` module resolution setting failed to resolve. +πŸ’€ Import failed to resolve to type declarations or JavaScript files. - 🚭 The implementation resolved at multiple entrypoints uses ESM syntax, but the detected module kind is CJS. - This will be an error in Node (and potentially other runtimes and bundlers). - The module kind was decided based on the nearest package.json’s lack of a `"type": "module"` field. - 🚭 The implementation resolved at multiple entrypoints uses ESM syntax, but the detected module kind is CJS. - This will be an error in Node (and potentially other runtimes and bundlers). - The module kind was decided based on the nearest package.json’s lack of a `"type": "module"` field. +❓ Wildcard subpaths cannot yet be analyzed by this tool. + +πŸ₯΄ Import found in a type declaration file failed to resolve. Either this indicates that runtime resolution errors will occur, or (more likely) the types misrepresent the contents of the JavaScript files. - ❓ Wildcards cannot yet be analyzed by this tool. β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ "vue" β”‚ "vue/server-renderer" β”‚ "vue/compiler-sfc" β”‚ "vue/jsx-runtime" β”‚ "vue/jsx-dev-runtime" β”‚ "vue/jsx" β”‚ "vue/dist/*" β”‚ "vue/package.json" β”‚ "vue/macros" β”‚ "vue/macros-global" β”‚ "vue/ref-macros" β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ node10 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ πŸ’€ Failed to resolve β”‚ 🟒 β”‚ ❓ Unable to check β”‚ 🟒 (JSON) β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🚭 Unexpected ESM syntax β”‚ ❓ Unable to check β”‚ 🟒 (JSON) β”‚ 🚭 Unexpected ESM syntax β”‚ 🚭 Unexpected ESM syntax β”‚ 🚭 Unexpected ESM syntax β”‚ +β”‚ node16 (from CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ ❓ Unable to check β”‚ 🟒 (JSON) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ node16 (from ESM) β”‚ 🟒 (ESM) β”‚ 🟒 (ESM) β”‚ 🟒 (ESM) β”‚ 🎭 Masquerading as CJS β”‚ 🎭 Masquerading as CJS β”‚ 🚭 Unexpected ESM syntax β”‚ ❓ Unable to check β”‚ 🟒 (JSON) β”‚ 🚭 Unexpected ESM syntax β”‚ 🚭 Unexpected ESM syntax β”‚ 🚭 Unexpected ESM syntax β”‚ +β”‚ node16 (from ESM) β”‚ πŸ₯΄ Internal resolution error β”‚ 🟒 (ESM) β”‚ 🟒 (ESM) β”‚ 🎭 Masquerading as CJS β”‚ 🎭 Masquerading as CJS β”‚ 🟒 (CJS) β”‚ ❓ Unable to check β”‚ 🟒 (JSON) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ 🟒 (CJS) β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ bundler β”‚ 🟒 β”‚ 🟒 +β”‚ bundler β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ ❓ Unable to check β”‚ 🟒 (JSON) β”‚ 🟒 β”‚ 🟒 β”‚ 🟒 β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ + ``` diff --git a/packages/core/package.json b/packages/core/package.json index 44f8920..7b2390c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -31,10 +31,6 @@ "development": "./src/index.ts", "default": "./dist/index.js" }, - "./problems": { - "development": "./src/problems.ts", - "default": "./dist/problems.js" - }, "./types": { "development": "./src/types.ts", "default": "./dist/types.js" @@ -43,6 +39,10 @@ "development": "./src/utils.ts", "default": "./dist/utils.js" }, + "./problems": { + "development": "./src/problems.ts", + "default": "./dist/problems.js" + }, "./versions": { "node": "./dist/versions.js" }, diff --git a/packages/core/src/checkPackage.ts b/packages/core/src/checkPackage.ts index 039308f..ff97aa9 100644 --- a/packages/core/src/checkPackage.ts +++ b/packages/core/src/checkPackage.ts @@ -2,19 +2,19 @@ import ts from "typescript"; import { fetchTarballHost } from "./fetchTarballHost.js"; import type { Host, - Analysis, + CheckResult, FS, ResolutionKind, EntrypointResolutionAnalysis, - TraceCollector, Resolution, - SymbolTable, - ModuleKind, + EntrypointInfo, } from "./types.js"; +import { createMultiCompilerHost, type MultiCompilerHost } from "./multiCompilerHost.js"; +import { getEntrypointResolutionProblems } from "./checks/entrypointResolutionProblems.js"; +import { getResolutionBasedFileProblems } from "./checks/resolutionBasedFileProblems.js"; +import { getFileProblems } from "./checks/fileProblems.js"; -type SourceFileCache = Map; - -export async function checkTgz(tgz: Uint8Array, host: Host = fetchTarballHost): Promise { +export async function checkTgz(tgz: Uint8Array, host: Host = fetchTarballHost): Promise { const packageFS = await host.createPackageFSFromTarball(tgz); return checkPackageWorker(packageFS); } @@ -23,14 +23,14 @@ export async function checkPackage( packageName: string, packageVersion?: string, host: Host = fetchTarballHost -): Promise { +): Promise { const packageFS = await host.createPackageFS(packageName, packageVersion); return checkPackageWorker(packageFS); } -async function checkPackageWorker(packageFS: FS): Promise { +async function checkPackageWorker(packageFS: FS): Promise { const files = packageFS.listFiles(); - const containsTypes = files.some(ts.hasTSFileExtension); + const types = files.some(ts.hasTSFileExtension) ? "included" : false; const parts = files[0].split("/"); let packageName = parts[2]; if (packageName.startsWith("@")) { @@ -38,12 +38,23 @@ async function checkPackageWorker(packageFS: FS): Promise { } const packageJsonContent = JSON.parse(packageFS.readFile(`/node_modules/${packageName}/package.json`)); const packageVersion = packageJsonContent.version; - if (!containsTypes) { - return { packageName, packageVersion, containsTypes }; + if (!types) { + return { packageName, packageVersion, types }; } - const entrypoints = checkEntrypoints(packageName, packageFS); - return { packageName, packageVersion, containsTypes, entrypointResolutions: entrypoints }; + const host = createMultiCompilerHost(packageFS); + const entrypointResolutions = getEntrypointInfo(packageName, packageFS, host); + const entrypointResolutionProblems = getEntrypointResolutionProblems(entrypointResolutions, host); + const resolutionBasedFileProblems = getResolutionBasedFileProblems(packageName, entrypointResolutions, host); + const fileProblems = getFileProblems(entrypointResolutions, host); + + return { + packageName, + packageVersion, + types, + entrypoints: entrypointResolutions, + problems: [...entrypointResolutionProblems, ...resolutionBasedFileProblems, ...fileProblems], + }; } function getSubpaths(exportsObject: any): string[] { @@ -57,179 +68,80 @@ function getSubpaths(exportsObject: any): string[] { return keys.flatMap((key) => getSubpaths(exportsObject[key])); } -function checkEntrypoints( - packageName: string, - fs: FS -): Record> { +function getEntrypointInfo(packageName: string, fs: FS, host: MultiCompilerHost): Record { const packageJson = JSON.parse(fs.readFile(`/node_modules/${packageName}/package.json`)); const subpaths = getSubpaths(packageJson.exports); const entrypoints = subpaths.length ? subpaths : ["."]; - const result: Record> = {}; - const sourceFileCache: SourceFileCache = new Map(); + const result: Record = {}; for (const entrypoint of entrypoints) { + const resolutions: Record = { + node10: getEntrypointResolution(packageName, "node10", entrypoint, host), + "node16-cjs": getEntrypointResolution(packageName, "node16-cjs", entrypoint, host), + "node16-esm": getEntrypointResolution(packageName, "node16-esm", entrypoint, host), + bundler: getEntrypointResolution(packageName, "bundler", entrypoint, host), + }; result[entrypoint] = { - node10: checkEntrypointTyped(packageName, fs, "node10", entrypoint, sourceFileCache), - "node16-cjs": checkEntrypointTyped(packageName, fs, "node16-cjs", entrypoint, sourceFileCache), - "node16-esm": checkEntrypointTyped(packageName, fs, "node16-esm", entrypoint, sourceFileCache), - bundler: checkEntrypointTyped(packageName, fs, "bundler", entrypoint, sourceFileCache), + subpath: entrypoint, + resolutions, + hasTypes: Object.values(resolutions).some((r) => r.resolution?.isTypeScript), + isWildcard: !!resolutions.bundler.isWildcard, }; } return result; } -function createModuleResolutionHost(fs: FS, trace: (message: string) => void): ts.ModuleResolutionHost { - return { - ...fs, - trace, - }; -} - -function createTraceCollector(): TraceCollector { - const traces: string[] = []; - return { - trace: (message: string) => traces.push(message), - read: () => { - const result = traces.slice(); - traces.length = 0; - return result; - }, - }; -} - -function checkEntrypointTyped( +function getEntrypointResolution( packageName: string, - fs: FS, resolutionKind: ResolutionKind, entrypoint: string, - sourceFileCache: SourceFileCache + host: MultiCompilerHost ): EntrypointResolutionAnalysis { if (entrypoint.includes("*")) { - return { name: entrypoint, isWildcard: true, trace: [] }; + return { name: entrypoint, resolutionKind, isWildcard: true }; } const moduleSpecifier = packageName + entrypoint.substring(1); // remove leading . before slash const importingFileName = resolutionKind === "node16-esm" ? "/index.mts" : "/index.ts"; - const moduleResolution = - resolutionKind === "node10" - ? // @ts-expect-error - ts.ModuleResolutionKind.Node10 - : resolutionKind === "node16-cjs" || resolutionKind === "node16-esm" - ? ts.ModuleResolutionKind.Node16 - : // @ts-expect-error - ts.ModuleResolutionKind.Bundler; + const moduleResolution = resolutionKind === "node10" ? "node10" : resolutionKind === "bundler" ? "bundler" : "node16"; const resolutionMode = resolutionKind === "node16-esm" ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS; - const traceCollector = createTraceCollector(); - const resolutionHost = createModuleResolutionHost(fs, traceCollector.trace); const resolution = tryResolve(); const implementationResolution = !resolution || ts.isDeclarationFileName(resolution.fileName) ? tryResolve(/*noDtsResolution*/ true) : undefined; + const files = resolution + ? host + .createProgram(moduleResolution, [resolution.fileName]) + .getSourceFiles() + .map((f) => f.fileName) + : undefined; + return { name: entrypoint, + resolutionKind, resolution, implementationResolution, - trace: traceCollector.read(), + files, }; function tryResolve(noDtsResolution?: boolean): Resolution | undefined { - let moduleKind: ModuleKind | undefined; - const compilerOptions = { - resolveJsonModule: true, - moduleResolution, - traceResolution: !noDtsResolution, - noDtsResolution, - }; - const resolution = ts.resolveModuleName( + const { resolution, trace } = host.resolveModuleName( moduleSpecifier, importingFileName, - compilerOptions, - resolutionHost, - undefined, - undefined, - resolutionMode + moduleResolution, + resolutionMode, + noDtsResolution ); const fileName = resolution.resolvedModule?.resolvedFileName; if (!fileName) { return undefined; } - let sourceInfo = sourceFileCache.get(fileName); - if (!sourceInfo) { - const sourceText = fs.readFile(fileName); - const sourceFile = ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest, /*setParentNodes*/ false); - sourceFileCache.set( - fileName, - (sourceInfo = { - sourceFile, - symbolTable: getModuleSymbolTable(sourceFile), - }) - ); - } - if (resolutionKind === "node16-cjs" || resolutionKind === "node16-esm") { - const kind = ts.getImpliedNodeFormatForFile( - resolution.resolvedModule.resolvedFileName as ts.Path, - /*packageJsonInfoCache*/ undefined, - fs, - compilerOptions - ); - if (kind) { - const isExtension = - resolution.resolvedModule.extension === ts.Extension.Cjs || - resolution.resolvedModule.extension === ts.Extension.Cts || - resolution.resolvedModule.extension === ts.Extension.Dcts || - resolution.resolvedModule.extension === ts.Extension.Mjs || - resolution.resolvedModule.extension === ts.Extension.Mts || - resolution.resolvedModule.extension === ts.Extension.Dmts; - const reasonPackageJsonInfo = isExtension - ? undefined - : ts.getPackageScopeForPath( - resolution.resolvedModule.resolvedFileName, - ts.getTemporaryModuleResolutionState(undefined, resolutionHost, compilerOptions) - ); - const reasonFileName = isExtension - ? resolution.resolvedModule.resolvedFileName - : reasonPackageJsonInfo - ? reasonPackageJsonInfo.packageDirectory + "/package.json" - : resolution.resolvedModule.resolvedFileName; - const reasonPackageJsonType = reasonPackageJsonInfo?.contents?.packageJsonContent.type; - moduleKind = { - detectedKind: kind, - detectedReason: isExtension ? "extension" : reasonPackageJsonType ? "type" : "no:type", - reasonFileName, - syntax: sourceInfo?.sourceFile.externalModuleIndicator - ? ts.ModuleKind.ESNext - : sourceInfo?.sourceFile.commonJsModuleIndicator - ? ts.ModuleKind.CommonJS - : undefined, - }; - } - } return { fileName, - moduleKind, + moduleKind: host.getModuleKindForFile(fileName, moduleResolution), isJson: resolution.resolvedModule.extension === ts.Extension.Json, isTypeScript: ts.hasTSFileExtension(resolution.resolvedModule.resolvedFileName), - exports: sourceInfo?.symbolTable, + trace, }; } } - -function getModuleSymbolTable(sourceFile: ts.SourceFile): SymbolTable | false { - ts.bindSourceFile(sourceFile, { allowJs: true, checkJs: true, target: ts.ScriptTarget.Latest }); - if (!sourceFile.symbol) { - return false; - } - const symbolTable: SymbolTable = {}; - sourceFile.symbol.exports?.forEach((symbol, escapedName) => { - const name = ts.unescapeLeadingUnderscores(escapedName); - symbolTable[name] = { - name, - flags: symbol.flags, - valueDeclarationRange: symbol.valueDeclaration && [ - symbol.valueDeclaration.getStart(sourceFile), - symbol.valueDeclaration.end, - ], - }; - }); - return symbolTable; -} diff --git a/packages/core/src/checks/entrypointResolutionProblems.ts b/packages/core/src/checks/entrypointResolutionProblems.ts new file mode 100644 index 0000000..d0b2380 --- /dev/null +++ b/packages/core/src/checks/entrypointResolutionProblems.ts @@ -0,0 +1,97 @@ +import ts from "typescript"; +import type { EntrypointInfo, EntrypointResolutionProblem } from "../types.js"; +import type { MultiCompilerHost } from "../multiCompilerHost.js"; +import { resolvedThroughFallback, visitResolutions } from "../utils.js"; + +export function getEntrypointResolutionProblems( + entrypointResolutions: Record, + host: MultiCompilerHost +): EntrypointResolutionProblem[] { + const problems: EntrypointResolutionProblem[] = []; + visitResolutions(entrypointResolutions, (result, entrypoint) => { + const { subpath } = entrypoint; + const { resolutionKind } = result; + if (result.isWildcard) { + problems.push({ + kind: "Wildcard", + entrypoint: subpath, + resolutionKind, + }); + return; + } + if (!result.resolution) { + problems.push({ + kind: "NoResolution", + entrypoint: subpath, + resolutionKind, + }); + } else if (!result.resolution.isTypeScript && !result.resolution.isJson) { + problems.push({ + kind: "UntypedResolution", + entrypoint: subpath, + resolutionKind, + }); + } + + const { resolution, implementationResolution } = result; + if ( + resolution?.moduleKind?.detectedKind === ts.ModuleKind.ESNext && + implementationResolution?.moduleKind?.detectedKind === ts.ModuleKind.CommonJS + ) { + problems.push({ + kind: "FalseESM", + entrypoint: subpath, + resolutionKind, + }); + } else if ( + resolution?.moduleKind?.detectedKind === ts.ModuleKind.CommonJS && + implementationResolution?.moduleKind?.detectedKind === ts.ModuleKind.ESNext + ) { + problems.push({ + kind: "FalseCJS", + entrypoint: subpath, + resolutionKind, + }); + } + + if (resolutionKind === "node16-cjs" && resolution?.moduleKind?.detectedKind === ts.ModuleKind.ESNext) { + problems.push({ + kind: "CJSResolvesToESM", + entrypoint: subpath, + resolutionKind, + }); + } + + if (resolution && resolvedThroughFallback(resolution.trace)) { + problems.push({ + kind: "FallbackCondition", + entrypoint: subpath, + resolutionKind, + }); + } + + if (resolutionKind === "node16-esm" && resolution && implementationResolution) { + const typesSourceFile = host.getSourceFile(resolution.fileName, "node16"); + if (typesSourceFile) { + ts.bindSourceFile(typesSourceFile, { target: ts.ScriptTarget.Latest, allowJs: true, checkJs: true }); + } + const typesExports = typesSourceFile?.symbol?.exports; + const jsSourceFile = typesExports && host.getSourceFile(implementationResolution.fileName, "node16"); + if (jsSourceFile) { + ts.bindSourceFile(jsSourceFile, { target: ts.ScriptTarget.Latest, allowJs: true, checkJs: true }); + } + const jsExports = jsSourceFile?.symbol?.exports; + if (typesExports && jsExports) { + if (typesExports.has(ts.InternalSymbolName.Default) && jsExports.has(ts.InternalSymbolName.ExportEquals)) { + // Also need to check for `default` property on `jsModule["export="]`? + problems.push({ + kind: "FalseExportDefault", + entrypoint: subpath, + resolutionKind, + }); + } + } + } + }); + return problems; +} diff --git a/packages/core/src/checks/fileProblems.ts b/packages/core/src/checks/fileProblems.ts new file mode 100644 index 0000000..7ba0747 --- /dev/null +++ b/packages/core/src/checks/fileProblems.ts @@ -0,0 +1,43 @@ +import ts from "typescript"; +import type { MultiCompilerHost } from "../multiCompilerHost.js"; +import type { EntrypointInfo, FileProblem } from "../types.js"; +import { isDefined } from "../utils.js"; + +export function getFileProblems( + entrypointResolutions: Record, + host: MultiCompilerHost +): FileProblem[] { + const problems: FileProblem[] = []; + const visibleFiles = new Set( + Object.values(entrypointResolutions).flatMap((entrypointResolution) => { + return Object.values(entrypointResolution.resolutions).flatMap((resolution) => { + return [resolution.resolution?.fileName, resolution.implementationResolution?.fileName].filter(isDefined); + }); + }) + ); + + for (const fileName of visibleFiles) { + if (ts.hasJSFileExtension(fileName)) { + const sourceFile = host.getSourceFile(fileName, "node16")!; + if ( + !sourceFile.externalModuleIndicator && + sourceFile.commonJsModuleIndicator && + sourceFile.symbol?.exports?.has(ts.InternalSymbolName.Default) && + sourceFile.symbol.exports.has(ts.escapeLeadingUnderscores("__esModule")) && + !sourceFile.symbol.exports.has(ts.InternalSymbolName.ExportEquals) + ) { + const decl = sourceFile.symbol.exports.get(ts.InternalSymbolName.Default)!.declarations![0]; + problems.push({ + kind: "CJSOnlyExportsDefault", + fileName, + range: { + pos: decl.getStart(sourceFile), + end: decl.end, + }, + }); + } + } + } + + return problems; +} diff --git a/packages/core/src/checks/resolutionBasedFileProblems.ts b/packages/core/src/checks/resolutionBasedFileProblems.ts new file mode 100644 index 0000000..afa8f27 --- /dev/null +++ b/packages/core/src/checks/resolutionBasedFileProblems.ts @@ -0,0 +1,94 @@ +import ts from "typescript"; +import type { MultiCompilerHost } from "../multiCompilerHost.js"; +import type { EntrypointInfo, ResolutionBasedFileProblem } from "../types.js"; +import { allResolutionOptions, getResolutionKinds } from "../utils.js"; + +export function getResolutionBasedFileProblems( + packageName: string, + entrypointResolutions: Record, + host: MultiCompilerHost +): ResolutionBasedFileProblem[] { + const result: ResolutionBasedFileProblem[] = []; + for (const resolutionOption of allResolutionOptions) { + const visibleFiles = Object.values(entrypointResolutions).flatMap((entrypoint) => { + const files = new Set(); + getResolutionKinds(resolutionOption).forEach((resolutionKind) => { + entrypoint.resolutions[resolutionKind].files?.forEach((file) => files.add(file)); + if (entrypoint.resolutions[resolutionKind].implementationResolution) { + files.add(entrypoint.resolutions[resolutionKind].implementationResolution!.fileName); + } + }); + return Array.from(files); + }); + + for (const fileName of visibleFiles) { + const sourceFile = host.getSourceFile(fileName, resolutionOption)!; + + if (sourceFile.imports) { + for (const moduleSpecifier of sourceFile.imports) { + const reference = moduleSpecifier.text; + if ( + reference !== packageName && + !reference.startsWith(`${packageName}/`) && + reference[0] !== "#" && + !ts.pathIsRelative(reference) + ) { + // Probably a reference to something we'd have to npm install. + // These can definitely be errors, but I'm not installing a whole + // graph for now. + continue; + } + const resolutionMode = ts.getModeForUsageLocation(sourceFile, moduleSpecifier); + const resolution = ts.getResolvedModule(sourceFile, moduleSpecifier.text, resolutionMode); + + if (!resolution) { + result.push({ + kind: "InternalResolutionError", + resolutionOption, + fileName, + error: { + moduleSpecifier: reference, + pos: moduleSpecifier.pos, + end: moduleSpecifier.end, + resolutionMode, + trace: host.getTrace(resolutionOption, fileName, moduleSpecifier.text, resolutionMode)!, + }, + }); + } + } + } + + if (ts.hasJSFileExtension(fileName)) { + const expectedModuleKind = host.getModuleKindForFile(fileName, resolutionOption); + const syntaxImpliedModuleKind = sourceFile.externalModuleIndicator + ? ts.ModuleKind.ESNext + : sourceFile.commonJsModuleIndicator + ? ts.ModuleKind.CommonJS + : undefined; + if ( + expectedModuleKind !== undefined && + syntaxImpliedModuleKind !== undefined && + expectedModuleKind.detectedKind !== syntaxImpliedModuleKind + ) { + const syntax = sourceFile.externalModuleIndicator ?? sourceFile.commonJsModuleIndicator; + result.push({ + kind: "UnexpectedModuleSyntax", + resolutionOption, + syntax: syntaxImpliedModuleKind, + fileName, + range: + typeof syntax === "object" + ? { + pos: syntax.getStart(sourceFile), + end: syntax.end, + } + : undefined, + moduleKind: expectedModuleKind, + }); + } + } + } + } + + return result; +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index c002fe2..3ab3acc 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,4 +1,3 @@ export * from "./checkPackage.js"; -export * from "./problems.js"; export type * from "./types.js"; export * from './parsePackageSpec.js'; diff --git a/packages/core/src/multiCompilerHost.ts b/packages/core/src/multiCompilerHost.ts new file mode 100644 index 0000000..a7b9450 --- /dev/null +++ b/packages/core/src/multiCompilerHost.ts @@ -0,0 +1,252 @@ +import ts from "typescript"; +import type { FS, ModuleKind, ResolutionOption } from "./types.js"; + +export interface ResolveModuleNameResult { + resolution: ts.ResolvedModuleWithFailedLookupLocations; + trace: string[]; +} + +export interface MultiCompilerHost { + getSourceFile(fileName: string, moduleResolution?: ResolutionOption): ts.SourceFile | undefined; + getImpliedNodeFormatForFile( + fileName: string, + moduleResolution: ResolutionOption + ): ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS | undefined; + getPackageScopeForPath(fileName: string): ts.PackageJsonInfo | undefined; + getModuleKindForFile(fileName: string, moduleResolution: "node16"): ModuleKind; + getModuleKindForFile(fileName: string, moduleResolution: ResolutionOption): ModuleKind | undefined; + resolveModuleName( + moduleName: string, + containingFile: string, + moduleResolution: ResolutionOption, + resolutionMode?: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS, + noDtsResolution?: boolean + ): ResolveModuleNameResult; + getTrace( + moduleResolution: ResolutionOption, + fromFileName: string, + moduleName: string, + resolutionMode: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS | undefined + ): string[] | undefined; + createProgram(moduleResolution: ResolutionOption, rootNames: string[]): ts.Program; +} + +export function createMultiCompilerHost(fs: FS): MultiCompilerHost { + const useCaseSensitiveFileNames = () => false; + const getCanonicalFileName = ts.createGetCanonicalFileName(false); + const getCurrentDirectory = () => "/"; + const getNewLine = () => "\n"; + const getDefaultLibFileName = () => "/node_modules/typescript/lib/lib.d.ts"; + const toPath = (fileName: string) => ts.toPath(fileName, "/", getCanonicalFileName); + const writeFile = () => { + throw new Error("Not implemented"); + }; + const languageVersion = ts.ScriptTarget.Latest; + const traceCollector = createTraceCollector(); + const compilerOptions: Record = { + node10: { + moduleResolution: ts.ModuleResolutionKind.NodeJs, + module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.Latest, + resolveJsonModule: true, + traceResolution: true, + }, + node16: { + moduleResolution: ts.ModuleResolutionKind.Node16, + module: ts.ModuleKind.Node16, + target: ts.ScriptTarget.Latest, + resolveJsonModule: true, + traceResolution: true, + }, + bundler: { + // @ts-expect-error + moduleResolution: ts.ModuleResolutionKind.Bundler, + module: ts.ModuleKind.ESNext, + target: ts.ScriptTarget.Latest, + resolveJsonModule: true, + traceResolution: true, + }, + }; + const moduleResolutionCaches: Record< + ResolutionOption, + [normal: ts.ModuleResolutionCache, noDtsResolution: ts.ModuleResolutionCache] + > = { + node10: [ + ts.createModuleResolutionCache("/", getCanonicalFileName, compilerOptions.node10), + ts.createModuleResolutionCache("/", getCanonicalFileName, compilerOptions.node10), + ], + node16: [ + ts.createModuleResolutionCache("/", getCanonicalFileName, compilerOptions.node16), + ts.createModuleResolutionCache("/", getCanonicalFileName, compilerOptions.node16), + ], + bundler: [ + ts.createModuleResolutionCache("/", getCanonicalFileName, compilerOptions.bundler), + ts.createModuleResolutionCache("/", getCanonicalFileName, compilerOptions.bundler), + ], + }; + const compilerHosts: Record = { + node10: createCompilerHost("node10"), + node16: createCompilerHost("node16"), + bundler: createCompilerHost("bundler"), + }; + const traceCache: Record>> = { + node10: {}, + node16: {}, + bundler: {}, + }; + + return { + getSourceFile, + getImpliedNodeFormatForFile, + getPackageScopeForPath, + getModuleKindForFile, + resolveModuleName, + createProgram, + getTrace, + }; + + function getSourceFile(fileName: string, moduleResolution: ResolutionOption = "bundler"): ts.SourceFile | undefined { + return compilerHosts[moduleResolution].getSourceFile(fileName, languageVersion); + } + + function getImpliedNodeFormatForFile( + fileName: string, + moduleResolution: ResolutionOption + ): ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS | undefined { + return ts.getImpliedNodeFormatForFile( + toPath(fileName), + moduleResolutionCaches[moduleResolution][0].getPackageJsonInfoCache(), + compilerHosts[moduleResolution], + compilerOptions[moduleResolution] + ); + } + + function getPackageScopeForPath(fileName: string): ts.PackageJsonInfo | undefined { + // Which compiler options get used here is irrelevant. + // Use the node16 cache because package.json it should be a hit. + return ts.getPackageScopeForPath( + fileName, + ts.getTemporaryModuleResolutionState( + moduleResolutionCaches.node16[0].getPackageJsonInfoCache(), + compilerHosts.node16, + compilerOptions.node16 + ) + ); + } + + function getModuleKindForFile(fileName: string, moduleResolution: "node16"): ModuleKind; + function getModuleKindForFile(fileName: string, moduleResolution: ResolutionOption): ModuleKind | undefined; + function getModuleKindForFile(fileName: string, moduleResolution: ResolutionOption): ModuleKind | undefined { + const kind = getImpliedNodeFormatForFile(fileName, moduleResolution); + if (kind) { + const extension = ts.getAnyExtensionFromPath(fileName); + const isExtension = + extension === ts.Extension.Cjs || + extension === ts.Extension.Cts || + extension === ts.Extension.Dcts || + extension === ts.Extension.Mjs || + extension === ts.Extension.Mts || + extension === ts.Extension.Dmts; + const reasonPackageJsonInfo = isExtension ? undefined : getPackageScopeForPath(fileName); + const reasonFileName = isExtension + ? fileName + : reasonPackageJsonInfo + ? reasonPackageJsonInfo.packageDirectory + "/package.json" + : fileName; + const reasonPackageJsonType = reasonPackageJsonInfo?.contents?.packageJsonContent.type; + return { + detectedKind: kind, + detectedReason: isExtension ? "extension" : reasonPackageJsonType ? "type" : "no:type", + reasonFileName, + }; + } + } + + function resolveModuleName( + moduleName: string, + containingFile: string, + moduleResolution: ResolutionOption, + resolutionMode?: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS, + noDtsResolution?: boolean + ): ResolveModuleNameResult { + traceCollector.clear(); + const options = compilerOptions[moduleResolution]; + const resolution = ts.resolveModuleName( + moduleName, + containingFile, + noDtsResolution ? { ...options, noDtsResolution } : options, + compilerHosts[moduleResolution], + moduleResolutionCaches[moduleResolution][+!!noDtsResolution], + /*redirectedReference*/ undefined, + resolutionMode + ); + const trace = traceCollector.read(); + const moduleKey = `${resolutionMode ?? 1}:${moduleName}`; + (traceCache[moduleResolution][containingFile] ??= {})[moduleKey] = trace; + return { + resolution, + trace, + }; + } + + function getTrace(moduleResolution: ResolutionOption, fromFileName: string, key: string): string[] | undefined { + return traceCache[moduleResolution][fromFileName]?.[key]; + } + + function createProgram(moduleResolution: ResolutionOption, rootNames: string[]): ts.Program { + return ts.createProgram({ + rootNames, + options: compilerOptions[moduleResolution], + host: compilerHosts[moduleResolution], + }); + } + + function createCompilerHost(moduleResolution: ResolutionOption): ts.CompilerHost { + const sourceFileCache = new Map(); + return { + ...fs, + getSourceFile: (fileName) => { + const path = toPath(fileName); + const cached = sourceFileCache.get(path); + if (cached) { + return cached; + } + const content = fileName.startsWith("/node_modules/typescript/lib") ? "" : fs.readFile(fileName); + const sourceFile = ts.createSourceFile( + fileName, + content, + { + languageVersion, + impliedNodeFormat: getImpliedNodeFormatForFile(fileName, moduleResolution), + }, + /*setParentNodes*/ true + ); + sourceFileCache.set(path, sourceFile); + return sourceFile; + }, + getDefaultLibFileName, + getCurrentDirectory, + writeFile, + getCanonicalFileName, + useCaseSensitiveFileNames, + getNewLine, + trace: traceCollector.trace, + }; + } + + function createTraceCollector() { + const traces: string[] = []; + return { + trace: (message: string) => traces.push(message), + read: () => { + const result = traces.slice(); + clear(); + return result; + }, + clear, + }; + function clear() { + traces.length = 0; + } + } +} diff --git a/packages/core/src/problems.ts b/packages/core/src/problems.ts index 221d33c..c2a2b56 100644 --- a/packages/core/src/problems.ts +++ b/packages/core/src/problems.ts @@ -1,485 +1,173 @@ -import ts from "typescript"; -import type { ModuleKindReason, ResolutionKind, TypedAnalysis } from "./types.js"; -import { allResolutionKinds } from "./utils.js"; - -export type ProblemKind = - | "NoResolution" - | "UntypedResolution" - | "FalseESM" - | "FalseCJS" - | "CJSResolvesToESM" - | "Wildcard" - | "UnexpectedESMSyntax" - | "UnexpectedCJSSyntax" - | "FallbackCondition" - | "CJSOnlyExportsDefault" - | "FalseExportDefault"; - -export interface Problem { - kind: ProblemKind; - entrypoint: string; - resolutionKind: ResolutionKind; -} - -export interface ProblemSummary { - kind: ProblemKind; +import type { Problem, ProblemKind, ResolutionKind, ResolutionOption, Analysis } from "./types.js"; +import { + allResolutionKinds, + getResolutionKinds, + getResolutionOption, + isEntrypointResolutionProblem, + isFileProblem, + isResolutionBasedFileProblem, +} from "./utils.js"; + +export interface ProblemKindInfo { title: string; - messages: { - messageText: string; - messageHtml: string; - }[]; -} - -const problemTitles: Record = { - Wildcard: "Wildcards", - NoResolution: "Resolution failed", - UntypedResolution: "Could not find types", - FalseESM: "Types are ESM, but implementation is CJS", - FalseCJS: "Types are CJS, but implementation is ESM", - CJSResolvesToESM: "Entrypoint is ESM-only", - UnexpectedESMSyntax: "Syntax is incompatible with detected module kind", - UnexpectedCJSSyntax: "Syntax is incompatible with detected module kind", - FallbackCondition: "Resloved through fallback condition", - CJSOnlyExportsDefault: "CJS module uses default export", - FalseExportDefault: "Types incorrectly use default export", -}; - -const moduleResolutionKinds: Record = { - node10: "node10", - "node16-cjs": "node16", - "node16-esm": "node16", - bundler: "bundler", + emoji: string; + shortDescription: string; + description: string; +} + +export const problemKindInfo: Record = { + Wildcard: { + emoji: "❓", + title: "Wildcards", + shortDescription: "Unable to check", + description: "Wildcard subpaths cannot yet be analyzed by this tool.", + }, + NoResolution: { + emoji: "πŸ’€", + title: "Resolution failed", + shortDescription: "Failed to resolve", + description: "Import failed to resolve to type declarations or JavaScript files.", + }, + UntypedResolution: { + emoji: "❌", + title: "Could not find types", + shortDescription: "No types", + description: "Import resolved to JavaScript files, but no type declarations were found.", + }, + FalseCJS: { + emoji: "🎭", + title: "Types are CJS, but implementation is ESM", + shortDescription: "Masquerading as CJS", + description: "Import resolved to a CommonJS type declaration file, but an ESM JavaScript file.", + }, + FalseESM: { + emoji: "πŸ‘Ί", + title: "Types are ESM, but implementation is CJS", + shortDescription: "Masquerading as ESM", + description: "Import resolved to an ESM type declaration file, but a CommonJS JavaScript file.", + }, + CJSResolvesToESM: { + emoji: "⚠️", + title: "Entrypoint is ESM-only", + shortDescription: "ESM (dynamic import only)", + description: + "A `require` call resolved to an ESM JavaScript file, which is an error in Node and some bundlers. CommonJS consumers will need to use a dynamic import.", + }, + FallbackCondition: { + emoji: "πŸ›", + title: "Resloved through fallback condition", + shortDescription: "Used fallback condition", + description: + "Import resolved to types through a conditional package.json export, but only after failing to resolve through an earlier condition. This behavior is a [TypeScript bug](https://github.com/microsoft/TypeScript/issues/50762). It may misrepresent the runtime behavior of this import and should not be relied upon.", + }, + CJSOnlyExportsDefault: { + emoji: "🀨", + title: "CJS module uses default export", + shortDescription: "CJS default export", + description: + "CommonJS module simulates a default export with `exports.default` and `exports.__esModule`, but does not also set `module.exports` for compatibility with Node. Node, and [some bundlers under certain conditions](https://andrewbranch.github.io/interop-test/#synthesizing-default-exports-for-cjs-modules), do not respect the `__esModule` marker, so accessing the intended default export will require a `.default` property access on the default import.", + }, + FalseExportDefault: { + emoji: "❗️", + title: "Types incorrectly use default export", + shortDescription: "Incorrect default export", + description: + "The resolved types use `export default` where the JavaScript file appears to use `module.exports =`. This will cause TypeScript under the `node16` module mode to think an extra `.default` property access is required, but that will likely fail at runtime. These types should use `export =` instead of `export default`.", + }, + UnexpectedModuleSyntax: { + emoji: "🚭", + title: "Syntax is incompatible with detected module kind", + shortDescription: "Unexpected module syntax", + description: + "Syntax detected in the module is incompatible with the module kind according to the package.json or file extension. This is an error in Node and may cause problems in some bundlers.", + }, + InternalResolutionError: { + emoji: "πŸ₯΄", + title: "Internal resolution error", + shortDescription: "Internal resolution error", + description: + "Import found in a type declaration file failed to resolve. Either this indicates that runtime resolution errors will occur, or (more likely) the types misrepresent the contents of the JavaScript files.", + }, }; -export function getSummarizedProblems(analysis: TypedAnalysis): ProblemSummary[] { - return summarizeProblems(getProblems(analysis), analysis); -} - -export function getProblems(analysis: TypedAnalysis): Problem[] { - const problems: Problem[] = []; - for (const subpath in analysis.entrypointResolutions) { - const entrypoint = analysis.entrypointResolutions[subpath]; - for (const kind in entrypoint) { - const resolutionKind = kind as keyof typeof entrypoint; - const result = entrypoint[resolutionKind]; - if (result.isWildcard) { - problems.push({ - kind: "Wildcard", - entrypoint: subpath, - resolutionKind, - }); - continue; - } - if (!result.resolution) { - problems.push({ - kind: "NoResolution", - entrypoint: subpath, - resolutionKind, - }); - } else if (!result.resolution.isTypeScript && !result.resolution.isJson) { - problems.push({ - kind: "UntypedResolution", - entrypoint: subpath, - resolutionKind, - }); - } - - const { resolution, implementationResolution } = result; - if ( - resolution?.moduleKind?.detectedKind === ts.ModuleKind.ESNext && - implementationResolution?.moduleKind?.detectedKind === ts.ModuleKind.CommonJS - ) { - problems.push({ - kind: "FalseESM", - entrypoint: subpath, - resolutionKind, - }); - } else if ( - resolution?.moduleKind?.detectedKind === ts.ModuleKind.CommonJS && - implementationResolution?.moduleKind?.detectedKind === ts.ModuleKind.ESNext - ) { - problems.push({ - kind: "FalseCJS", - entrypoint: subpath, - resolutionKind, - }); - } - - if (resolutionKind === "node16-cjs" && resolution?.moduleKind?.detectedKind === ts.ModuleKind.ESNext) { - problems.push({ - kind: "CJSResolvesToESM", - entrypoint: subpath, - resolutionKind, - }); - } - - if (resolution && resolvedThroughFallback(result.trace)) { - problems.push({ - kind: "FallbackCondition", - entrypoint: subpath, - resolutionKind, - }); - } - - const typesModule = resolution?.exports; - const jsModule = implementationResolution?.exports; - if (resolutionKind === "node16-esm" && resolution && implementationResolution && typesModule && jsModule) { - if (typesModule.default && jsModule[ts.InternalSymbolName.ExportEquals]) { - // Also need to check for `default` property on `jsModule["export="]`? - problems.push({ - kind: "FalseExportDefault", - entrypoint: subpath, - resolutionKind, - }); - } else if ( - typesModule.default && - jsModule.default && - jsModule.__esModule && - !typesModule[ts.InternalSymbolName.ExportEquals] && - !jsModule[ts.InternalSymbolName.ExportEquals] - ) { - problems.push({ - kind: "CJSOnlyExportsDefault", - entrypoint: subpath, - resolutionKind, - }); - } - } - - if ( - implementationResolution?.moduleKind?.syntax && - implementationResolution.moduleKind.syntax !== implementationResolution.moduleKind.detectedKind - ) { - problems.push({ - kind: - implementationResolution.moduleKind.syntax === ts.ModuleKind.ESNext - ? "UnexpectedESMSyntax" - : "UnexpectedCJSSyntax", - entrypoint: subpath, - resolutionKind, - }); - } - } - } - return problems; -} - -export function resolvedThroughFallback(traces: string[]) { - let i = 0; - while (i < traces.length) { - i = traces.indexOf("Entering conditional exports.", i); - if (i === -1) { +export interface ProblemFilter { + kind?: ProblemKind; + entrypoint?: string; + resolutionKind?: ResolutionKind; + resolutionOption?: ResolutionOption; +} + +export function filterProblems(analysis: Analysis, filter: ProblemFilter): Problem[]; +export function filterProblems(problems: readonly Problem[], analysis: Analysis, filter: ProblemFilter): Problem[]; +export function filterProblems( + ...args: + | [analysis: Analysis, filter: ProblemFilter] + | [problems: readonly Problem[], analysis: Analysis, filter: ProblemFilter] +) { + const [problems, analysis, filter] = args.length === 2 ? [args[0].problems, ...args] : args; + return problems.filter((p) => { + if (filter.kind && p.kind !== filter.kind) { return false; } - if (conditionalExportsResolvedThroughFallback()) { - return true; + if (filter.entrypoint && filter.resolutionKind) { + return problemAffectsEntrypointResolution(p, filter.entrypoint, filter.resolutionKind, analysis); } - } - - function conditionalExportsResolvedThroughFallback(): boolean { - i++; - let seenFailure = false; - for (; i < traces.length; i++) { - if (traces[i].startsWith("Failed to resolve under condition '")) { - seenFailure = true; - } else if (seenFailure && traces[i].startsWith("Resolved under condition '")) { - return true; - } else if (traces[i] === "Entering conditional exports.") { - if (conditionalExportsResolvedThroughFallback()) { - return true; - } - } else if (traces[i] === "Exiting conditional exports.") { - return false; - } + if (filter.entrypoint && filter.resolutionOption) { + return getResolutionKinds(filter.resolutionOption).every((resolutionKind) => + problemAffectsEntrypointResolution(p, filter.entrypoint!, resolutionKind, analysis) + ); } - return false; - } -} - -export function groupByKind(problems: Problem[]): Partial> { - const result: Partial> = {}; - for (const problem of problems) { - (result[problem.kind] ??= []).push(problem); - } - return result; -} - -export function summarizeProblems(problems: Problem[], analysis: TypedAnalysis): ProblemSummary[] { - const grouped = groupByKind(problems); - const result: ProblemSummary[] = []; - for (const kind in grouped) { - const problems = grouped[kind as ProblemKind]!; - const summary: ProblemSummary = { - kind: problems[0].kind, - title: problemTitles[problems[0].kind], - messages: getMessages(problems[0].kind, analysis, problems), - }; - result.push(summary); - } - return result; + if (filter.entrypoint) { + return problemAffectsEntrypoint(p, filter.entrypoint, analysis); + } + if (filter.resolutionKind) { + return problemAffectsResolutionKind(p, filter.resolutionKind, analysis); + } + return true; + }); } -function getMessages(kind: ProblemKind, analysis: TypedAnalysis, problems: Problem[]) { - if (kind === "Wildcard") { - return [msg(() => `Wildcards cannot yet be analyzed by this tool.`)]; - } - - const allEntrypoints = new Set(Object.keys(analysis.entrypointResolutions)); - const groupedByEntrypoint = groupByEntrypoint(problems); - const groupedByResolutionKind = groupByResolutionKind(problems); - const fullRows = Object.keys(groupedByResolutionKind) - .map((resolutionKind) => { - const problems = groupedByResolutionKind[resolutionKind as ResolutionKind]; - return problems?.length === allEntrypoints.size ? problems : undefined; - }) - .filter((g): g is Problem[] => !!g); - const fullColumns = Object.keys(groupedByEntrypoint) - .map((entrypoint) => { - const problems = groupedByEntrypoint[entrypoint]; - return problems?.length === allResolutionKinds.length ? problems : undefined; - }) - .filter((g): g is Problem[] => !!g); - - const messages: { messageText: string; messageHtml: string }[] = []; - - if (fullRows.length > 0) { - messages.push( - msg((f) => { - const resolutionKinds = formatResolutionKinds( - fullRows.map((r) => r[0].resolutionKind), - f - ); - return getMessageText( - resolutionKinds, - allEntrypoints.size === 1 ? "the package" : f.strong("all entrypoints"), - analysis, - fullRows.flat(), - f - ); - }) - ); +export function problemAffectsResolutionKind(problem: Problem, resolutionKind: ResolutionKind, analysis: Analysis) { + if (isEntrypointResolutionProblem(problem)) { + return problem.resolutionKind === resolutionKind; } - - if (fullRows.length === allResolutionKinds.length) { - return messages; + if (isResolutionBasedFileProblem(problem)) { + return problem.resolutionOption === getResolutionOption(resolutionKind); } - - if (fullColumns.length > 0) { - messages.push( - msg((f) => { - const entrypoints = formatEntrypoints( - analysis.packageName, - fullColumns.map((c) => c[0].entrypoint), - allEntrypoints.size, - f - ); - return getMessageText(f.strong("all module resolution settings"), entrypoints, analysis, fullColumns.flat(), f); - }) - ); - } - - const remainingProblems = problems.filter( - (p) => - !fullRows.some((r) => r[0].resolutionKind === p.resolutionKind) && - !fullColumns.some((c) => c[0].entrypoint === p.entrypoint) + return Object.values(analysis.entrypoints).some((entrypointInfo) => + entrypointInfo.resolutions[resolutionKind].files?.includes(problem.fileName) ); - if (remainingProblems.length > 0) { - const groupedByEntrypoint = groupByEntrypoint(remainingProblems); - const groupedByResolutionKind = groupByResolutionKind(remainingProblems); - // Report fewer, larger groups - const biggerGroups = - Object.keys(groupedByEntrypoint).length <= Object.keys(groupedByResolutionKind).length - ? groupedByEntrypoint - : groupedByResolutionKind; - for (const groupKey in biggerGroups) { - const problems = - biggerGroups === groupedByEntrypoint - ? groupedByEntrypoint[groupKey] - : biggerGroups[groupKey as ResolutionKind]!; - const entrypoints = biggerGroups === groupedByEntrypoint ? [groupKey] : problems.map((p) => p.entrypoint); - const resolutionKinds = - biggerGroups === groupedByResolutionKind ? [groupKey as ResolutionKind] : problems.map((p) => p.resolutionKind); - messages.push( - msg((f) => - getMessageText( - formatResolutionKinds(resolutionKinds, f), - formatEntrypoints(analysis.packageName, entrypoints, allEntrypoints.size, f), - analysis, - problems, - f - ) - ) - ); - } - } - return messages; - - function getMessageText( - resolutionKinds: string, - entrypoints: string, - analysis: TypedAnalysis, - problems: readonly Problem[], - f: Formatters - ): string { - switch (kind) { - case "NoResolution": - return `Imports of ${entrypoints} under ${resolutionKinds} failed to resolve.`; - case "UntypedResolution": - return `Imports of ${entrypoints} under ${resolutionKinds} resolved to JavaScript files, but no types.`; - case "FalseESM": - return `Imports of ${entrypoints} under ${resolutionKinds} resolved to ESM types, but CJS implementations.`; - case "FalseCJS": - return `Imports of ${entrypoints} under ${resolutionKinds} resolved to CJS types, but ESM implementations.`; - case "CJSResolvesToESM": - return `Imports of ${entrypoints} resolved to ES modules from a CJS importing module. CJS modules in Node will only be able to access this entrypoint with a dynamic import.`; - case "Wildcard": - throw new Error("Wildcard should have been handled above."); - case "FallbackCondition": - return ( - `Imports of ${entrypoints} under ${resolutionKinds} resolved through a conditional package.json export, but ` + - `only after failing to resolve through an earlier condition. This behavior is a ${f.a( - "TypeScript bug", - "https://github.com/microsoft/TypeScript/issues/50762" - )} and should not be relied upon.` - ); - case "CJSOnlyExportsDefault": - // Only issued in node16-esm - return ( - `The CJS module resolved at ${entrypoints} under contains a simulated ` + - `${f.code("export default")} with an ${f.code("__esModule")} marker, but no top-level ` + - `${f.code("module.exports")}. Node does not respect the ${f.code("__esModule")} marker, ` + - `so accessing the intended default export will require a ${f.code(".default")} property ` + - `access in Node from an ES module.` - ); - case "FalseExportDefault": - // Only issued in node16-esm - return ( - `The types resolved at ${entrypoints} use ${f.code("export default")} where the implementation ` + - `appears to use ${f.code("module.exports =")}. Node treats a default import of these constructs from an ` + - `ES module differently, so these types will make TypeScript under the ${f.code("node16")} resolution mode ` + - `think an extra ${f.code(".default")} property access is required, but that will likely fail at runtime ` + - `in Node. These types should use ${f.code("export =")} instead of ${f.code("export default")}.` - ); - case "UnexpectedESMSyntax": - case "UnexpectedCJSSyntax": - // Issued in node16-esm and node16-cjs - const reason = problems.reduce((prevReason: ModuleKindReason | undefined, p) => { - const reason = - analysis.entrypointResolutions[p.entrypoint]["node16-esm"].implementationResolution?.moduleKind - ?.detectedReason; - return !prevReason ? reason : prevReason === reason ? reason : undefined; - }, undefined); - const [syntax, moduleKind] = - kind === "UnexpectedCJSSyntax" ? (["CJS", "ESM"] as const) : (["ESM", "CJS"] as const); - return ( - `The implementation resolved at ${entrypoints} uses ${syntax} syntax, but the detected module kind is ${moduleKind}. ` + - `This will be an error in Node (and potentially other runtimes and bundlers).` + - (reason === "extension" - ? ` The module kind was decided based on the resolved file’s ${ - moduleKind === "ESM" ? f.code(".mjs") : f.code(".cjs") - } extension.` - : reason === "type" - ? ` The module kind was decided based on the nearest package.json’s ${f.code(`"type"`)} field.` - : reason === "no:type" - ? ` The module kind was decided based on the nearest package.json’s lack of a ${f.code( - `"type": "module"` - )} field.` - : "") - ); - } - } -} - -function groupByResolutionKind(problems: Problem[]) { - return problems.reduce((result: Partial>, problem) => { - (result[problem.resolutionKind] ??= []).push(problem); - return result; - }, {}); -} - -function groupByEntrypoint(problems: Problem[]) { - return problems.reduce((result: Record, problem) => { - (result[problem.entrypoint] ??= []).push(problem); - return result; - }, {}); } -function formatResolutionKind(kind: ResolutionKind, f: Formatters) { - switch (kind) { - case "node10": - case "bundler": - return `the ${f.code(moduleResolutionKinds[kind])} module resolution setting`; - case "node16-cjs": - return ( - `the ${f.code("node16")} module resolution setting when the importing module is CJS ` + - `(its extension is ${f.code(".cts")} or ${f.code(".cjs")}, or it has a ` + - `${f.code(".ts")} or ${f.code(".js")} extension and is in scope of a ${f.code("package.json")} ` + - `that does not contain ${f.code('"type": "module"')})` - ); - case "node16-esm": - return ( - `the ${f.code("node16")} module resolution setting when the importing module is ESM ` + - `(its extension is ${f.code(".mts")} or ${f.code(".mjs")}, or it has a ` + - `${f.code(".ts")} or ${f.code(".js")} extension and is in scope of a ${f.code("package.json")} ` + - `that contains ${f.code('"type": "module"')})` - ); +export function problemAffectsEntrypoint(problem: Problem, entrypoint: string, analysis: Analysis) { + if (isEntrypointResolutionProblem(problem)) { + return problem.entrypoint === entrypoint; } + return allResolutionKinds.some((resolutionKind) => + analysis.entrypoints[entrypoint].resolutions[resolutionKind].files?.includes(problem.fileName) + ); } -function formatResolutionKinds(kinds: ResolutionKind[], f: Formatters) { - if (kinds.length === 1) { - return formatResolutionKind(kinds[0], f); - } else if (kinds.length === 2 && kinds.includes("node16-cjs") && kinds.includes("node16-esm")) { - return `the ${f.code("node16")} module resolution setting`; - } else if (kinds.length === allResolutionKinds.length - 1 && !kinds.includes("node10")) { - return f.strong("all modern module resolution settings"); - } else if (kinds.length === allResolutionKinds.length) { - return f.strong("all module resolution settings"); - } else if (kinds.length === 2 && kinds.includes("node16-esm") && kinds.includes("bundler")) { - return `resolution modes that use the ${f.code("import")} condition in package.json ${f.code(`"exports"`)}`; - } else { - return f.strong("multiple module resolution settings"); +export function problemAffectsEntrypointResolution( + problem: Problem, + entrypoint: string, + resolutionKind: ResolutionKind, + analysis: Analysis +) { + if (isEntrypointResolutionProblem(problem)) { + return problem.entrypoint === entrypoint && problem.resolutionKind === resolutionKind; } -} - -function formatEntrypoints(packageName: string, entrypoints: string[], entrypointCount: number, f: Formatters) { - if (entrypoints.length === 1) { - return formatEntrypoint(packageName, entrypoints[0], f); + if (isResolutionBasedFileProblem(problem)) { + return ( + getResolutionOption(resolutionKind) === problem.resolutionOption && + analysis.entrypoints[entrypoint].resolutions[resolutionKind].files?.includes(problem.fileName) + ); } - if (entrypoints.length === entrypointCount) { - return f.strong("all entrypoints"); + if (isFileProblem(problem)) { + return ( + analysis.entrypoints[entrypoint].resolutions[resolutionKind].files?.includes(problem.fileName) || + analysis.entrypoints[entrypoint].resolutions[resolutionKind].files + ); } - return f.strong("multiple entrypoints"); -} - -function formatEntrypoint(packageName: string, subpath: string, f: Formatters) { - return f.code(`"${subpath === "." ? packageName : `${packageName}/${subpath.substring(2)}`}"`); -} - -type Formatters = Record<"strong" | "em" | "code", (text: string) => string> & { - a: (text: string, href: string) => string; -}; -const identity = (x: T) => x; -const textFormatters: Formatters = { - strong: identity, - em: identity, - code: (text) => "`" + text + "`", - a: (text, href) => `${text} (${href})`, -}; -const htmlFormatters: Formatters = { - strong: (text) => `${text}`, - em: (text) => `${text}`, - code: (text) => `${nonBreaking(text)}`, - a: (text, href) => `${text}`, -}; - -function nonBreaking(text: string) { - return text.length < 20 ? text.replace(/ /g, "\u00a0") : text; -} - -function msg(cb: (format: Formatters) => string): { messageText: string; messageHtml: string } { - return { - messageText: cb(textFormatters), - messageHtml: cb(htmlFormatters), - }; + throw new Error(`Unhandled problem type '${(problem satisfies never as Problem).kind}'`); } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 58df27f..d1b8aaa 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -12,46 +12,38 @@ export interface FS { listFiles: () => string[]; } -export interface TraceCollector { - trace: (message: string) => void; - read: () => string[]; -} - -export type SourceFileCache = Record; - export type ResolutionKind = "node10" | "node16-cjs" | "node16-esm" | "bundler"; +export type ResolutionOption = "node10" | "node16" | "bundler"; +export interface EntrypointInfo { + subpath: string; + resolutions: Record; + hasTypes: boolean; + isWildcard: boolean; +} -export type EntrypointResolutions = Record>; - -export interface TypedAnalysis { +export interface Analysis { packageName: string; packageVersion: string; - containsTypes: true; - entrypointResolutions: EntrypointResolutions; -} - -export type SymbolTable = Record; - -export interface Symbol { - name: string; - flags: ts.SymbolFlags; - valueDeclarationRange: [number, number] | undefined; + types: "included"; + entrypoints: Record; + problems: Problem[]; } -export interface UntypedAnalysis { +export interface UntypedResult { packageName: string; packageVersion: string; - containsTypes: false; + types: false; } -export type Analysis = TypedAnalysis | UntypedAnalysis; +export type CheckResult = Analysis | UntypedResult; export interface EntrypointResolutionAnalysis { name: string; + resolutionKind: ResolutionKind; isWildcard?: boolean; resolution?: Resolution; implementationResolution?: Resolution; - trace: string[]; + files?: string[]; } export type ModuleKindReason = "extension" | "type" | "no:type"; @@ -59,7 +51,6 @@ export interface ModuleKind { detectedKind: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS; detectedReason: ModuleKindReason; reasonFileName: string; - syntax: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS | undefined; } export interface Resolution { @@ -67,18 +58,65 @@ export interface Resolution { isTypeScript: boolean; isJson: boolean; moduleKind: ModuleKind | undefined; - exports?: SymbolTable | false; + trace: string[]; +} + +export interface InternalResolutionErrorDetails { + pos: number; + end: number; + moduleSpecifier: string; + resolutionMode: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS | undefined; + trace: string[]; } +export type EntrypointResolutionProblemKind = + | "NoResolution" + | "UntypedResolution" + | "FalseESM" + | "FalseCJS" + | "CJSResolvesToESM" + | "Wildcard" + | "FallbackCondition" + | "FalseExportDefault"; + +export interface EntrypointResolutionProblem { + kind: EntrypointResolutionProblemKind; + entrypoint: string; + resolutionKind: ResolutionKind; +} + +export interface InternalResolutionProblem { + kind: "InternalResolutionError"; + resolutionOption: ResolutionOption; + fileName: string; + error: InternalResolutionErrorDetails; +} + +export interface UnexpectedModuleSyntaxProblem { + kind: "UnexpectedModuleSyntax"; + resolutionOption: ResolutionOption; + syntax: ts.ModuleKind.ESNext | ts.ModuleKind.CommonJS; + moduleKind: ModuleKind; + fileName: string; + range?: ts.TextRange; +} + +export interface CJSOnlyExportsDefaultProblem { + kind: "CJSOnlyExportsDefault"; + fileName: string; + range: ts.TextRange; +} + +export type ResolutionBasedFileProblem = InternalResolutionProblem | UnexpectedModuleSyntaxProblem; +export type FileProblem = CJSOnlyExportsDefaultProblem; +export type Problem = EntrypointResolutionProblem | ResolutionBasedFileProblem | FileProblem; +export type ProblemKind = Problem["kind"]; +export type FileProblemKind = FileProblem["kind"]; +export type ResolutionBasedFileProblemKind = ResolutionBasedFileProblem["kind"]; + export type Failable = { status: "error"; error: string } | { status: "success"; data: T }; export interface ParsedPackageSpec { packageName: string; version: string | undefined; } - -declare global { - interface ImportMeta { - env?: Record; - } -} diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index 5c7ef05..8f32ea8 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -1,3 +1,144 @@ -import type { ResolutionKind } from "./types.js"; +import type { + EntrypointInfo, + EntrypointResolutionAnalysis, + EntrypointResolutionProblem, + FileProblem, + Problem, + ProblemKind, + ResolutionBasedFileProblem, + ResolutionKind, + ResolutionOption, +} from "./types.js"; +export const allResolutionOptions: ResolutionOption[] = ["node10", "node16", "bundler"]; export const allResolutionKinds: ResolutionKind[] = ["node10", "node16-cjs", "node16-esm", "bundler"]; + +export function getResolutionOption(resolutionKind: ResolutionKind): ResolutionOption { + switch (resolutionKind) { + case "node10": + return "node10"; + case "node16-cjs": + case "node16-esm": + return "node16"; + case "bundler": + return "bundler"; + } +} + +export function getResolutionKinds(resolutionOption: ResolutionOption): ResolutionKind[] { + switch (resolutionOption) { + case "node10": + return ["node10"]; + case "node16": + return ["node16-cjs", "node16-esm"]; + case "bundler": + return ["bundler"]; + } +} + +export function isDefined(value: T | undefined): value is T { + return value !== undefined; +} + +export function resolvedThroughFallback(traces: string[]) { + let i = 0; + while (i < traces.length) { + i = traces.indexOf("Entering conditional exports.", i); + if (i === -1) { + return false; + } + if (conditionalExportsResolvedThroughFallback()) { + return true; + } + } + + function conditionalExportsResolvedThroughFallback(): boolean { + i++; + let seenFailure = false; + for (; i < traces.length; i++) { + if (traces[i].startsWith("Failed to resolve under condition '")) { + seenFailure = true; + } else if (seenFailure && traces[i].startsWith("Resolved under condition '")) { + return true; + } else if (traces[i] === "Entering conditional exports.") { + if (conditionalExportsResolvedThroughFallback()) { + return true; + } + } else if (traces[i] === "Exiting conditional exports.") { + return false; + } + } + return false; + } +} + +export function visitResolutions( + entrypoints: Record, + visitor: (analysis: EntrypointResolutionAnalysis, info: EntrypointInfo) => unknown +) { + for (const entrypoint of Object.values(entrypoints)) { + for (const resolution of Object.values(entrypoint.resolutions)) { + if (visitor(resolution, entrypoint)) { + return; + } + } + } +} + +type AssertNever = T; + +export function isEntrypointResolutionProblemKind(kind: ProblemKind): kind is EntrypointResolutionProblem["kind"] { + switch (kind) { + case "NoResolution": + case "UntypedResolution": + case "FalseESM": + case "FalseCJS": + case "CJSResolvesToESM": + case "Wildcard": + case "FallbackCondition": + case "FalseExportDefault": + return true; + default: + return false as AssertNever; + } +} + +export function isEntrypointResolutionProblem(problem: Problem): problem is EntrypointResolutionProblem { + return isEntrypointResolutionProblemKind(problem.kind); +} + +export function isFileProblemKind(kind: ProblemKind): kind is FileProblem["kind"] { + switch (kind) { + case "CJSOnlyExportsDefault": + return true; + default: + return false as AssertNever; + } +} + +export function isFileProblem(problem: Problem): problem is FileProblem { + return isFileProblemKind(problem.kind); +} + +export function isResolutionBasedFileProblemKind(kind: ProblemKind): kind is ResolutionBasedFileProblem["kind"] { + switch (kind) { + case "InternalResolutionError": + case "UnexpectedModuleSyntax": + return true; + default: + return false as AssertNever; + } +} + +export function isResolutionBasedFileProblem(problem: Problem): problem is ResolutionBasedFileProblem { + return isResolutionBasedFileProblemKind(problem.kind); +} +export function groupProblemsByKind( + problems: (Problem & { kind: K })[] +): Partial> { + const result: Partial> = {}; + for (const problem of problems) { + (result[problem.kind] ??= []).push(problem); + } + return result; +} diff --git a/packages/core/test/fixtures/@reduxjs__toolkit@2.0.0-beta.0.tgz b/packages/core/test/fixtures/@reduxjs__toolkit@2.0.0-beta.0.tgz new file mode 100644 index 0000000..c3980a9 Binary files /dev/null and b/packages/core/test/fixtures/@reduxjs__toolkit@2.0.0-beta.0.tgz differ diff --git a/packages/core/test/problems/resolvedThroughFallback.test.ts b/packages/core/test/problems/resolvedThroughFallback.test.ts index 920f1e6..16a4a6a 100644 --- a/packages/core/test/problems/resolvedThroughFallback.test.ts +++ b/packages/core/test/problems/resolvedThroughFallback.test.ts @@ -1,6 +1,6 @@ import assert from "node:assert"; import { test } from "node:test"; -import { resolvedThroughFallback } from "@arethetypeswrong/core/problems"; +import { resolvedThroughFallback } from "@arethetypeswrong/core/utils"; test("resolvedThroughFallback", () => { assert.ok(!resolvedThroughFallback([])); diff --git a/packages/core/test/snapshots.test.ts b/packages/core/test/snapshots.test.ts index 2f0e310..e6d256f 100644 --- a/packages/core/test/snapshots.test.ts +++ b/packages/core/test/snapshots.test.ts @@ -2,7 +2,7 @@ import fs from "fs"; import { access, readFile, writeFile } from "fs/promises"; import assert from "node:assert"; import { after, describe, test } from "node:test"; -import { checkTgz, getProblems, summarizeProblems } from "@arethetypeswrong/core"; +import { checkTgz } from "@arethetypeswrong/core"; const updateSnapshots = process.env.UPDATE_SNAPSHOTS; @@ -28,22 +28,14 @@ describe("snapshots", async () => { test(fixture, async () => { const tarball = await readFile(new URL(`../fixtures/${fixture}`, import.meta.url)); const analysis = await checkTgz(tarball); - const problems = analysis.containsTypes ? getProblems(analysis) : undefined; - const summary = analysis.containsTypes ? summarizeProblems(problems!, analysis) : undefined; const snapshotURL = new URL(`../snapshots/${fixture}.md`, import.meta.url); const expectedSnapshot = [ `# ${fixture}`, "", - "## Summary", - "", - "```json", - JSON.stringify(summary, null, 2), - "```", - "", "## Problems", "", "```json", - JSON.stringify(problems, null, 2), + JSON.stringify(analysis.types ? analysis.problems : [], null, 2), "```", ].join("\n"); diff --git a/packages/core/test/snapshots/@reduxjs__toolkit@2.0.0-beta.0.tgz.md b/packages/core/test/snapshots/@reduxjs__toolkit@2.0.0-beta.0.tgz.md new file mode 100644 index 0000000..7ed9712 --- /dev/null +++ b/packages/core/test/snapshots/@reduxjs__toolkit@2.0.0-beta.0.tgz.md @@ -0,0 +1,343 @@ +# @reduxjs__toolkit@2.0.0-beta.0.tgz + +## Problems + +```json +[ + { + "kind": "FalseCJS", + "entrypoint": ".", + "resolutionKind": "node16-esm" + }, + { + "kind": "FalseCJS", + "entrypoint": "./react", + "resolutionKind": "node16-esm" + }, + { + "kind": "FalseCJS", + "entrypoint": "./query", + "resolutionKind": "node16-esm" + }, + { + "kind": "FalseCJS", + "entrypoint": "./query/react", + "resolutionKind": "node16-esm" + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/dynamicMiddleware/react/index.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/tsHelpers", + "pos": 153, + "end": 187, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/dynamicMiddleware/react/index.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/dynamicMiddleware/types", + "pos": 379, + "end": 427, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/apiState", + "pos": 157, + "end": 201, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/endpointDefinitions", + "pos": 311, + "end": 361, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/buildSelectors", + "pos": 424, + "end": 474, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/buildInitiate", + "pos": 551, + "end": 600, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/defaultSerializeQueryArgs", + "pos": 642, + "end": 698, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/apiTypes", + "pos": 737, + "end": 776, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/tsHelpers", + "pos": 821, + "end": 861, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/module", + "pos": 912, + "end": 954, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/namedHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/endpointDefinitions", + "pos": 167, + "end": 217, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/module.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/endpointDefinitions", + "pos": 155, + "end": 205, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/module.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/baseQueryTypes", + "pos": 284, + "end": 329, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/ApiProvider.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/apiTypes", + "pos": 181, + "end": 220, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/index.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/module", + "pos": 257, + "end": 298, + "resolutionMode": 1 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/dynamicMiddleware/react/index.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/tsHelpers", + "pos": 153, + "end": 187 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/dynamicMiddleware/react/index.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/dynamicMiddleware/types", + "pos": 379, + "end": 427 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/apiState", + "pos": 157, + "end": 201 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/endpointDefinitions", + "pos": 311, + "end": 361 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/buildSelectors", + "pos": 424, + "end": 474 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/buildInitiate", + "pos": 551, + "end": 600 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/defaultSerializeQueryArgs", + "pos": 642, + "end": 698 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/apiTypes", + "pos": 737, + "end": 776 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/tsHelpers", + "pos": 821, + "end": 861 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/buildHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/module", + "pos": 912, + "end": 954 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/namedHooks.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/endpointDefinitions", + "pos": 167, + "end": 217 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/module.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/endpointDefinitions", + "pos": 155, + "end": 205 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/module.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/baseQueryTypes", + "pos": 284, + "end": 329 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/ApiProvider.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/apiTypes", + "pos": 181, + "end": 220 + } + }, + { + "kind": "InternalResolutionError", + "resolutionOption": "bundler", + "fileName": "/node_modules/@reduxjs/toolkit/dist/query/react/index.d.ts", + "error": { + "moduleSpecifier": "@reduxjs/toolkit/dist/query/core/module", + "pos": 257, + "end": 298 + } + } +] +``` \ No newline at end of file diff --git a/packages/core/test/snapshots/@vitejs__plugin-react@3.1.0.tgz.md b/packages/core/test/snapshots/@vitejs__plugin-react@3.1.0.tgz.md index dd6ff53..51999ca 100644 --- a/packages/core/test/snapshots/@vitejs__plugin-react@3.1.0.tgz.md +++ b/packages/core/test/snapshots/@vitejs__plugin-react@3.1.0.tgz.md @@ -1,22 +1,5 @@ # @vitejs__plugin-react@3.1.0.tgz -## Summary - -```json -[ - { - "kind": "FalseCJS", - "title": "Types are CJS, but implementation is ESM", - "messages": [ - { - "messageText": "Imports of the package under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `\"type\": \"module\"`) resolved to CJS types, but ESM implementations.", - "messageHtml": "Imports of the package under the node16 module resolution setting when the importing module is ESM (its extension is .mts or .mjs, or it has a .ts or .js extension and is in scope of a package.json that contains \"type\":Β \"module\") resolved to CJS types, but ESM implementations." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/ajv@8.12.0.tgz.md b/packages/core/test/snapshots/ajv@8.12.0.tgz.md index c0c6e0a..93d6620 100644 --- a/packages/core/test/snapshots/ajv@8.12.0.tgz.md +++ b/packages/core/test/snapshots/ajv@8.12.0.tgz.md @@ -1,22 +1,5 @@ # ajv@8.12.0.tgz -## Summary - -```json -[ - { - "kind": "FalseExportDefault", - "title": "Types incorrectly use default export", - "messages": [ - { - "messageText": "The types resolved at the package use `export default` where the implementation appears to use `module.exports =`. Node treats a default import of these constructs from an ES module differently, so these types will make TypeScript under the `node16` resolution mode think an extra `.default` property access is required, but that will likely fail at runtime in Node. These types should use `export =` instead of `export default`.", - "messageHtml": "The types resolved at the package use exportΒ default where the implementation appears to use module.exportsΒ =. Node treats a default import of these constructs from an ES module differently, so these types will make TypeScript under the node16 resolution mode think an extra .default property access is required, but that will likely fail at runtime in Node. These types should use exportΒ = instead of exportΒ default." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/astring@1.8.6.tgz.md b/packages/core/test/snapshots/astring@1.8.6.tgz.md index 6ff31d6..ece7f99 100644 --- a/packages/core/test/snapshots/astring@1.8.6.tgz.md +++ b/packages/core/test/snapshots/astring@1.8.6.tgz.md @@ -1,22 +1,5 @@ # astring@1.8.6.tgz -## Summary - -```json -[ - { - "kind": "FalseCJS", - "title": "Types are CJS, but implementation is ESM", - "messages": [ - { - "messageText": "Imports of the package under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `\"type\": \"module\"`) resolved to CJS types, but ESM implementations.", - "messageHtml": "Imports of the package under the node16 module resolution setting when the importing module is ESM (its extension is .mts or .mjs, or it has a .ts or .js extension and is in scope of a package.json that contains \"type\":Β \"module\") resolved to CJS types, but ESM implementations." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/axios@1.4.0.tgz.md b/packages/core/test/snapshots/axios@1.4.0.tgz.md index c132642..7ea8af3 100644 --- a/packages/core/test/snapshots/axios@1.4.0.tgz.md +++ b/packages/core/test/snapshots/axios@1.4.0.tgz.md @@ -1,60 +1,5 @@ # axios@1.4.0.tgz -## Summary - -```json -[ - { - "kind": "Wildcard", - "title": "Wildcards", - "messages": [ - { - "messageText": "Wildcards cannot yet be analyzed by this tool.", - "messageHtml": "Wildcards cannot yet be analyzed by this tool." - } - ] - }, - { - "kind": "NoResolution", - "title": "Resolution failed", - "messages": [ - { - "messageText": "Imports of multiple entrypoints under the `node10` module resolution setting failed to resolve.", - "messageHtml": "Imports of multiple entrypoints under the node10 module resolution setting failed to resolve." - } - ] - }, - { - "kind": "UntypedResolution", - "title": "Could not find types", - "messages": [ - { - "messageText": "Imports of multiple entrypoints under the `node16` module resolution setting when the importing module is CJS (its extension is `.cts` or `.cjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that does not contain `\"type\": \"module\"`) resolved to JavaScript files, but no types.", - "messageHtml": "Imports of multiple entrypoints under the node16 module resolution setting when the importing module is CJS (its extension is .cts or .cjs, or it has a .ts or .js extension and is in scope of a package.json that does not contain \"type\":Β \"module\") resolved to JavaScript files, but no types." - }, - { - "messageText": "Imports of multiple entrypoints under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `\"type\": \"module\"`) resolved to JavaScript files, but no types.", - "messageHtml": "Imports of multiple entrypoints under the node16 module resolution setting when the importing module is ESM (its extension is .mts or .mjs, or it has a .ts or .js extension and is in scope of a package.json that contains \"type\":Β \"module\") resolved to JavaScript files, but no types." - }, - { - "messageText": "Imports of multiple entrypoints under the `bundler` module resolution setting resolved to JavaScript files, but no types.", - "messageHtml": "Imports of multiple entrypoints under the bundler module resolution setting resolved to JavaScript files, but no types." - } - ] - }, - { - "kind": "CJSResolvesToESM", - "title": "Entrypoint is ESM-only", - "messages": [ - { - "messageText": "Imports of multiple entrypoints resolved to ES modules from a CJS importing module. CJS modules in Node will only be able to access this entrypoint with a dynamic import.", - "messageHtml": "Imports of multiple entrypoints resolved to ES modules from a CJS importing module. CJS modules in Node will only be able to access this entrypoint with a dynamic import." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/commander@10.0.1.tgz.md b/packages/core/test/snapshots/commander@10.0.1.tgz.md index f0a015e..4e5f9b1 100644 --- a/packages/core/test/snapshots/commander@10.0.1.tgz.md +++ b/packages/core/test/snapshots/commander@10.0.1.tgz.md @@ -1,42 +1,5 @@ # commander@10.0.1.tgz -## Summary - -```json -[ - { - "kind": "FalseCJS", - "title": "Types are CJS, but implementation is ESM", - "messages": [ - { - "messageText": "Imports of `\"commander\"` under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `\"type\": \"module\"`) resolved to CJS types, but ESM implementations.", - "messageHtml": "Imports of \"commander\" under the node16 module resolution setting when the importing module is ESM (its extension is .mts or .mjs, or it has a .ts or .js extension and is in scope of a package.json that contains \"type\":Β \"module\") resolved to CJS types, but ESM implementations." - } - ] - }, - { - "kind": "UntypedResolution", - "title": "Could not find types", - "messages": [ - { - "messageText": "Imports of `\"commander/esm.mjs\"` under all module resolution settings resolved to JavaScript files, but no types.", - "messageHtml": "Imports of \"commander/esm.mjs\" under all module resolution settings resolved to JavaScript files, but no types." - } - ] - }, - { - "kind": "CJSResolvesToESM", - "title": "Entrypoint is ESM-only", - "messages": [ - { - "messageText": "Imports of `\"commander/esm.mjs\"` resolved to ES modules from a CJS importing module. CJS modules in Node will only be able to access this entrypoint with a dynamic import.", - "messageHtml": "Imports of \"commander/esm.mjs\" resolved to ES modules from a CJS importing module. CJS modules in Node will only be able to access this entrypoint with a dynamic import." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/ejs@3.1.9.tgz.md b/packages/core/test/snapshots/ejs@3.1.9.tgz.md index 2d0747f..7e49dad 100644 --- a/packages/core/test/snapshots/ejs@3.1.9.tgz.md +++ b/packages/core/test/snapshots/ejs@3.1.9.tgz.md @@ -1,13 +1,7 @@ # ejs@3.1.9.tgz -## Summary - -```json - -``` - ## Problems ```json - +[] ``` \ No newline at end of file diff --git a/packages/core/test/snapshots/hexoid@1.0.0.tgz.md b/packages/core/test/snapshots/hexoid@1.0.0.tgz.md index ba7b654..a6f500b 100644 --- a/packages/core/test/snapshots/hexoid@1.0.0.tgz.md +++ b/packages/core/test/snapshots/hexoid@1.0.0.tgz.md @@ -1,22 +1,5 @@ # hexoid@1.0.0.tgz -## Summary - -```json -[ - { - "kind": "FalseExportDefault", - "title": "Types incorrectly use default export", - "messages": [ - { - "messageText": "The types resolved at the package use `export default` where the implementation appears to use `module.exports =`. Node treats a default import of these constructs from an ES module differently, so these types will make TypeScript under the `node16` resolution mode think an extra `.default` property access is required, but that will likely fail at runtime in Node. These types should use `export =` instead of `export default`.", - "messageHtml": "The types resolved at the package use exportΒ default where the implementation appears to use module.exportsΒ =. Node treats a default import of these constructs from an ES module differently, so these types will make TypeScript under the node16 resolution mode think an extra .default property access is required, but that will likely fail at runtime in Node. These types should use exportΒ = instead of exportΒ default." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/klona@2.0.6.tgz.md b/packages/core/test/snapshots/klona@2.0.6.tgz.md index 26f1b39..0afa097 100644 --- a/packages/core/test/snapshots/klona@2.0.6.tgz.md +++ b/packages/core/test/snapshots/klona@2.0.6.tgz.md @@ -1,22 +1,5 @@ # klona@2.0.6.tgz -## Summary - -```json -[ - { - "kind": "FalseCJS", - "title": "Types are CJS, but implementation is ESM", - "messages": [ - { - "messageText": "Imports of multiple entrypoints under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `\"type\": \"module\"`) resolved to CJS types, but ESM implementations.", - "messageHtml": "Imports of multiple entrypoints under the node16 module resolution setting when the importing module is ESM (its extension is .mts or .mjs, or it has a .ts or .js extension and is in scope of a package.json that contains \"type\":Β \"module\") resolved to CJS types, but ESM implementations." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/node-html-parser@6.1.5.tgz.md b/packages/core/test/snapshots/node-html-parser@6.1.5.tgz.md index f99ad01..1d66cdd 100644 --- a/packages/core/test/snapshots/node-html-parser@6.1.5.tgz.md +++ b/packages/core/test/snapshots/node-html-parser@6.1.5.tgz.md @@ -1,30 +1,16 @@ # node-html-parser@6.1.5.tgz -## Summary - -```json -[ - { - "kind": "CJSOnlyExportsDefault", - "title": "CJS module uses default export", - "messages": [ - { - "messageText": "The CJS module resolved at the package under contains a simulated `export default` with an `__esModule` marker, but no top-level `module.exports`. Node does not respect the `__esModule` marker, so accessing the intended default export will require a `.default` property access in Node from an ES module.", - "messageHtml": "The CJS module resolved at the package under contains a simulated exportΒ default with an __esModule marker, but no top-level module.exports. Node does not respect the __esModule marker, so accessing the intended default export will require a .default property access in Node from an ES module." - } - ] - } -] -``` - ## Problems ```json [ { "kind": "CJSOnlyExportsDefault", - "entrypoint": ".", - "resolutionKind": "node16-esm" + "fileName": "/node_modules/node-html-parser/dist/index.js", + "range": { + "pos": 1077, + "end": 1092 + } } ] ``` \ No newline at end of file diff --git a/packages/core/test/snapshots/postcss@8.4.21.tgz.md b/packages/core/test/snapshots/postcss@8.4.21.tgz.md index 09f39c3..575b43b 100644 --- a/packages/core/test/snapshots/postcss@8.4.21.tgz.md +++ b/packages/core/test/snapshots/postcss@8.4.21.tgz.md @@ -1,52 +1,5 @@ # postcss@8.4.21.tgz -## Summary - -```json -[ - { - "kind": "FalseCJS", - "title": "Types are CJS, but implementation is ESM", - "messages": [ - { - "messageText": "Imports of `\"postcss\"` under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `\"type\": \"module\"`) resolved to CJS types, but ESM implementations.", - "messageHtml": "Imports of \"postcss\" under the node16 module resolution setting when the importing module is ESM (its extension is .mts or .mjs, or it has a .ts or .js extension and is in scope of a package.json that contains \"type\":Β \"module\") resolved to CJS types, but ESM implementations." - } - ] - }, - { - "kind": "FallbackCondition", - "title": "Resloved through fallback condition", - "messages": [ - { - "messageText": "Imports of `\"postcss\"` under resolution modes that use the `import` condition in package.json `\"exports\"` resolved through a conditional package.json export, but only after failing to resolve through an earlier condition. This behavior is a TypeScript bug (https://github.com/microsoft/TypeScript/issues/50762) and should not be relied upon.", - "messageHtml": "Imports of \"postcss\" under resolution modes that use the import condition in package.json \"exports\" resolved through a conditional package.json export, but only after failing to resolve through an earlier condition. This behavior is a TypeScript bug and should not be relied upon." - } - ] - }, - { - "kind": "FalseExportDefault", - "title": "Types incorrectly use default export", - "messages": [ - { - "messageText": "The types resolved at multiple entrypoints use `export default` where the implementation appears to use `module.exports =`. Node treats a default import of these constructs from an ES module differently, so these types will make TypeScript under the `node16` resolution mode think an extra `.default` property access is required, but that will likely fail at runtime in Node. These types should use `export =` instead of `export default`.", - "messageHtml": "The types resolved at multiple entrypoints use exportΒ default where the implementation appears to use module.exportsΒ =. Node treats a default import of these constructs from an ES module differently, so these types will make TypeScript under the node16 resolution mode think an extra .default property access is required, but that will likely fail at runtime in Node. These types should use exportΒ = instead of exportΒ default." - } - ] - }, - { - "kind": "UntypedResolution", - "title": "Could not find types", - "messages": [ - { - "messageText": "Imports of multiple entrypoints under all module resolution settings resolved to JavaScript files, but no types.", - "messageHtml": "Imports of multiple entrypoints under all module resolution settings resolved to JavaScript files, but no types." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/react-chartjs-2@5.2.0.tgz.md b/packages/core/test/snapshots/react-chartjs-2@5.2.0.tgz.md index ea77a5a..b8933e4 100644 --- a/packages/core/test/snapshots/react-chartjs-2@5.2.0.tgz.md +++ b/packages/core/test/snapshots/react-chartjs-2@5.2.0.tgz.md @@ -1,32 +1,5 @@ # react-chartjs-2@5.2.0.tgz -## Summary - -```json -[ - { - "kind": "FalseESM", - "title": "Types are ESM, but implementation is CJS", - "messages": [ - { - "messageText": "Imports of the package under the `node16` module resolution setting when the importing module is CJS (its extension is `.cts` or `.cjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that does not contain `\"type\": \"module\"`) resolved to ESM types, but CJS implementations.", - "messageHtml": "Imports of the package under the node16 module resolution setting when the importing module is CJS (its extension is .cts or .cjs, or it has a .ts or .js extension and is in scope of a package.json that does not contain \"type\":Β \"module\") resolved to ESM types, but CJS implementations." - } - ] - }, - { - "kind": "CJSResolvesToESM", - "title": "Entrypoint is ESM-only", - "messages": [ - { - "messageText": "Imports of the package resolved to ES modules from a CJS importing module. CJS modules in Node will only be able to access this entrypoint with a dynamic import.", - "messageHtml": "Imports of the package resolved to ES modules from a CJS importing module. CJS modules in Node will only be able to access this entrypoint with a dynamic import." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/rfdc@1.3.0.tgz.md b/packages/core/test/snapshots/rfdc@1.3.0.tgz.md index 694ee3b..b4abc6a 100644 --- a/packages/core/test/snapshots/rfdc@1.3.0.tgz.md +++ b/packages/core/test/snapshots/rfdc@1.3.0.tgz.md @@ -1,22 +1,5 @@ # rfdc@1.3.0.tgz -## Summary - -```json -[ - { - "kind": "UntypedResolution", - "title": "Could not find types", - "messages": [ - { - "messageText": "Imports of `\"rfdc/default\"` under all module resolution settings resolved to JavaScript files, but no types.", - "messageHtml": "Imports of \"rfdc/default\" under all module resolution settings resolved to JavaScript files, but no types." - } - ] - } -] -``` - ## Problems ```json diff --git a/packages/core/test/snapshots/vue@3.3.4.tgz.md b/packages/core/test/snapshots/vue@3.3.4.tgz.md index 2ba294d..05c8d22 100644 --- a/packages/core/test/snapshots/vue@3.3.4.tgz.md +++ b/packages/core/test/snapshots/vue@3.3.4.tgz.md @@ -1,56 +1,5 @@ # vue@3.3.4.tgz -## Summary - -```json -[ - { - "kind": "FalseCJS", - "title": "Types are CJS, but implementation is ESM", - "messages": [ - { - "messageText": "Imports of multiple entrypoints under the `node16` module resolution setting when the importing module is ESM (its extension is `.mts` or `.mjs`, or it has a `.ts` or `.js` extension and is in scope of a `package.json` that contains `\"type\": \"module\"`) resolved to CJS types, but ESM implementations.", - "messageHtml": "Imports of multiple entrypoints under the node16 module resolution setting when the importing module is ESM (its extension is .mts or .mjs, or it has a .ts or .js extension and is in scope of a package.json that contains \"type\":Β \"module\") resolved to CJS types, but ESM implementations." - } - ] - }, - { - "kind": "NoResolution", - "title": "Resolution failed", - "messages": [ - { - "messageText": "Imports of `\"vue/jsx-dev-runtime\"` under the `node10` module resolution setting failed to resolve.", - "messageHtml": "Imports of \"vue/jsx-dev-runtime\" under the node10 module resolution setting failed to resolve." - } - ] - }, - { - "kind": "UnexpectedESMSyntax", - "title": "Syntax is incompatible with detected module kind", - "messages": [ - { - "messageText": "The implementation resolved at multiple entrypoints uses ESM syntax, but the detected module kind is CJS. This will be an error in Node (and potentially other runtimes and bundlers). The module kind was decided based on the nearest package.json’s lack of a `\"type\": \"module\"` field.", - "messageHtml": "The implementation resolved at multiple entrypoints uses ESM syntax, but the detected module kind is CJS. This will be an error in Node (and potentially other runtimes and bundlers). The module kind was decided based on the nearest package.json’s lack of a \"type\":Β \"module\" field." - }, - { - "messageText": "The implementation resolved at multiple entrypoints uses ESM syntax, but the detected module kind is CJS. This will be an error in Node (and potentially other runtimes and bundlers). The module kind was decided based on the nearest package.json’s lack of a `\"type\": \"module\"` field.", - "messageHtml": "The implementation resolved at multiple entrypoints uses ESM syntax, but the detected module kind is CJS. This will be an error in Node (and potentially other runtimes and bundlers). The module kind was decided based on the nearest package.json’s lack of a \"type\":Β \"module\" field." - } - ] - }, - { - "kind": "Wildcard", - "title": "Wildcards", - "messages": [ - { - "messageText": "Wildcards cannot yet be analyzed by this tool.", - "messageHtml": "Wildcards cannot yet be analyzed by this tool." - } - ] - } -] -``` - ## Problems ```json @@ -70,16 +19,6 @@ "entrypoint": "./jsx-dev-runtime", "resolutionKind": "node16-esm" }, - { - "kind": "UnexpectedESMSyntax", - "entrypoint": "./jsx", - "resolutionKind": "node16-cjs" - }, - { - "kind": "UnexpectedESMSyntax", - "entrypoint": "./jsx", - "resolutionKind": "node16-esm" - }, { "kind": "Wildcard", "entrypoint": "./dist/*", @@ -101,34 +40,15 @@ "resolutionKind": "bundler" }, { - "kind": "UnexpectedESMSyntax", - "entrypoint": "./macros", - "resolutionKind": "node16-cjs" - }, - { - "kind": "UnexpectedESMSyntax", - "entrypoint": "./macros", - "resolutionKind": "node16-esm" - }, - { - "kind": "UnexpectedESMSyntax", - "entrypoint": "./macros-global", - "resolutionKind": "node16-cjs" - }, - { - "kind": "UnexpectedESMSyntax", - "entrypoint": "./macros-global", - "resolutionKind": "node16-esm" - }, - { - "kind": "UnexpectedESMSyntax", - "entrypoint": "./ref-macros", - "resolutionKind": "node16-cjs" - }, - { - "kind": "UnexpectedESMSyntax", - "entrypoint": "./ref-macros", - "resolutionKind": "node16-esm" + "kind": "InternalResolutionError", + "resolutionOption": "node16", + "fileName": "/node_modules/vue/dist/vue.d.mts", + "error": { + "moduleSpecifier": "../jsx", + "pos": 454, + "end": 463, + "resolutionMode": 99 + } } ] ``` \ No newline at end of file diff --git a/packages/web/package.json b/packages/web/package.json index 5b72fdd..673d2bc 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -17,9 +17,11 @@ "dependencies": { "@arethetypeswrong/core": "file:../core", "immer": "^9.0.21", + "marked": "^5.1.0", "nprogress": "^0.2.0" }, "devDependencies": { + "@types/marked": "^5.0.0", "@types/nprogress": "^0.2.0", "esbuild": "^0.17.4", "vite": "^4.0.4" diff --git a/packages/web/src/main.css b/packages/web/src/main.css index 7df6bf5..5797a89 100644 --- a/packages/web/src/main.css +++ b/packages/web/src/main.css @@ -116,6 +116,9 @@ dt, dd { padding: 0.5em 0; } +dd > p { + margin: 0; +} #resolutions { margin-bottom: 1rem; font-size: small; diff --git a/packages/web/src/main.ts b/packages/web/src/main.ts index f87536d..50a8ef9 100644 --- a/packages/web/src/main.ts +++ b/packages/web/src/main.ts @@ -8,7 +8,7 @@ import { parsePackageSpec, type ParsedPackageSpec } from "@arethetypeswrong/core const worker = new Worker(new URL("../worker/worker.ts", import.meta.url), { type: "module" }); worker.onmessage = async (event: MessageEvent) => { updateState((state) => { - state.checks = event.data.data; + state.analysis = event.data.data.result; state.isLoading = false; state.message = undefined; }); @@ -81,7 +81,7 @@ function onPackageNameInput(value: string) { updateState((state) => { state.packageInfo.info = undefined; state.packageInfo.parsed = undefined; - state.checks = undefined; + state.analysis = undefined; state.message = { isError: true, text: parsed.error, @@ -92,7 +92,7 @@ function onPackageNameInput(value: string) { if (!shallowEqual(getState().packageInfo.parsed, parsed.data)) { updateState((state) => { state.packageInfo.parsed = parsed.data; - state.checks = undefined; + state.analysis = undefined; }); } } diff --git a/packages/web/src/renderer.ts b/packages/web/src/renderer.ts index 74e900e..aa122b8 100644 --- a/packages/web/src/renderer.ts +++ b/packages/web/src/renderer.ts @@ -53,13 +53,10 @@ export function subscribeRenderer(events: Events) { function render() { const state = getState(); updateView(messageElement, Message, { isError: state.message?.isError, text: state.message?.text || "" }); - updateView(problemsElement, ProblemList, { - problems: state.checks?.problemSummaries, - containsTypes: state.checks?.analysis.containsTypes, - }); - updateView(resolutionsElement, ChecksTable, { checks: state.checks }); + updateView(problemsElement, ProblemList, { analysis: state.analysis }); + updateView(resolutionsElement, ChecksTable, { analysis: state.analysis }); updateView(checkButton, CheckButton, { disabled: !state.packageInfo.parsed }); - updateView(detailsElement, Details, { analysis: state.checks?.analysis }); + updateView(detailsElement, Details, { analysis: state.analysis }); } }); } diff --git a/packages/web/src/state.ts b/packages/web/src/state.ts index f05a064..8dc9d93 100644 --- a/packages/web/src/state.ts +++ b/packages/web/src/state.ts @@ -1,12 +1,6 @@ -import type { Analysis, ProblemSummary, Problem, ParsedPackageSpec } from "@arethetypeswrong/core"; +import type { CheckResult, ParsedPackageSpec } from "@arethetypeswrong/core"; import { produce } from "immer"; -export interface Checks { - analysis: Analysis; - problemSummaries?: ProblemSummary[]; - problems?: Problem[]; -} - export interface State { isLoading: boolean; message?: { @@ -14,7 +8,7 @@ export interface State { text: string; }; packageInfo: PackageInfoState; - checks?: Checks; + analysis?: CheckResult; } export interface PackageInfoState { diff --git a/packages/web/src/views/ChecksTable.ts b/packages/web/src/views/ChecksTable.ts index 045bd9c..9b63011 100644 --- a/packages/web/src/views/ChecksTable.ts +++ b/packages/web/src/views/ChecksTable.ts @@ -1,21 +1,6 @@ -import type { ProblemKind, ResolutionKind } from "@arethetypeswrong/core"; -import { allResolutionKinds } from "@arethetypeswrong/core/utils"; -import type { Checks } from "../state"; -import { problemEmoji } from "./problemEmoji"; - -const problemShortDescriptions: Record = { - Wildcard: `${problemEmoji.Wildcard} Unable to check`, - NoResolution: `${problemEmoji.NoResolution} Failed to resolve`, - UntypedResolution: `${problemEmoji.UntypedResolution} No types`, - FalseCJS: `${problemEmoji.FalseCJS} Masquerading as CJS`, - FalseESM: `${problemEmoji.FalseESM} Masquerading as ESM`, - CJSResolvesToESM: `${problemEmoji.CJSResolvesToESM} ESM (dynamic import only)`, - FallbackCondition: `${problemEmoji.FallbackCondition} Used fallback condition`, - CJSOnlyExportsDefault: `${problemEmoji.CJSOnlyExportsDefault} CJS default export`, - FalseExportDefault: `${problemEmoji.FalseExportDefault} Incorrect default export`, - UnexpectedESMSyntax: `${problemEmoji.UnexpectedESMSyntax} Unexpected ESM syntax`, - UnexpectedCJSSyntax: `${problemEmoji.UnexpectedCJSSyntax} Unexpected CJS syntax`, -}; +import type { CheckResult, ProblemKind, ResolutionKind } from "@arethetypeswrong/core"; +import { filterProblems, problemKindInfo } from "@arethetypeswrong/core/problems"; +import { allResolutionKinds, groupProblemsByKind } from "@arethetypeswrong/core/utils"; const resolutionKinds: Record = { node10: "node10", @@ -30,16 +15,16 @@ const moduleKinds = { "": "", }; -export function ChecksTable(props: { checks?: Checks }) { - if (!props.checks || !props.checks.analysis.containsTypes) { +export function ChecksTable(props: { analysis?: CheckResult }) { + if (!props.analysis || !props.analysis.types) { return { className: "display-none", innerHTML: "", }; } - const { analysis, problems } = props.checks; - const subpaths = Object.keys(analysis.entrypointResolutions); + const { analysis } = props; + const subpaths = Object.keys(analysis.entrypoints); const entrypoints = subpaths.map((s) => s === "." ? analysis.packageName : `${analysis.packageName}/${s.substring(2)}` ); @@ -60,16 +45,24 @@ export function ChecksTable(props: { checks?: Checks }) { ${resolutionKinds[resolutionKind]} ${subpaths .map((subpath) => { - const problemsForCell = problems?.filter( - (problem) => problem.entrypoint === subpath && problem.resolutionKind === resolutionKind + const resolutionInfo = analysis.entrypoints[subpath].resolutions[resolutionKind]; + const problemsForCell = Object.entries( + groupProblemsByKind(filterProblems(analysis, { resolutionKind, entrypoint: subpath })) ); - const resolution = analysis.entrypointResolutions[subpath][resolutionKind].resolution; return `${ - problemsForCell?.length - ? problemsForCell.map((problem) => problemShortDescriptions[problem.kind]).join("
") - : resolution?.isJson + problemsForCell.length + ? problemsForCell + .map( + ([kind, problem]) => + problemKindInfo[kind as ProblemKind].emoji + + " " + + problemKindInfo[kind as ProblemKind].shortDescription + + (problem.length > 1 ? ` (${problem.length})` : "") + ) + .join("
") + : resolutionInfo.resolution?.isJson ? "βœ… (JSON)" - : "βœ… " + moduleKinds[resolution?.moduleKind?.detectedKind || ""] + : "βœ… " + moduleKinds[resolutionInfo.resolution?.moduleKind?.detectedKind || ""] }`; }) .join("")} diff --git a/packages/web/src/views/Details.ts b/packages/web/src/views/Details.ts index 7ee5a74..54d4085 100644 --- a/packages/web/src/views/Details.ts +++ b/packages/web/src/views/Details.ts @@ -1,6 +1,6 @@ -import type { Analysis } from "@arethetypeswrong/core"; +import type { CheckResult } from "@arethetypeswrong/core"; -export function Details(props: { analysis?: Analysis }) { +export function Details(props: { analysis?: CheckResult }) { if (!props.analysis) { return { className: "display-none", diff --git a/packages/web/src/views/ProblemList.ts b/packages/web/src/views/ProblemList.ts index f4cdbfa..58c42d6 100644 --- a/packages/web/src/views/ProblemList.ts +++ b/packages/web/src/views/ProblemList.ts @@ -1,34 +1,38 @@ -import type { ProblemSummary } from "@arethetypeswrong/core"; -import { problemEmoji } from "./problemEmoji"; +import { marked } from "marked"; +import type { CheckResult, ProblemKind } from "@arethetypeswrong/core"; +import { problemKindInfo } from "@arethetypeswrong/core/problems"; +import { groupProblemsByKind } from "@arethetypeswrong/core/utils"; -export function ProblemList(props: { problems?: ProblemSummary[]; containsTypes: boolean | undefined }) { - if (props.containsTypes === false) { +export function ProblemList(props: { analysis?: CheckResult }) { + if (!props.analysis) { return { - innerHTML: "This package does not contain types.", + innerHTML: "", }; } - if (!props.problems) { + if (!props.analysis.types) { return { - innerHTML: "", + innerHTML: "This package does not contain types.", }; } - if (props.problems.length === 0) { + if (!props.analysis.problems.length) { return { innerHTML: "No problems found 🌟", }; } + const problems = groupProblemsByKind(props.analysis.problems); return { - innerHTML: `
${props.problems.map(problem).join("")}
`, + innerHTML: `
+ ${Object.entries(problems) + .map(([kind]) => { + return ` +
${problemKindInfo[kind as ProblemKind].emoji}
+
${marked.parse(problemKindInfo[kind as ProblemKind].description)}
+ `; + }) + .join("")} +
`, }; } - -function problem(p: ProblemSummary) { - return p.messages - .map((message) => { - return `
${problemEmoji[p.kind]}
${message.messageHtml}
`; - }) - .join(""); -} diff --git a/packages/web/src/views/problemEmoji.ts b/packages/web/src/views/problemEmoji.ts deleted file mode 100644 index fbbf21e..0000000 --- a/packages/web/src/views/problemEmoji.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { ProblemKind } from "@arethetypeswrong/core"; - -export const problemEmoji: Record = { - Wildcard: "❓", - NoResolution: "πŸ’€", - UntypedResolution: "❌", - FalseCJS: "🎭", - FalseESM: "πŸ‘Ί", - CJSResolvesToESM: "⚠️", - FallbackCondition: "πŸ›", - CJSOnlyExportsDefault: "🀨", - FalseExportDefault: "❗️", - UnexpectedESMSyntax: "🚭", - UnexpectedCJSSyntax: "🚱", -}; diff --git a/packages/web/worker/worker.ts b/packages/web/worker/worker.ts index f364a13..1005979 100644 --- a/packages/web/worker/worker.ts +++ b/packages/web/worker/worker.ts @@ -1,12 +1,4 @@ -import { - checkPackage, - checkTgz, - getProblems, - summarizeProblems, - type Analysis, - type Problem, - type ProblemSummary, -} from "@arethetypeswrong/core"; +import { checkPackage, checkTgz, type CheckResult } from "@arethetypeswrong/core"; export interface CheckPackageEventData { kind: "check-package"; @@ -22,25 +14,19 @@ export interface CheckFileEventData { export interface ResultMessage { kind: "result"; data: { - analysis: Analysis; - problemSummaries?: ProblemSummary[]; - problems?: Problem[]; + result: CheckResult; }; } onmessage = async (event: MessageEvent) => { - const analysis = + const result = event.data.kind === "check-file" ? await checkTgz(event.data.file) : await checkPackage(event.data.packageName, event.data.version); - const problems = analysis.containsTypes ? getProblems(analysis) : undefined; - const problemSummaries = problems && analysis.containsTypes ? summarizeProblems(problems, analysis) : undefined; postMessage({ kind: "result", data: { - analysis, - problemSummaries, - problems, + result, }, } satisfies ResultMessage); };