From 5acb25b3e1e8cd6d5fa85fdb76baea5a34a1131b Mon Sep 17 00:00:00 2001 From: Daniel Tschinder <231804+danez@users.noreply.github.com> Date: Fri, 3 Feb 2023 14:59:59 +0100 Subject: [PATCH] fix: migrate framework-info to TS and vitest and enable more strictness (#4819) * fix: version is not part of read-pkg-up result * fix: migrate context to TS and ensure we do not access version on undefined * fix: migrate framework-info to TS and vitest and enable more strictness * chore: fix tests * chore: fix order of build commands * chore: move fixture * chore: fix build * chore: move to prebuild --- package-lock.json | 1301 ++++++++++++++--- .../build/src/log/messages/compatibility.ts | 8 +- packages/build/src/plugins/options.ts | 2 +- packages/cache-utils/src/fs.ts | 5 +- packages/config/src/path.ts | 4 +- packages/framework-info/.gitignore | 8 +- packages/framework-info/package.json | 23 +- .../framework-info/scripts/transform_json.js | 20 +- packages/framework-info/src/context.js | 34 - packages/framework-info/src/context.ts | 42 + .../framework-info/src/{core.js => core.ts} | 107 +- .../src/{detect.js => detect.ts} | 24 +- .../framework-info/src/{dev.js => dev.ts} | 30 +- .../src/frameworks/{main.js => main.ts} | 5 +- packages/framework-info/src/main.js | 138 -- packages/framework-info/src/main.ts | 92 ++ .../src/{package.js => package.ts} | 15 +- .../src/{plugins.js => plugins.ts} | 8 +- .../src/{run_script.js => run_script.ts} | 10 +- packages/framework-info/src/types.ts | 60 + packages/framework-info/test/dev.js | 59 - packages/framework-info/test/main.js | 69 - packages/framework-info/test/options.js | 29 - packages/framework-info/test/run_script.js | 9 - .../framework-info/test/snapshots/main.js.md | 299 ---- .../test/snapshots/main.js.snap | Bin 2320 -> 0 bytes .../tests/__snapshots__/main.test.ts.snap | 283 ++++ .../{test/detect.js => tests/detect.test.ts} | 38 +- packages/framework-info/tests/dev.test.ts | 51 + .../fixtures/colon_scripts/package.json | 0 .../fixtures/config_files/config.rb | 0 .../fixtures/config_files/package.json | 0 .../fixtures/dependencies/package.json | 0 .../fixtures/dev_command_scripts/package.json | 0 .../fixtures/dev_dependencies/package.json | 0 .../{test => tests}/fixtures/empty/.gitkeep | 0 .../fixtures/empty/package.json | 0 .../fixtures/empty_dependencies/config.rb | 0 .../fixtures/empty_dependencies/package.json | 0 .../fixtures/empty_scripts/package.json | 0 .../excluded_dependencies/package.json | 0 .../fixtures/excluded_script/package.json | 0 .../invalid_dependencies/package.json | 0 .../fixtures/invalid_package/package.json | 0 .../fixtures/invalid_scripts/package.json | 0 .../fixtures/monorepos/app1/package.json | 0 .../fixtures/monorepos/app2/package.json | 0 .../monorepos/node_modules/next/package.json | 0 .../@vue/cli-service/package.json | 0 .../node_modules/vuepress/package.json | 0 .../fixtures/multiple/package.json | 0 .../fixtures/next-plugin/package.json | 0 .../fixtures/no-version/package.json | 0 .../fixtures/no_package/config.rb | 0 .../{test => tests}/fixtures/package.json | 0 .../fixtures/parent_package/package.json | 0 .../scripts-order/build-first/package.json | 0 .../command-substring/package.json | 0 .../scripts-order/dev-first/package.json | 0 .../scripts-order/postfix-format/package.json | 0 .../scripts-order/vite-framework/package.json | 0 .../several_dependencies/package.json | 0 .../simple/node_modules/sapper/package.json | 0 .../fixtures/simple/package.json | 0 .../fixtures/syntax_package/package.json | 0 .../fixtures/use_scripts/package.json | 0 .../fixtures/yarn_scripts/package.json | 0 .../fixtures/yarn_scripts/yarn.lock | 0 .../frameworks.test.ts} | 36 +- .../helpers/main.js => tests/helpers/main.ts} | 0 packages/framework-info/tests/main.test.ts | 74 + packages/framework-info/tests/options.test.ts | 21 + .../package.js => tests/package.test.ts} | 30 +- .../framework-info/tests/run_script.test.ts | 9 + packages/framework-info/tsconfig.json | 12 +- packages/framework-info/vite.config.js | 5 +- packages/functions-utils/src/main.ts | 2 +- packages/nock-udp/src/main.ts | 2 +- tsconfig.base.json | 6 +- 79 files changed, 1924 insertions(+), 1046 deletions(-) delete mode 100644 packages/framework-info/src/context.js create mode 100644 packages/framework-info/src/context.ts rename packages/framework-info/src/{core.js => core.ts} (51%) rename packages/framework-info/src/{detect.js => detect.ts} (61%) rename packages/framework-info/src/{dev.js => dev.ts} (67%) rename packages/framework-info/src/frameworks/{main.js => main.ts} (92%) delete mode 100644 packages/framework-info/src/main.js create mode 100644 packages/framework-info/src/main.ts rename packages/framework-info/src/{package.js => package.ts} (61%) rename packages/framework-info/src/{plugins.js => plugins.ts} (52%) rename packages/framework-info/src/{run_script.js => run_script.ts} (55%) create mode 100644 packages/framework-info/src/types.ts delete mode 100644 packages/framework-info/test/dev.js delete mode 100644 packages/framework-info/test/main.js delete mode 100644 packages/framework-info/test/options.js delete mode 100644 packages/framework-info/test/run_script.js delete mode 100644 packages/framework-info/test/snapshots/main.js.md delete mode 100644 packages/framework-info/test/snapshots/main.js.snap create mode 100644 packages/framework-info/tests/__snapshots__/main.test.ts.snap rename packages/framework-info/{test/detect.js => tests/detect.test.ts} (54%) create mode 100644 packages/framework-info/tests/dev.test.ts rename packages/framework-info/{test => tests}/fixtures/colon_scripts/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/config_files/config.rb (100%) rename packages/framework-info/{test => tests}/fixtures/config_files/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/dependencies/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/dev_command_scripts/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/dev_dependencies/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/empty/.gitkeep (100%) rename packages/framework-info/{test => tests}/fixtures/empty/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/empty_dependencies/config.rb (100%) rename packages/framework-info/{test => tests}/fixtures/empty_dependencies/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/empty_scripts/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/excluded_dependencies/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/excluded_script/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/invalid_dependencies/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/invalid_package/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/invalid_scripts/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/monorepos/app1/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/monorepos/app2/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/monorepos/node_modules/next/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/multiple/node_modules/@vue/cli-service/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/multiple/node_modules/vuepress/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/multiple/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/next-plugin/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/no-version/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/no_package/config.rb (100%) rename packages/framework-info/{test => tests}/fixtures/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/parent_package/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/scripts-order/build-first/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/scripts-order/command-substring/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/scripts-order/dev-first/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/scripts-order/postfix-format/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/scripts-order/vite-framework/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/several_dependencies/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/simple/node_modules/sapper/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/simple/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/syntax_package/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/use_scripts/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/yarn_scripts/package.json (100%) rename packages/framework-info/{test => tests}/fixtures/yarn_scripts/yarn.lock (100%) rename packages/framework-info/{test/frameworks.js => tests/frameworks.test.ts} (76%) rename packages/framework-info/{test/helpers/main.js => tests/helpers/main.ts} (100%) create mode 100644 packages/framework-info/tests/main.test.ts create mode 100644 packages/framework-info/tests/options.test.ts rename packages/framework-info/{test/package.js => tests/package.test.ts} (57%) create mode 100644 packages/framework-info/tests/run_script.test.ts diff --git a/package-lock.json b/package-lock.json index 5ab34cb20a..e8c63f14ea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1266,6 +1266,150 @@ "node": ">=12" } }, + "node_modules/@esbuild/android-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", + "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", + "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", + "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", + "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", + "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", + "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", + "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", + "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", + "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/linux-loong64": { "version": "0.15.10", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.10.tgz", @@ -1282,6 +1426,182 @@ "node": ">=12" } }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", + "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", + "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", + "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", + "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", + "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", + "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", + "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", + "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", + "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", + "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", + "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", @@ -1421,18 +1741,6 @@ "node": ">=8" } }, - "node_modules/@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", - "dev": true, - "dependencies": { - "@sinclair/typebox": "^0.24.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, "node_modules/@jest/types": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", @@ -8418,12 +8726,6 @@ "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", "dev": true }, - "node_modules/@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", - "dev": true - }, "node_modules/@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -8561,9 +8863,9 @@ } }, "node_modules/@types/chai": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", - "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, "node_modules/@types/chai-subset": { @@ -9521,9 +9823,9 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "bin": { "acorn": "bin/acorn" }, @@ -9618,9 +9920,9 @@ } }, "node_modules/ajv": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", - "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -10378,15 +10680,6 @@ "node": ">=8" } }, - "node_modules/big-cartesian": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/big-cartesian/-/big-cartesian-3.0.1.tgz", - "integrity": "sha512-bhbA8tAIg5D8Nz8DWnB9dlO9OwYTkDS9UBOrV/z3YHs442e10SMWjgW1tPUCGu0IPSBHyKT/VwUuvE1NKQq2Rw==", - "dev": true, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -10900,6 +11193,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/cacache": { "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", @@ -11135,14 +11437,14 @@ } }, "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", @@ -13308,15 +13610,15 @@ "dev": true }, "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "dependencies": { "type-detect": "^4.0.0" }, "engines": { - "node": ">=0.12" + "node": ">=6" } }, "node_modules/deep-extend": { @@ -15920,6 +16222,7 @@ "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -18404,6 +18707,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, "dependencies": { "universalify": "^2.0.0" }, @@ -20284,6 +20588,24 @@ "node": ">=10" } }, + "node_modules/mlly": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.1.0.tgz", + "integrity": "sha512-cwzBrBfwGC1gYJyfcy8TcZU1f+dbH/T+TuOhtYP2wLv/Fb51/uV7HJQfBPtEupZ2ORLRU1EKFS/QfS3eo9+kBQ==", + "dev": true, + "dependencies": { + "acorn": "^8.8.1", + "pathe": "^1.0.0", + "pkg-types": "^1.0.1", + "ufo": "^1.0.1" + } + }, + "node_modules/mlly/node_modules/pathe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.0.0.tgz", + "integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==", + "dev": true + }, "node_modules/modify-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", @@ -22799,6 +23121,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pathe": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-0.2.0.tgz", + "integrity": "sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==", + "dev": true + }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -22874,6 +23202,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pkg-types": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.1.tgz", + "integrity": "sha512-jHv9HB+Ho7dj6ItwppRDDl0iZRYBD0jsakHXtFgoLr+cHSF6xC+QL54sJmWxyGxOLYSHm0afhXhXcQDQqH9z8g==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.0.0", + "pathe": "^1.0.0" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.0.0.tgz", + "integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==", + "dev": true + }, "node_modules/plur": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", @@ -22898,9 +23243,9 @@ } }, "node_modules/postcss": { - "version": "8.4.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz", - "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==", + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", "funding": [ { "type": "opencollective", @@ -24353,6 +24698,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -24709,7 +25060,6 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -24720,7 +25070,6 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -24845,6 +25194,12 @@ "node": ">=8" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -25405,62 +25760,6 @@ "dev": true, "peer": true }, - "node_modules/test-each": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/test-each/-/test-each-4.0.0.tgz", - "integrity": "sha512-R0M4rFth/0xKHx4tMTLN+D49NVzvZaGto4fXIaEo9sgZwb4FHmuMpsa5+mo3MRQdQAUUUnhwAON/HSugfulq+A==", - "dev": true, - "dependencies": { - "big-cartesian": "^3.0.1", - "is-plain-obj": "^4.0.0", - "pretty-format": "^28.0.0-alpha.3" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/test-each/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-each/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/test-each/node_modules/pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "dependencies": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" - } - }, - "node_modules/test-each/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -25527,9 +25826,9 @@ } }, "node_modules/tinybench": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.0.tgz", - "integrity": "sha512-zs1gMVBwyyG2QbVchYIbnabRhMOCGvrwZz/q+SV+LIMa9q5YDQZi2kkI6ZRqV2Bz7ba1uvrc7ieUoE4KWnGeKg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", "dev": true }, "node_modules/tinypool": { @@ -26061,6 +26360,12 @@ "node": ">=4.2.0" } }, + "node_modules/ufo": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz", + "integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==", + "dev": true + }, "node_modules/uglify-js": { "version": "3.17.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.3.tgz", @@ -26165,6 +26470,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, "engines": { "node": ">= 10.0.0" } @@ -26559,6 +26865,40 @@ } } }, + "node_modules/vite-node": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.27.1.tgz", + "integrity": "sha512-d6+ue/3NzsfndWaPbYh/bFkHbmAWfDXI4B874zRx+WREnG6CUHUbBC8lKaRYZjeR6gCPN5m1aVNNRXBYICA9XA==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.1.0", + "pathe": "^0.2.0", + "picocolors": "^1.0.0", + "source-map": "^0.6.1", + "source-map-support": "^0.5.21", + "vite": "^3.0.0 || ^4.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": ">=v14.16.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/vite-node/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/vite/node_modules/resolve": { "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", @@ -26867,6 +27207,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -27958,10 +28314,9 @@ "version": "9.7.2", "license": "MIT", "dependencies": { - "ajv": "^8.0.0", + "ajv": "^8.12.0", "filter-obj": "^3.0.0", "find-up": "^6.3.0", - "fs-extra": "^10.1.0", "is-plain-obj": "^4.0.0", "locate-path": "^7.0.0", "p-filter": "^3.0.0", @@ -27972,24 +28327,55 @@ "url": "^0.11.0" }, "devDependencies": { - "ava": "^4.0.0", "babel-loader": "^8.2.2", - "c8": "^7.11.0", "cpy": "^9.0.0", "cpy-cli": "^4.0.0", "del": "^6.0.0", + "fast-glob": "^3.2.12", "npm-run-all": "^4.1.5", "path-browserify": "^1.0.1", "rollup-plugin-node-polyfills": "^0.2.1", - "test-each": "^4.0.0", "tmp-promise": "^3.0.2", "typescript": "^4.9.4", - "vite": "^3.1.6" + "vite": "^4.0.4", + "vitest": "^0.27.1" }, "engines": { "node": "^14.14.0 || >=16.0.0" } }, + "packages/framework-info/node_modules/@esbuild/android-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", + "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "packages/framework-info/node_modules/@esbuild/linux-loong64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, "packages/framework-info/node_modules/aggregate-error": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", @@ -28046,6 +28432,43 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "packages/framework-info/node_modules/esbuild": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" + } + }, "packages/framework-info/node_modules/p-event": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", @@ -28088,6 +28511,39 @@ "node": ">=8" } }, + "packages/framework-info/node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/framework-info/node_modules/rollup": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.10.0.tgz", + "integrity": "sha512-JmRYz44NjC1MjVF2VKxc0M1a97vn+cDxeqWmnwyAF4FvpjK8YFdHpaqvQB+3IxCvX05vJxKZkoMDU8TShhmJVA==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "packages/framework-info/node_modules/semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", @@ -28102,6 +28558,135 @@ "node": ">=10" } }, + "packages/framework-info/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/framework-info/node_modules/strip-literal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.0.tgz", + "integrity": "sha512-5o4LsH1lzBzO9UFH63AJ2ad2/S2AVx6NtjOcaz+VTT2h1RiRvbipW72z8M/lxEhcPHDBQwpDrnTF7sXy/7OwCQ==", + "dev": true, + "dependencies": { + "acorn": "^8.8.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "packages/framework-info/node_modules/vite": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.4.tgz", + "integrity": "sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==", + "dev": true, + "dependencies": { + "esbuild": "^0.16.3", + "postcss": "^8.4.20", + "resolve": "^1.22.1", + "rollup": "^3.7.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "packages/framework-info/node_modules/vitest": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.27.1.tgz", + "integrity": "sha512-1sIpQ1DVFTEn7c1ici1XHcVfdU4nKiBmPtPAtGKJJJLuJjojTv/OHGgcf69P57alM4ty8V4NMv+7Yoi5Cxqx9g==", + "dev": true, + "dependencies": { + "@types/chai": "^4.3.4", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "acorn": "^8.8.1", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.7", + "debug": "^4.3.4", + "local-pkg": "^0.4.2", + "picocolors": "^1.0.0", + "source-map": "^0.6.1", + "strip-literal": "^1.0.0", + "tinybench": "^2.3.1", + "tinypool": "^0.3.0", + "tinyspy": "^1.0.2", + "vite": "^3.0.0 || ^4.0.0", + "vite-node": "0.27.1", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.16.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, "packages/functions-utils": { "name": "@netlify/functions-utils", "version": "5.1.6", @@ -29278,6 +29863,69 @@ "dev": true, "optional": true }, + "@esbuild/android-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", + "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", + "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", + "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", + "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", + "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", + "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", + "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", + "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", + "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", + "dev": true, + "optional": true + }, "@esbuild/linux-loong64": { "version": "0.15.10", "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.10.tgz", @@ -29285,6 +29933,83 @@ "dev": true, "optional": true }, + "@esbuild/linux-mips64el": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", + "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", + "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", + "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", + "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", + "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", + "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", + "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", + "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", + "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", + "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", + "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", + "dev": true, + "optional": true + }, "@eslint/eslintrc": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", @@ -29393,15 +30118,6 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, - "@jest/schemas": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-28.1.3.tgz", - "integrity": "sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==", - "dev": true, - "requires": { - "@sinclair/typebox": "^0.24.1" - } - }, "@jest/types": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", @@ -34299,16 +35015,14 @@ "@netlify/framework-info": { "version": "file:packages/framework-info", "requires": { - "ajv": "^8.0.0", - "ava": "^4.0.0", + "ajv": "^8.12.0", "babel-loader": "^8.2.2", - "c8": "^7.11.0", "cpy": "^9.0.0", "cpy-cli": "^4.0.0", "del": "^6.0.0", + "fast-glob": "^3.2.12", "filter-obj": "^3.0.0", "find-up": "^6.3.0", - "fs-extra": "^10.1.0", "is-plain-obj": "^4.0.0", "locate-path": "^7.0.0", "npm-run-all": "^4.1.5", @@ -34319,13 +35033,27 @@ "read-pkg-up": "^9.0.0", "rollup-plugin-node-polyfills": "^0.2.1", "semver": "^7.3.4", - "test-each": "^4.0.0", "tmp-promise": "^3.0.2", "typescript": "^4.9.4", "url": "^0.11.0", - "vite": "^3.1.6" + "vite": "^4.0.4", + "vitest": "^0.27.1" }, "dependencies": { + "@esbuild/android-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", + "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "dev": true, + "optional": true + }, "aggregate-error": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", @@ -34364,6 +35092,36 @@ "p-map": "^5.3.0" } }, + "esbuild": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" + } + }, "p-event": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", @@ -34391,6 +35149,26 @@ "p-finally": "^1.0.0" } }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "rollup": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.10.0.tgz", + "integrity": "sha512-JmRYz44NjC1MjVF2VKxc0M1a97vn+cDxeqWmnwyAF4FvpjK8YFdHpaqvQB+3IxCvX05vJxKZkoMDU8TShhmJVA==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, "semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", @@ -34398,6 +35176,60 @@ "requires": { "lru-cache": "^6.0.0" } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "strip-literal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.0.tgz", + "integrity": "sha512-5o4LsH1lzBzO9UFH63AJ2ad2/S2AVx6NtjOcaz+VTT2h1RiRvbipW72z8M/lxEhcPHDBQwpDrnTF7sXy/7OwCQ==", + "dev": true, + "requires": { + "acorn": "^8.8.1" + } + }, + "vite": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.4.tgz", + "integrity": "sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==", + "dev": true, + "requires": { + "esbuild": "^0.16.3", + "fsevents": "~2.3.2", + "postcss": "^8.4.20", + "resolve": "^1.22.1", + "rollup": "^3.7.0" + } + }, + "vitest": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.27.1.tgz", + "integrity": "sha512-1sIpQ1DVFTEn7c1ici1XHcVfdU4nKiBmPtPAtGKJJJLuJjojTv/OHGgcf69P57alM4ty8V4NMv+7Yoi5Cxqx9g==", + "dev": true, + "requires": { + "@types/chai": "^4.3.4", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "acorn": "^8.8.1", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.7", + "debug": "^4.3.4", + "local-pkg": "^0.4.2", + "picocolors": "^1.0.0", + "source-map": "^0.6.1", + "strip-literal": "^1.0.0", + "tinybench": "^2.3.1", + "tinypool": "^0.3.0", + "tinyspy": "^1.0.2", + "vite": "^3.0.0 || ^4.0.0", + "vite-node": "0.27.1", + "why-is-node-running": "^2.2.2" + } } } }, @@ -35243,12 +36075,6 @@ "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", "dev": true }, - "@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", - "dev": true - }, "@sindresorhus/is": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", @@ -35362,9 +36188,9 @@ } }, "@types/chai": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", - "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, "@types/chai-subset": { @@ -36100,9 +36926,9 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, "acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==" + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" }, "acorn-import-assertions": { "version": "1.8.0", @@ -36171,9 +36997,9 @@ } }, "ajv": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.2.tgz", - "integrity": "sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -36736,12 +37562,6 @@ } } }, - "big-cartesian": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/big-cartesian/-/big-cartesian-3.0.1.tgz", - "integrity": "sha512-bhbA8tAIg5D8Nz8DWnB9dlO9OwYTkDS9UBOrV/z3YHs442e10SMWjgW1tPUCGu0IPSBHyKT/VwUuvE1NKQq2Rw==", - "dev": true - }, "big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -37101,6 +37921,12 @@ } } }, + "cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true + }, "cacache": { "version": "16.1.3", "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", @@ -37269,14 +38095,14 @@ } }, "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", @@ -38904,9 +39730,9 @@ "dev": true }, "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "requires": { "type-detect": "^4.0.0" @@ -40764,6 +41590,7 @@ "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -42582,6 +43409,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, "requires": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" @@ -44026,6 +44854,26 @@ "mkdirp": "^1.0.3" } }, + "mlly": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.1.0.tgz", + "integrity": "sha512-cwzBrBfwGC1gYJyfcy8TcZU1f+dbH/T+TuOhtYP2wLv/Fb51/uV7HJQfBPtEupZ2ORLRU1EKFS/QfS3eo9+kBQ==", + "dev": true, + "requires": { + "acorn": "^8.8.1", + "pathe": "^1.0.0", + "pkg-types": "^1.0.1", + "ufo": "^1.0.1" + }, + "dependencies": { + "pathe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.0.0.tgz", + "integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==", + "dev": true + } + } + }, "modify-values": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", @@ -45948,6 +46796,12 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==" }, + "pathe": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-0.2.0.tgz", + "integrity": "sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==", + "dev": true + }, "pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -45993,6 +46847,25 @@ "find-up": "^6.1.0" } }, + "pkg-types": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.1.tgz", + "integrity": "sha512-jHv9HB+Ho7dj6ItwppRDDl0iZRYBD0jsakHXtFgoLr+cHSF6xC+QL54sJmWxyGxOLYSHm0afhXhXcQDQqH9z8g==", + "dev": true, + "requires": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.0.0", + "pathe": "^1.0.0" + }, + "dependencies": { + "pathe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.0.0.tgz", + "integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==", + "dev": true + } + } + }, "plur": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", @@ -46008,9 +46881,9 @@ "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=" }, "postcss": { - "version": "8.4.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz", - "integrity": "sha512-UNxNOLQydcOFi41yHNMcKRZ39NeXlr8AxGuZJsdub8vIb12fHzcq37DTU/QtbI6WLxNg2gF9Z+8qtRwTj1UI1Q==", + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", "requires": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -47078,6 +47951,12 @@ "object-inspect": "^1.9.0" } }, + "siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -47354,7 +48233,6 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "peer": true, "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -47364,8 +48242,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "peer": true + "dev": true } } }, @@ -47474,6 +48351,12 @@ } } }, + "stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, "stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -47878,49 +48761,6 @@ } } }, - "test-each": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/test-each/-/test-each-4.0.0.tgz", - "integrity": "sha512-R0M4rFth/0xKHx4tMTLN+D49NVzvZaGto4fXIaEo9sgZwb4FHmuMpsa5+mo3MRQdQAUUUnhwAON/HSugfulq+A==", - "dev": true, - "requires": { - "big-cartesian": "^3.0.1", - "is-plain-obj": "^4.0.0", - "pretty-format": "^28.0.0-alpha.3" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "pretty-format": { - "version": "28.1.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.3.tgz", - "integrity": "sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==", - "dev": true, - "requires": { - "@jest/schemas": "^28.1.3", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - } - }, - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", - "dev": true - } - } - }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -47977,9 +48817,9 @@ "dev": true }, "tinybench": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.0.tgz", - "integrity": "sha512-zs1gMVBwyyG2QbVchYIbnabRhMOCGvrwZz/q+SV+LIMa9q5YDQZi2kkI6ZRqV2Bz7ba1uvrc7ieUoE4KWnGeKg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", "dev": true }, "tinypool": { @@ -48384,6 +49224,12 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" }, + "ufo": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz", + "integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==", + "dev": true + }, "uglify-js": { "version": "3.17.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.3.tgz", @@ -48465,7 +49311,8 @@ "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true }, "unix-dgram": { "version": "2.0.6", @@ -48758,6 +49605,30 @@ } } }, + "vite-node": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.27.1.tgz", + "integrity": "sha512-d6+ue/3NzsfndWaPbYh/bFkHbmAWfDXI4B874zRx+WREnG6CUHUbBC8lKaRYZjeR6gCPN5m1aVNNRXBYICA9XA==", + "dev": true, + "requires": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.1.0", + "pathe": "^0.2.0", + "picocolors": "^1.0.0", + "source-map": "^0.6.1", + "source-map-support": "^0.5.21", + "vite": "^3.0.0 || ^4.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "vitest": { "version": "0.24.3", "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.24.3.tgz", @@ -48965,6 +49836,16 @@ "is-symbol": "^1.0.3" } }, + "why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "requires": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + } + }, "wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", diff --git a/packages/build/src/log/messages/compatibility.ts b/packages/build/src/log/messages/compatibility.ts index df51bd44cc..a4187ba4ef 100644 --- a/packages/build/src/log/messages/compatibility.ts +++ b/packages/build/src/log/messages/compatibility.ts @@ -50,7 +50,7 @@ const getPluginDescription = function ( }, debug, ) { - const versionedPackage = getVersionedPackage(packageName, version) + const versionedPackage = getVersionedPackage(version) const pluginOrigin = getPluginOrigin(loadedFrom, origin) const description = `${THEME.highlightWords(packageName)}${versionedPackage} ${pluginOrigin}` if (!debug) { @@ -106,7 +106,7 @@ const getOutdatedPlugin = function ({ loadedFrom, origin, }) { - const versionedPackage = getVersionedPackage(packageName, version) + const versionedPackage = getVersionedPackage(version) const outdatedDescription = getOutdatedDescription({ latestVersion, migrationGuide, loadedFrom, origin }) return `${THEME.warningHighlightWords(packageName)}${versionedPackage}: ${outdatedDescription}` } @@ -165,7 +165,7 @@ const getIncompatiblePlugin = function ({ compatibleVersion, compatWarning, }) { - const versionedPackage = getVersionedPackage(packageName, version) + const versionedPackage = getVersionedPackage(version) return `${THEME.warningHighlightWords( packageName, )}${versionedPackage}: version ${compatibleVersion} is the most recent version compatible with ${compatWarning}` @@ -173,6 +173,6 @@ const getIncompatiblePlugin = function ({ // Make sure we handle `package.json` with `version` being either `undefined` // or an empty string -const getVersionedPackage = function (packageName, version = '') { +const getVersionedPackage = function (version = '') { return version === '' ? '' : `@${version}` } diff --git a/packages/build/src/plugins/options.ts b/packages/build/src/plugins/options.ts index 2dd07df799..dbf9be857b 100644 --- a/packages/build/src/plugins/options.ts +++ b/packages/build/src/plugins/options.ts @@ -79,7 +79,7 @@ const loadPluginFiles = async function ({ // Core plugins can only be included once. // For example, when testing core plugins, they might be included as local plugins, // in which case they should not be included twice. -const isNotRedundantCorePlugin = function (pluginOptionsA, index, pluginsOptions) { +const isNotRedundantCorePlugin = function (pluginOptionsA, _index, pluginsOptions) { return ( pluginOptionsA.loadedFrom !== 'core' || pluginsOptions.every( diff --git a/packages/cache-utils/src/fs.ts b/packages/cache-utils/src/fs.ts index 6f62bd34a3..c3a92475d1 100644 --- a/packages/cache-utils/src/fs.ts +++ b/packages/cache-utils/src/fs.ts @@ -1,4 +1,4 @@ -import { promises as fs } from 'fs' +import { promises as fs, Stats } from 'fs' import { basename, dirname } from 'path' import cpy from 'cpy' @@ -78,10 +78,11 @@ const getSrcGlob = async function (src: string): Promise { return baseOptions } -const getStat = async (src: string) => { +const getStat = async (src: string): Promise => { try { return await fs.stat(src) } catch { // continue regardless error + return undefined } } diff --git a/packages/config/src/path.ts b/packages/config/src/path.ts index ea79dde1cc..dfaef1b259 100644 --- a/packages/config/src/path.ts +++ b/packages/config/src/path.ts @@ -15,7 +15,7 @@ export const getConfigPath = async function ({ configOpt, cwd, repositoryRoot, c const configPath = await pLocate( [ searchConfigOpt(cwd, configOpt), - searchBaseConfigFile(repositoryRoot, configBase), + searchBaseConfigFile(configBase), searchConfigFile(repositoryRoot), findUp(FILENAME, { cwd }), ], @@ -36,7 +36,7 @@ const searchConfigOpt = function (cwd: string, configOpt?: string) { /** * Look for `repositoryRoot/{base}/netlify.*` */ -const searchBaseConfigFile = function (repositoryRoot, configBase?: string) { +const searchBaseConfigFile = function (configBase?: string) { if (configBase === undefined) { return } diff --git a/packages/framework-info/.gitignore b/packages/framework-info/.gitignore index 88c3b8b2d1..67ed40ad8a 100644 --- a/packages/framework-info/.gitignore +++ b/packages/framework-info/.gitignore @@ -2,13 +2,13 @@ node_modules yarn-error.log .vscode dist -build +src/generated .DS_Store # Local Netlify folder .netlify # These are mock node_modules folder for testing purposes -!test/fixtures/simple/node_modules -!test/fixtures/multiple/node_modules -!test/fixtures/monorepos/node_modules +!tests/fixtures/simple/node_modules +!tests/fixtures/multiple/node_modules +!tests/fixtures/monorepos/node_modules diff --git a/packages/framework-info/package.json b/packages/framework-info/package.json index 08b9c0fd5d..36220c96ca 100644 --- a/packages/framework-info/package.json +++ b/packages/framework-info/package.json @@ -5,24 +5,23 @@ "type": "module", "main": "./dist/index.umd.cjs", "exports": { - "node": "./src/main.js", + "node": "./lib/main.js", "default": "./dist/index.umd.cjs" }, "files": [ - "build/*.js", - "src/**/*.js", + "lib", "dist/index.umd.cjs" ], "scripts": { + "prebuild": "node scripts/transform_json.js", "build": "run-s build:*", "build:ts": "tsc", - "build:json": "node scripts/transform_json.js", "build:browser": "run-s build:browser:*", "build:browser:core": "vite build", "build:browser:site-root": "cpy index.html ./dist", - "test": "npm run test:dev", - "test:dev": "ava", - "test:ci": "c8 -r lcovonly -r text -r json ava" + "test": "vitest run", + "test:dev": "vitest", + "test:ci": "vitest run --reporter=default" }, "keywords": [ "dependency-management", @@ -58,10 +57,9 @@ "url": "https://github.com/netlify/build/issues" }, "dependencies": { - "ajv": "^8.0.0", + "ajv": "^8.12.0", "filter-obj": "^3.0.0", "find-up": "^6.3.0", - "fs-extra": "^10.1.0", "is-plain-obj": "^4.0.0", "locate-path": "^7.0.0", "p-filter": "^3.0.0", @@ -72,19 +70,18 @@ "url": "^0.11.0" }, "devDependencies": { - "ava": "^4.0.0", "babel-loader": "^8.2.2", - "c8": "^7.11.0", "cpy": "^9.0.0", "cpy-cli": "^4.0.0", "del": "^6.0.0", + "fast-glob": "^3.2.12", "npm-run-all": "^4.1.5", "path-browserify": "^1.0.1", "rollup-plugin-node-polyfills": "^0.2.1", - "test-each": "^4.0.0", "tmp-promise": "^3.0.2", "typescript": "^4.9.4", - "vite": "^3.1.6" + "vite": "^4.0.4", + "vitest": "^0.27.1" }, "engines": { "node": "^14.14.0 || >=16.0.0" diff --git a/packages/framework-info/scripts/transform_json.js b/packages/framework-info/scripts/transform_json.js index 063a1ab2b7..869647162a 100644 --- a/packages/framework-info/scripts/transform_json.js +++ b/packages/framework-info/scripts/transform_json.js @@ -1,11 +1,12 @@ import { promises as fs } from 'fs' import process from 'process' +import { fileURLToPath } from 'url' -import { FRAMEWORK_NAMES } from '../src/frameworks/main.js' +import glob from 'fast-glob' const FRAMEWORKS_DIR = new URL('../src/frameworks/', import.meta.url) -const BUILD_DIR = new URL('../build/', import.meta.url) -const FRAMEWORKS_BUILD = new URL('frameworks.js', BUILD_DIR) +const BUILD_DIR = new URL('../src/generated/', import.meta.url) +const FRAMEWORKS_BUILD = new URL('frameworks.ts', BUILD_DIR) // We enforce frameworks to be written with JSON to ensure they remain logicless // which is simpler for contributors and avoid adding unnecessary logic. @@ -14,7 +15,8 @@ const FRAMEWORKS_BUILD = new URL('frameworks.js', BUILD_DIR) // Therefore, we transform JSON to JavaScript files using at build time. const transformFrameworks = async function () { await fs.mkdir(BUILD_DIR, { recursive: true }) - const frameworks = await Promise.all(FRAMEWORK_NAMES.map(transformFramework)) + const frameworkFiles = await glob('*.json', { cwd: fileURLToPath(FRAMEWORKS_DIR), absolute: true }) + const frameworks = await Promise.all(frameworkFiles.map(transformFramework)) const fileContents = `${FRAMEWORKS_HEADER}${JSON.stringify(frameworks, null, 2)}` await fs.writeFile(FRAMEWORKS_BUILD, fileContents) } @@ -31,16 +33,16 @@ const updateLogoUrls = function (contents) { return updatedContents } -const transformFramework = async function (frameworkName) { - const frameworkUrl = new URL(`${frameworkName}.json`, FRAMEWORKS_DIR) - const jsonContents = await fs.readFile(frameworkUrl) +const transformFramework = async function (frameworkFile) { + const jsonContents = await fs.readFile(frameworkFile) const contents = JSON.parse(jsonContents) const updatedContents = updateLogoUrls(contents) return updatedContents } -const FRAMEWORKS_HEADER = `// This file is autogenerated at build time -export const FRAMEWORKS = ` +const FRAMEWORKS_HEADER = `import type { FrameworkDefinition } from "../types.js" +// This file is autogenerated at build time +export const FRAMEWORKS: FrameworkDefinition[] = ` transformFrameworks() diff --git a/packages/framework-info/src/context.js b/packages/framework-info/src/context.js deleted file mode 100644 index cca86dc904..0000000000 --- a/packages/framework-info/src/context.js +++ /dev/null @@ -1,34 +0,0 @@ -import { cwd, version as nodejsVersion } from 'process' - -import isPlainObj from 'is-plain-obj' -import { locatePath } from 'locate-path' -import { readPackageUp } from 'read-pkg-up' - -export const getPackageJson = async (projectDir) => { - try { - const result = await readPackageUp({ cwd: projectDir, normalize: false }) - if (result === undefined) { - return {} - } - - const { version, packageJson, path: packageJsonPath } = result - - if (!isPlainObj(packageJson)) { - return { packageJsonPath } - } - - return { version, packageJson, packageJsonPath } - } catch { - return {} - } -} - -export const getContext = async ({ projectDir = cwd(), nodeVersion = nodejsVersion } = {}) => { - const { packageJson, packageJsonPath = projectDir } = await getPackageJson(projectDir) - return { - pathExists: async (path) => (await locatePath([path], { type: 'file', cwd: projectDir })) !== undefined, - packageJson, - packageJsonPath, - nodeVersion, - } -} diff --git a/packages/framework-info/src/context.ts b/packages/framework-info/src/context.ts new file mode 100644 index 0000000000..1d074b9e81 --- /dev/null +++ b/packages/framework-info/src/context.ts @@ -0,0 +1,42 @@ +import { cwd, version as nodejsVersion } from 'process' + +import { locatePath } from 'locate-path' +import { PackageJson, readPackageUp } from 'read-pkg-up' + +interface PackageJsonInfo { + packageJson?: PackageJson + packageJsonPath?: string +} + +export type PathExists = (path: string) => Promise + +export interface Context extends PackageJsonInfo { + pathExists: PathExists + nodeVersion: string +} + +export const getPackageJson = async (projectDir: string): Promise => { + try { + const result = await readPackageUp({ cwd: projectDir, normalize: false }) + if (result === undefined) { + return {} + } + + const { packageJson, path: packageJsonPath } = result + + return { packageJson, packageJsonPath } + } catch { + return {} + } +} + +export const getContext = async (projectDir: string = cwd(), nodeVersion: string = nodejsVersion): Promise => { + const { packageJson, packageJsonPath = projectDir } = await getPackageJson(projectDir) + + return { + pathExists: async (path) => (await locatePath([path], { type: 'file', cwd: projectDir })) !== undefined, + packageJson, + packageJsonPath, + nodeVersion, + } +} diff --git a/packages/framework-info/src/core.js b/packages/framework-info/src/core.ts similarity index 51% rename from packages/framework-info/src/core.js rename to packages/framework-info/src/core.ts index b9588622c3..70fe55ad0d 100644 --- a/packages/framework-info/src/core.js +++ b/packages/framework-info/src/core.ts @@ -1,71 +1,26 @@ import pFilter from 'p-filter' +import type { PackageJson } from 'read-pkg-up' -import { FRAMEWORKS } from '../build/frameworks.js' - +import type { Context, PathExists } from './context.js' import { usesFramework } from './detect.js' import { getDevCommands } from './dev.js' +import type { FrameworkName } from './frameworks/main.js' +import { FRAMEWORKS } from './generated/frameworks.js' import { getPackageJsonContent } from './package.js' import { getPlugins } from './plugins.js' import { getRunScriptCommand } from './run_script.js' +import type { Framework, FrameworkDefinition } from './types.js' -const getContext = (context) => { +const getContext = (context: Context) => { const { pathExists, packageJson, packageJsonPath = '.', nodeVersion } = context + return { pathExists, packageJson, packageJsonPath, nodeVersion } } -/** - * @typedef {object} PollingStrategy - * @property {'TCP'|'HTTP'} name - Name of the polling strategy. Possible names - TCP,HTTP - */ - -/** - * A callback to check if a path exists - * @callback PathExists - * @param {string} path - * @returns {Promise} - */ - -/** - * @typedef {object} Context - * @property {PathExists} pathExists - Checks if a path exists - * @property {object} packageJson - Content of package.json - * @property {string} [packageJsonPath='.'] - Path of package.json - * @property {nodeVersion} [nodeVersion] - Node.js version of the runtime environment. Used to recommend Netlify build plugins - */ - -/** - * @typedef {object} Dev - * @property {string} commands - Dev command. There might be several alternatives or empty - * @property {number} port - Server port - * @property {PollingStrategy[]} pollingStrategies - Dev Server polling strategies - */ - -/** - * @typedef {object} Build - * @property {string} commands - Build command. There might be several alternatives - * @property {string} directory - Relative path to the directory where files are built - */ - -/** - * @typedef {object} Framework - * @property {string} id - framework id such as `"gatsby"` - * @property {string} name - framework name such as `"Gatsby"` - * @property {string} category - Category among `"static_site_generator"`, `"frontend_framework"` and `"build_tool"` - * @property {Dev} dev - Information about the dev command - * @property {Build} build - Information about the build command - * @property {string} staticAssetsDirectory - Directory where the framework stores static assets. Can be `undefined` - * @property {object} env - Environment variables that should be set when calling the dev command - * @property {string[]} plugins - A list of recommend Netlify build plugins to install for the framework - */ - /** * Return all the frameworks used by a project. - * - * @param {Context} context - Context - * - * @returns {Promise} frameworks - Frameworks used by a project */ -export const listFrameworks = async function (context) { +export const listFrameworks = async function (context: Context): Promise { const { pathExists, packageJson, packageJsonPath, nodeVersion } = getContext(context) const { npmDependencies, scripts, runScriptCommand } = await getProjectInfo({ pathExists, @@ -81,13 +36,8 @@ export const listFrameworks = async function (context) { /** * Return whether a project uses a specific framework - * - * @param {string} frameworkId - Id such as `"gatsby"` - * @param {Context} [context] - Context - * - * @returns {Promise} result - Whether the project uses this framework */ -export const hasFramework = async function (frameworkId, context) { +export const hasFramework = async function (frameworkId: FrameworkName, context: Context): Promise { const framework = getFrameworkById(frameworkId) const { pathExists, packageJson, packageJsonPath } = getContext(context) const { npmDependencies } = await getProjectInfo({ pathExists, packageJson, packageJsonPath }) @@ -97,13 +47,8 @@ export const hasFramework = async function (frameworkId, context) { /** * Return some information about a framework used by a project. - * - * @param {string} frameworkId - Id such as `"gatsby"` - * @param {Context} [context] - Context - * - * @returns {Promise} framework - Framework used by a project */ -export const getFramework = async function (frameworkId, context) { +export const getFramework = async function (frameworkId: FrameworkName, context: Context): Promise { const framework = getFrameworkById(frameworkId) const { pathExists, packageJson, packageJsonPath, nodeVersion } = getContext(context) const { scripts, runScriptCommand } = await getProjectInfo({ @@ -115,7 +60,7 @@ export const getFramework = async function (frameworkId, context) { return frameworkInfo } -const getFrameworkById = function (frameworkId) { +const getFrameworkById = function (frameworkId: FrameworkName): FrameworkDefinition { const framework = FRAMEWORKS.find(({ id }) => id === frameworkId) if (framework === undefined) { const frameworkIds = FRAMEWORKS.map((knownFramework) => getFrameworkId(knownFramework)) @@ -123,17 +68,24 @@ const getFrameworkById = function (frameworkId) { .join(', ') throw new Error(`Invalid framework "${frameworkId}". It should be one of: ${frameworkIds}`) } + return framework } -const getFrameworkId = function ({ id }) { +const getFrameworkId = function ({ id }: FrameworkDefinition): string { return id } -const getProjectInfo = async function ({ pathExists, packageJson, packageJsonPath }) { - const { npmDependencies, scripts } = await getPackageJsonContent({ - packageJson, - }) +const getProjectInfo = async function ({ + pathExists, + packageJson, + packageJsonPath, +}: { + pathExists: PathExists + packageJson: PackageJson | undefined + packageJsonPath: string +}) { + const { npmDependencies, scripts } = getPackageJsonContent(packageJson) const runScriptCommand = await getRunScriptCommand({ pathExists, packageJsonPath }) return { npmDependencies, scripts, runScriptCommand } } @@ -150,11 +102,20 @@ const getFrameworkInfo = function ( env, logo, plugins, + }: FrameworkDefinition, + { + scripts, + runScriptCommand, + nodeVersion, + }: { + scripts: Record + runScriptCommand: string + nodeVersion: string }, - { scripts, runScriptCommand, nodeVersion }, -) { +): Framework { const devCommands = getDevCommands({ frameworkDevCommand, scripts, runScriptCommand }) const recommendedPlugins = getPlugins(plugins, { nodeVersion }) + return { id, name, diff --git a/packages/framework-info/src/detect.js b/packages/framework-info/src/detect.ts similarity index 61% rename from packages/framework-info/src/detect.js rename to packages/framework-info/src/detect.ts index 7d5230c0e9..8b72266248 100644 --- a/packages/framework-info/src/detect.js +++ b/packages/framework-info/src/detect.ts @@ -1,5 +1,8 @@ import pLocate from 'p-locate' +import type { PathExists } from './context.js' +import type { FrameworkDefinition } from './types.js' + // Checks if the project is using a specific framework: // - if `framework.npmDependencies` is set, one of them must be present in the // `package.json` `dependencies|devDependencies` @@ -13,9 +16,9 @@ export const usesFramework = async function ( excludedNpmDependencies: frameworkExcludedNpmDependencies, configFiles, }, - }, - { pathExists, npmDependencies }, -) { + }: FrameworkDefinition, + { pathExists, npmDependencies }: { pathExists: PathExists; npmDependencies: string[] }, +): Promise { return ( usesNpmDependencies(frameworkNpmDependencies, npmDependencies) && lacksExcludedNpmDependencies(frameworkExcludedNpmDependencies, npmDependencies) && @@ -23,24 +26,27 @@ export const usesFramework = async function ( ) } -const usesNpmDependencies = function (frameworkNpmDependencies, npmDependencies) { +const usesNpmDependencies = function (frameworkNpmDependencies: string[], npmDependencies: string[]): boolean { return ( frameworkNpmDependencies.length === 0 || frameworkNpmDependencies.some((frameworkNpmDependency) => npmDependencies.includes(frameworkNpmDependency)) ) } -const lacksExcludedNpmDependencies = function (frameworkExcludedNpmDependencies, npmDependencies) { +const lacksExcludedNpmDependencies = function ( + frameworkExcludedNpmDependencies: string[], + npmDependencies: string[], +): boolean { return frameworkExcludedNpmDependencies.every( (frameworkNpmDependency) => !npmDependencies.includes(frameworkNpmDependency), ) } -const configExists = async (configFiles, pathExists) => { - const exists = await pLocate(configFiles, (file) => pathExists(file)) - return exists +const configExists = async (configFiles: string[], pathExists: PathExists): Promise => { + const exists = await pLocate(configFiles, (file: string) => pathExists(file)) + return !!exists } -const usesConfigFiles = async function (configFiles, pathExists) { +const usesConfigFiles = async function (configFiles: string[], pathExists: PathExists): Promise { return configFiles.length === 0 || (await configExists(configFiles, pathExists)) } diff --git a/packages/framework-info/src/dev.js b/packages/framework-info/src/dev.ts similarity index 67% rename from packages/framework-info/src/dev.js rename to packages/framework-info/src/dev.ts index 2d9912be75..408ac008b6 100644 --- a/packages/framework-info/src/dev.js +++ b/packages/framework-info/src/dev.ts @@ -3,7 +3,15 @@ // - `package.json` `scripts` containing `framework.dev.command` // - `package.json` `scripts` whose names are among `NPM_DEV_SCRIPTS` // - `framework.dev.command` -export const getDevCommands = function ({ frameworkDevCommand, scripts, runScriptCommand }) { +export const getDevCommands = function ({ + frameworkDevCommand, + scripts, + runScriptCommand, +}: { + frameworkDevCommand?: string + scripts: Record + runScriptCommand: string +}): string[] { if (frameworkDevCommand === undefined) { return [] } @@ -17,7 +25,7 @@ export const getDevCommands = function ({ frameworkDevCommand, scripts, runScrip return [frameworkDevCommand] } -const getScriptDevCommands = function (scripts, frameworkDevCommand) { +const getScriptDevCommands = function (scripts: Record, frameworkDevCommand: string): string[] { const preferredScripts = getPreferredScripts(scripts, frameworkDevCommand) if (preferredScripts.length !== 0) { return preferredScripts @@ -27,41 +35,37 @@ const getScriptDevCommands = function (scripts, frameworkDevCommand) { return devScripts.sort(scriptsSorter) } -const getSortIndex = (index) => (index === -1 ? Number.MAX_SAFE_INTEGER : index) +const getSortIndex = (index: number): number => (index === -1 ? Number.MAX_SAFE_INTEGER : index) -const scriptsSorter = (script1, script2) => { +const scriptsSorter = (script1: string, script2: string): number => { const index1 = NPM_DEV_SCRIPTS.findIndex((devScriptName) => matchesNpmWDevScript(script1, devScriptName)) const index2 = NPM_DEV_SCRIPTS.findIndex((devScriptName) => matchesNpmWDevScript(script2, devScriptName)) return getSortIndex(index1) - getSortIndex(index2) } -const getPreferredScripts = function (scripts, frameworkDevCommand) { +const getPreferredScripts = function (scripts: Record, frameworkDevCommand: string): string[] { return Object.entries(scripts) .filter(([, scriptValue]) => scriptValue.includes(frameworkDevCommand)) - .map((script) => getEntryKey(script)) + .map(([key]) => key) .sort(scriptsSorter) } -const getEntryKey = function ([key]) { - return key -} - // Check if the npm script is likely to contain a dev command -const isNpmDevScript = function (scriptName, scriptValue) { +const isNpmDevScript = function (scriptName: string, scriptValue: string): boolean { return NPM_DEV_SCRIPTS.some( (devScriptName) => matchesNpmWDevScript(scriptName, devScriptName) && !isExcludedScript(scriptValue), ) } // We also match script names like `docs:dev` -const matchesNpmWDevScript = function (scriptName, devScriptName) { +const matchesNpmWDevScript = function (scriptName: string, devScriptName: string): boolean { return scriptName === devScriptName || scriptName.endsWith(`:${devScriptName}`) } const NPM_DEV_SCRIPTS = ['dev', 'serve', 'develop', 'start', 'run', 'build', 'web'] -const isExcludedScript = function (scriptValue) { +const isExcludedScript = function (scriptValue: string): boolean { return EXCLUDED_SCRIPTS.some((excluded) => scriptValue.includes(excluded)) } diff --git a/packages/framework-info/src/frameworks/main.js b/packages/framework-info/src/frameworks/main.ts similarity index 92% rename from packages/framework-info/src/frameworks/main.js rename to packages/framework-info/src/frameworks/main.ts index da149f6e54..0ac9849cac 100644 --- a/packages/framework-info/src/frameworks/main.js +++ b/packages/framework-info/src/frameworks/main.ts @@ -1,5 +1,6 @@ // We purposely order the following array to ensure the most relevant framework // is always first, if several frameworks are detected at once. + // Therefore, we cannot use `fs.readdir()`. export const FRAMEWORK_NAMES = [ // Static site generators @@ -56,4 +57,6 @@ export const FRAMEWORK_NAMES = [ 'gulp', 'vite', 'wmr', -] +] as const + +export type FrameworkName = typeof FRAMEWORK_NAMES[number] diff --git a/packages/framework-info/src/main.js b/packages/framework-info/src/main.js deleted file mode 100644 index c41f386556..0000000000 --- a/packages/framework-info/src/main.js +++ /dev/null @@ -1,138 +0,0 @@ -import { join } from 'path' -import { cwd } from 'process' - -import { findUp } from 'find-up' - -import { getContext, getPackageJson } from './context.js' -import { listFrameworks as list, hasFramework as has, getFramework as get } from './core.js' - -/** - * @typedef {object} Options - * @property {string} [projectDir=process.cwd()] - Project's directory - * @property {string} [nodeVersion=process.version] - Node.js version of the runtime environment. Used to recommend Netlify build plugins - */ - -/** - * @typedef {object} Dev - * @property {string} commands - Dev command. There might be several alternatives or empty - * @property {number} port - Server port - */ - -/** - * @typedef {object} Build - * @property {string} commands - Build command. There might be several alternatives - * @property {string} directory - Relative path to the directory where files are built - */ - -/** - * @typedef {object} FrameworkPackage - * @property {string} name - The name of the package. e.g: 'gatsby' - * @property {string} version - The version of the installed package as found in the package.json. Is set to 'unknown' by default. - */ - -/** - * @typedef {object} Framework - * @property {string} id - Id such as `"gatsby"` - * @property {string} category - Category among `"static_site_generator"`, `"frontend_framework"` and `"build_tool"` - * @property {FrameworkPackage} package - Information about the framework's underlying package - * @property {Dev} dev - Information about the dev command - * @property {Build} build - Information about the build command - * @property {object} env - Environment variables that should be set when calling the dev command - * @property {string[]} plugins - A list of recommend Netlify build plugins to install for the framework - */ - -/** - * Gets the version of the framework that is installed in a project. - * - * This cannot currently be used in the browser at this time, which is why it's defined - * here rather than in `core.js` as part of the `getFrameworkInfo` method - * - * @param {string} projectDir - Project directory - * @param {Framework} frameworkInfo - Information about the framework as detected by `getFrameworkInfo` - * - * @returns {Promise} - */ -const getFrameworkVersion = async (projectDir, frameworkInfo) => { - if (!frameworkInfo.package || !frameworkInfo.package.name) { - return frameworkInfo - } - - const npmPackage = frameworkInfo.package.name - - // Get path of package.json for the installed framework. We need to traverse up the directories - // in the event that the project uses something like npm workspaces, and the installed framework package - // has been hoisted to the root directory of the project (which differs from the directory of the project/application being built) - const installedFrameworkPath = await findUp(join('node_modules', npmPackage, 'package.json'), { cwd: projectDir }) - - if (!installedFrameworkPath) { - return frameworkInfo - } - - const { packageJson } = await getPackageJson(installedFrameworkPath) - - return { - ...frameworkInfo, - package: { - name: npmPackage, - version: packageJson?.version || 'unknown', - }, - } -} - -/** - * Return all the frameworks used by a project. - * - * @param {Options} options - Options - * - * @returns {Promise} frameworks - Frameworks used by a project - */ -export const listFrameworks = async function (opts) { - const context = await getContext(opts) - const frameworkList = await list(context) - - const projectDir = opts && opts.projectDir ? opts.projectDir : cwd() - - const settledPromises = await Promise.allSettled( - frameworkList.map((framework) => getFrameworkVersion(projectDir, framework)), - ) - const updatedList = settledPromises.map((result) => { - if (result.status === 'fulfilled') { - return result.value - } - - throw result.reason - }) - - return updatedList -} - -/** - * Return whether a project uses a specific framework - * - * @param {string} frameworkId - Id such as `"gatsby"` - * @param {Options} [options] - Context - * - * @returns {Promise} result - Whether the project uses this framework - */ -export const hasFramework = async function (frameworkId, options) { - const context = await getContext(options) - return has(frameworkId, context) -} - -/** - * Return some information about a framework used by a project. - * - * @param {string} frameworkId - Id such as `"gatsby"` - * @param {Options} [options] - Context - * - * @returns {Promise} framework - Framework used by a project - */ -export const getFramework = async function (frameworkId, options) { - const context = await getContext(options) - return get(frameworkId, context) -} - -export const supportedRuntimes = { - next: { package: '@netlify/plugin-nextjs', skipFlag: 'NETLIFY_NEXT_PLUGIN_SKIP' }, - gatsby: { package: '@netlify/plugin-gatsby', skipFlag: 'NETLIFY_GATSBY_PLUGIN_SKIP' }, -} diff --git a/packages/framework-info/src/main.ts b/packages/framework-info/src/main.ts new file mode 100644 index 0000000000..7d24c744b5 --- /dev/null +++ b/packages/framework-info/src/main.ts @@ -0,0 +1,92 @@ +import { join } from 'path' +import { cwd } from 'process' + +import { findUp } from 'find-up' + +import { getContext, getPackageJson } from './context.js' +import { listFrameworks as list, hasFramework as has, getFramework as get } from './core.js' +import type { FrameworkName } from './frameworks/main.js' +import type { Framework } from './types.js' + +interface Options { + projectDir?: string + nodeVersion?: string +} + +/** + * Gets the version of the framework that is installed in a project. + * + * This cannot currently be used in the browser at this time, which is why it's defined + * here rather than in `core.js` as part of the `getFrameworkInfo` method + */ +const getFrameworkVersion = async (projectDir: string, frameworkInfo: Framework): Promise => { + if (!frameworkInfo.package || !frameworkInfo.package.name) { + return frameworkInfo + } + + const npmPackage = frameworkInfo.package.name + + // Get path of package.json for the installed framework. We need to traverse up the directories + // in the event that the project uses something like npm workspaces, and the installed framework package + // has been hoisted to the root directory of the project (which differs from the directory of the project/application being built) + const installedFrameworkPath = await findUp(join('node_modules', npmPackage, 'package.json'), { cwd: projectDir }) + + if (!installedFrameworkPath) { + return frameworkInfo + } + + const { packageJson } = await getPackageJson(installedFrameworkPath) + + return { + ...frameworkInfo, + package: { + name: npmPackage, + version: packageJson?.version || 'unknown', + }, + } +} + +/** + * Return all the frameworks used by a project. + */ +export const listFrameworks = async function (opts: Options = {}): Promise { + const context = await getContext(opts.projectDir, opts.nodeVersion) + const frameworkList = await list(context) + + const projectDir = opts && opts.projectDir ? opts.projectDir : cwd() + + const settledPromises = await Promise.allSettled( + frameworkList.map((framework) => getFrameworkVersion(projectDir, framework)), + ) + const updatedList = settledPromises.map((result) => { + if (result.status === 'fulfilled') { + return result.value + } + + throw result.reason + }) + + return updatedList +} + +/** + * Return whether a project uses a specific framework + */ +export const hasFramework = async function (frameworkId: FrameworkName, options: Options = {}): Promise { + const context = await getContext(options.projectDir, options.nodeVersion) + return has(frameworkId, context) +} + +/** + * Return some information about a framework used by a project. + */ +export const getFramework = async function (frameworkId: FrameworkName, options: Options = {}): Promise { + const context = await getContext(options.projectDir, options.nodeVersion) + + return get(frameworkId, context) +} + +export const supportedRuntimes = { + next: { package: '@netlify/plugin-nextjs', skipFlag: 'NETLIFY_NEXT_PLUGIN_SKIP' }, + gatsby: { package: '@netlify/plugin-gatsby', skipFlag: 'NETLIFY_GATSBY_PLUGIN_SKIP' }, +} diff --git a/packages/framework-info/src/package.js b/packages/framework-info/src/package.ts similarity index 61% rename from packages/framework-info/src/package.js rename to packages/framework-info/src/package.ts index d183b0514d..266cd06412 100644 --- a/packages/framework-info/src/package.js +++ b/packages/framework-info/src/package.ts @@ -1,22 +1,24 @@ import filterObj from 'filter-obj' import isPlainObj from 'is-plain-obj' +import type { PackageJson } from 'read-pkg-up' -export const getPackageJsonContent = function ({ packageJson }) { +export const getPackageJsonContent = function (packageJson: PackageJson | undefined) { if (packageJson === undefined) { return { npmDependencies: [], scripts: {} } } const npmDependencies = getNpmDependencies(packageJson) const scripts = getScripts(packageJson) + return { npmDependencies, scripts } } // Retrieve `package.json` `dependencies` and `devDependencies` names -const getNpmDependencies = function ({ dependencies, devDependencies }) { +const getNpmDependencies = function ({ dependencies, devDependencies }: PackageJson) { return [...getObjectKeys(dependencies), ...getObjectKeys(devDependencies)] } -const getObjectKeys = function (value) { +const getObjectKeys = function (value: any): string[] { if (!isPlainObj(value)) { return [] } @@ -25,15 +27,14 @@ const getObjectKeys = function (value) { } // Retrieve `package.json` `scripts` -const getScripts = function ({ scripts }) { +const getScripts = function ({ scripts }: PackageJson): Record { if (!isPlainObj(scripts)) { return {} } - const scriptsA = filterObj(scripts, isValidScript) - return scriptsA + return filterObj(scripts, isValidScript) as Record } -const isValidScript = function (key, value) { +const isValidScript = function (_key: unknown, value: any): value is string { return typeof value === 'string' } diff --git a/packages/framework-info/src/plugins.js b/packages/framework-info/src/plugins.ts similarity index 52% rename from packages/framework-info/src/plugins.js rename to packages/framework-info/src/plugins.ts index 4a1c194730..e884ed4426 100644 --- a/packages/framework-info/src/plugins.js +++ b/packages/framework-info/src/plugins.ts @@ -1,16 +1,20 @@ import Ajv from 'ajv' import semver from 'semver' +import type { FrameworkDefinition } from './types.js' + const MIN_NODE_VERSION_KEYWORD = { keyword: 'minNodeVersion', - validate: (minNodeVersion, { nodeVersion }) => + validate: (minNodeVersion: string, { nodeVersion }: { nodeVersion: string }) => semver.valid(minNodeVersion) && semver.valid(nodeVersion) && semver.gte(nodeVersion, minNodeVersion), } +// https://github.com/ajv-validator/ajv/issues/2132 +// @ts-expect-error Ajv types do not work with moduleResolution:nodenext const ajv = new Ajv({}) ajv.addKeyword(MIN_NODE_VERSION_KEYWORD) -export const getPlugins = function (plugins, { nodeVersion }) { +export const getPlugins = function (plugins: FrameworkDefinition['plugins'], { nodeVersion }: { nodeVersion: string }) { return plugins .filter(({ condition }) => ajv.validate(condition, { nodeVersion })) .map(({ packageName }) => packageName) diff --git a/packages/framework-info/src/run_script.js b/packages/framework-info/src/run_script.ts similarity index 55% rename from packages/framework-info/src/run_script.js rename to packages/framework-info/src/run_script.ts index d9b9bd0092..fab9d37aae 100644 --- a/packages/framework-info/src/run_script.js +++ b/packages/framework-info/src/run_script.ts @@ -1,7 +1,15 @@ import { dirname } from 'path' +import type { PathExists } from './context.js' + // Retrieve the command to run `package.json` `scripts` commands -export const getRunScriptCommand = async function ({ pathExists, packageJsonPath }) { +export const getRunScriptCommand = async function ({ + pathExists, + packageJsonPath, +}: { + pathExists: PathExists + packageJsonPath: string +}) { const yarnExists = await pathExists(`${dirname(packageJsonPath)}/yarn.lock`) if (yarnExists) { return 'yarn' diff --git a/packages/framework-info/src/types.ts b/packages/framework-info/src/types.ts new file mode 100644 index 0000000000..5b25395bb0 --- /dev/null +++ b/packages/framework-info/src/types.ts @@ -0,0 +1,60 @@ +import type { FrameworkName } from './frameworks/main.js' + +interface PollingStrategy { + name: 'HTTP' | 'TCP' +} + +interface Plugin { + packageName: string + condition: { + minNodeVersion: string + } +} + +interface BaseFramework { + id: FrameworkName + name: string + category: 'build_tool' | 'frontend_framework' | 'static_site_generator' + logo?: { + default: string + light: string + dark: string + } + staticAssetsDirectory?: string + env: Record +} + +export interface FrameworkDefinition extends BaseFramework { + detect: { + npmDependencies: string[] + excludedNpmDependencies: string[] + configFiles: string[] + } + dev: { + command?: string + port?: number + pollingStrategies?: PollingStrategy[] + } + build: { + command: string + directory: string + } + plugins: Plugin[] +} + +export interface Framework extends BaseFramework { + package: { + name: string + version: string + } + dev: { + commands?: string[] + port?: number + pollingStrategies?: PollingStrategy[] + } + build: { + commands: string[] + directory: string + } + plugins: string[] +} diff --git a/packages/framework-info/test/dev.js b/packages/framework-info/test/dev.js deleted file mode 100644 index 1de685855e..0000000000 --- a/packages/framework-info/test/dev.js +++ /dev/null @@ -1,59 +0,0 @@ -import test from 'ava' - -import { getFrameworks } from './helpers/main.js' - -test('Should use package scripts as dev command', async (t) => { - const frameworks = await getFrameworks('use_scripts') - t.is(frameworks.length, 1) - t.deepEqual(frameworks[0].dev.commands, ['npm run dev', 'npm run start']) -}) - -test('Should allow package scripts names with colons', async (t) => { - const frameworks = await getFrameworks('colon_scripts') - t.is(frameworks.length, 1) - t.deepEqual(frameworks[0].dev.commands, ['npm run docs:dev']) -}) - -test('Should only use package scripts if it includes framework.dev.command', async (t) => { - const frameworks = await getFrameworks('dev_command_scripts') - t.is(frameworks.length, 1) - t.deepEqual(frameworks[0].dev.commands, ['npm run another']) -}) - -test('Should default dev.commands to framework.dev.command', async (t) => { - const frameworks = await getFrameworks('empty_scripts') - t.is(frameworks.length, 1) - t.deepEqual(frameworks[0].dev.commands, ['sapper dev']) -}) - -test('Should sort scripts in the format *:', async (t) => { - const frameworks = await getFrameworks('scripts-order/postfix-format') - - t.is(frameworks.length, 1) - - t.deepEqual(frameworks[0].dev.commands, ['npm run site:dev', 'npm run site:start', 'npm run site:build']) -}) - -test('Should sort scripts when dev command is a substring of build command', async (t) => { - const frameworks = await getFrameworks('scripts-order/command-substring') - - t.is(frameworks.length, 1) - - t.deepEqual(frameworks[0].dev.commands, ['npm run dev', 'npm run build']) -}) - -test('Should prioritize dev over serve', async (t) => { - const frameworks = await getFrameworks('scripts-order/vite-framework') - - t.is(frameworks.length, 1) - - t.deepEqual(frameworks[0].dev.commands, ['npm run dev', 'npm run serve', 'npm run build']) -}) - -test(`Should exclude 'netlify dev' script`, async (t) => { - const frameworks = await getFrameworks('excluded_script') - - t.is(frameworks.length, 1) - - t.deepEqual(frameworks[0].dev.commands, ['npm run build']) -}) diff --git a/packages/framework-info/test/main.js b/packages/framework-info/test/main.js deleted file mode 100644 index 28777e2061..0000000000 --- a/packages/framework-info/test/main.js +++ /dev/null @@ -1,69 +0,0 @@ -import test from 'ava' - -import { getFrameworks, getFramework, hasFramework } from './helpers/main.js' - -test('Should detect frameworks', async (t) => { - const frameworks = await getFrameworks('simple') - t.snapshot(frameworks) -}) - -test('Should return an empty array when no framework is detected', async (t) => { - const frameworks = await getFrameworks('empty') - t.is(frameworks.length, 0) -}) - -test('Should return several items when multiple frameworks are detected', async (t) => { - const frameworks = await getFrameworks('multiple') - t.is(frameworks.length, 2) -}) - -test('Should return the version of each framework when multiple are detected', async (t) => { - const frameworks = await getFrameworks('multiple') - t.snapshot(frameworks) -}) - -test('Should return the version of a framework that is not detected by npm package', async (t) => { - const frameworks = await getFrameworks('no_package') - t.snapshot(frameworks) -}) - -test('Should return the version of the framework when the installed package is hoisted to the root project directory', async (t) => { - const frameworks = await getFrameworks('monorepos/app1') - t.snapshot(frameworks) -}) - -test('Should work if version cannot be detected', async (t) => { - const frameworks = await getFrameworks('no-version') - t.snapshot(frameworks) -}) - -test('Should allow getting a specific framework', async (t) => { - const framework = await getFramework('simple', 'sapper') - t.snapshot(framework) -}) - -test('Should throw when passing an invalid framework', async (t) => { - await t.throwsAsync(getFramework('simple', 'doesNotExist')) -}) - -test('Should allow testing a specific framework', async (t) => { - const trueResult = await hasFramework('simple', 'sapper') - t.true(trueResult) - - const falseResult = await hasFramework('simple', 'nuxt') - t.false(falseResult) -}) - -test('Should throw when testing an invalid framework', async (t) => { - await t.throwsAsync(hasFramework('simple', 'doesNotExist')) -}) - -test('Should sort framework ids in invalid framework error message', async (t) => { - const error = await t.throwsAsync(hasFramework('simple', 'doesNotExist')) - - // we don't use a hardcoded string here, since it will change when a new framework is added - const [, frameworksFromMessage] = error.message.match(/It should be one of: (.+)/) - const frameworksArray = frameworksFromMessage.split(', ') - - t.deepEqual(frameworksArray, [...frameworksArray].sort()) -}) diff --git a/packages/framework-info/test/options.js b/packages/framework-info/test/options.js deleted file mode 100644 index 8d1587bc8c..0000000000 --- a/packages/framework-info/test/options.js +++ /dev/null @@ -1,29 +0,0 @@ -import { cwd, chdir } from 'process' - -import test from 'ava' - -import { listFrameworks } from '../src/main.js' - -import { FIXTURES_DIR } from './helpers/main.js' - -test.serial('projectDir option defaults to process.cwd()', async (t) => { - const oldCwd = cwd() - chdir(`${FIXTURES_DIR}/simple`) - try { - const frameworks = await listFrameworks({}) - t.is(frameworks.length, 1) - } finally { - chdir(oldCwd) - } -}) - -test.serial('Can trigger with no options', async (t) => { - const oldCwd = cwd() - chdir(`${FIXTURES_DIR}/simple`) - try { - const frameworks = await listFrameworks() - t.is(frameworks.length, 1) - } finally { - chdir(oldCwd) - } -}) diff --git a/packages/framework-info/test/run_script.js b/packages/framework-info/test/run_script.js deleted file mode 100644 index b0d2c8b688..0000000000 --- a/packages/framework-info/test/run_script.js +++ /dev/null @@ -1,9 +0,0 @@ -import test from 'ava' - -import { getFrameworks } from './helpers/main.js' - -test('Should use Yarn when there is a yarn.lock', async (t) => { - const frameworks = await getFrameworks('yarn_scripts') - t.is(frameworks.length, 1) - t.deepEqual(frameworks[0].dev.commands, ['yarn dev', 'yarn start']) -}) diff --git a/packages/framework-info/test/snapshots/main.js.md b/packages/framework-info/test/snapshots/main.js.md deleted file mode 100644 index e00c91b5fa..0000000000 --- a/packages/framework-info/test/snapshots/main.js.md +++ /dev/null @@ -1,299 +0,0 @@ -# Snapshot report for `test/main.js` - -The actual snapshot is saved in `main.js.snap`. - -Generated by [AVA](https://avajs.dev). - -## Should detect frameworks - -> Snapshot 1 - - [ - { - build: { - commands: [ - 'sapper export', - ], - directory: '__sapper__/export', - }, - category: 'frontend_framework', - dev: { - commands: [ - 'sapper dev', - ], - pollingStrategies: [ - { - name: 'TCP', - }, - { - name: 'HTTP', - }, - ], - port: 3000, - }, - env: {}, - id: 'sapper', - logo: { - dark: 'https://framework-info.netlify.app/logos/sapper/default.svg', - default: 'https://framework-info.netlify.app/logos/sapper/default.svg', - light: 'https://framework-info.netlify.app/logos/sapper/default.svg', - }, - name: 'Sapper', - package: { - name: 'sapper', - version: '3.4.3', - }, - plugins: [], - staticAssetsDirectory: 'static', - }, - ] - -## Should return the version of each framework when multiple are detected - -> Snapshot 1 - - [ - { - build: { - commands: [ - 'vuepress build', - ], - directory: '.vuepress/dist', - }, - category: 'static_site_generator', - dev: { - commands: [ - 'vuepress dev', - ], - pollingStrategies: [ - { - name: 'TCP', - }, - { - name: 'HTTP', - }, - ], - port: 8080, - }, - env: {}, - id: 'vuepress', - logo: { - dark: 'https://framework-info.netlify.app/logos/vuepress/default.svg', - default: 'https://framework-info.netlify.app/logos/vuepress/default.svg', - light: 'https://framework-info.netlify.app/logos/vuepress/default.svg', - }, - name: 'VuePress', - package: { - name: 'vuepress', - version: '4.5.6', - }, - plugins: [], - staticAssetsDirectory: undefined, - }, - { - build: { - commands: [ - 'vue-cli-service build', - ], - directory: 'dist', - }, - category: 'frontend_framework', - dev: { - commands: [ - 'vue-cli-service serve', - ], - pollingStrategies: [ - { - name: 'TCP', - }, - { - name: 'HTTP', - }, - ], - port: 8080, - }, - env: {}, - id: 'vue', - logo: { - dark: 'https://framework-info.netlify.app/logos/vue/default.svg', - default: 'https://framework-info.netlify.app/logos/vue/default.svg', - light: 'https://framework-info.netlify.app/logos/vue/default.svg', - }, - name: 'Vue.js', - package: { - name: '@vue/cli-service', - version: '1.2.3', - }, - plugins: [], - staticAssetsDirectory: undefined, - }, - ] - -## Should return the version of a framework that is not detected by npm package - -> Snapshot 1 - - [ - { - build: { - commands: [ - 'bundle exec middleman build', - ], - directory: 'build', - }, - category: 'static_site_generator', - dev: { - commands: [ - 'bundle exec middleman server', - ], - pollingStrategies: [ - { - name: 'TCP', - }, - { - name: 'HTTP', - }, - ], - port: 4567, - }, - env: {}, - id: 'middleman', - logo: { - dark: 'https://framework-info.netlify.app/logos/middleman/default.svg', - default: 'https://framework-info.netlify.app/logos/middleman/default.svg', - light: 'https://framework-info.netlify.app/logos/middleman/default.svg', - }, - name: 'Middleman', - package: { - name: undefined, - version: 'unknown', - }, - plugins: [], - staticAssetsDirectory: undefined, - }, - ] - -## Should return the version of the framework when the installed package is hoisted to the root project directory - -> Snapshot 1 - - [ - { - build: { - commands: [ - 'next build', - ], - directory: '.next', - }, - category: 'static_site_generator', - dev: { - commands: [ - 'next', - ], - pollingStrategies: [ - { - name: 'TCP', - }, - ], - port: 3000, - }, - env: {}, - id: 'next', - logo: { - dark: 'https://framework-info.netlify.app/logos/nextjs/dark.svg', - default: 'https://framework-info.netlify.app/logos/nextjs/light.svg', - light: 'https://framework-info.netlify.app/logos/nextjs/light.svg', - }, - name: 'Next.js', - package: { - name: 'next', - version: '3.2.1', - }, - plugins: [ - '@netlify/plugin-nextjs', - ], - staticAssetsDirectory: undefined, - }, - ] - -## Should work if version cannot be detected - -> Snapshot 1 - - [ - { - build: { - commands: [ - 'docpad generate', - ], - directory: 'out', - }, - category: 'static_site_generator', - dev: { - commands: [ - 'docpad run', - ], - pollingStrategies: [ - { - name: 'TCP', - }, - { - name: 'HTTP', - }, - ], - port: 9778, - }, - env: {}, - id: 'docpad', - logo: undefined, - name: 'DocPad', - package: { - name: 'docpad', - version: 'unknown', - }, - plugins: [], - staticAssetsDirectory: undefined, - }, - ] - -## Should allow getting a specific framework - -> Snapshot 1 - - { - build: { - commands: [ - 'sapper export', - ], - directory: '__sapper__/export', - }, - category: 'frontend_framework', - dev: { - commands: [ - 'sapper dev', - ], - pollingStrategies: [ - { - name: 'TCP', - }, - { - name: 'HTTP', - }, - ], - port: 3000, - }, - env: {}, - id: 'sapper', - logo: { - dark: 'https://framework-info.netlify.app/logos/sapper/default.svg', - default: 'https://framework-info.netlify.app/logos/sapper/default.svg', - light: 'https://framework-info.netlify.app/logos/sapper/default.svg', - }, - name: 'Sapper', - package: { - name: 'sapper', - version: 'unknown', - }, - plugins: [], - staticAssetsDirectory: 'static', - } diff --git a/packages/framework-info/test/snapshots/main.js.snap b/packages/framework-info/test/snapshots/main.js.snap deleted file mode 100644 index 390814c6ec7bd2441b266c02cfbb352f0191770b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2320 zcmV+r3GennRzV9vIxC?&K43Z z7}RHGXXa+UnVp&aOolQ4*esj68o%p-i`k(`Hhr_E zi3eEL*%}`oXV_teWf?ZlvNt%5@}I-+A>bRpE5LbkKg%#z0@nc_0}S90YX=^>t2~E( zu_Azf@Vh-S6g>}kc<)mfEl#w$3n+i>@C!dV%hPnu0OcU?Rhl{ydR}`9j{2q` z=1IyLz%%^v0A?%d!h)zs^a$o8dekOMrPggNm5OAkp=yQ|lCwg-5grmpM$*eiCL3zK zE-SOU4b7a0GNI4Pn_;bg_|&Pq6W>pfL~Y*r=lYsqH1sXSqC0)3Wu>YX6k^on>VX3K zTQujKUTk%}D3PkztQ!S=ah8gku@4O(bh<9j*7_83n#n$s_D|?!~eGQxE($s^JrJt!(Zir#VhbUSukXzZP;pX<-vMZj& z-?nGZE=OcOXp4+SjHadtMvVye-4WEPK*UOIS$Kr~HKGU$xchRWP6SaSwl)zdC`lum zJd(t%!|x_wTbwMl2J*v0z7izyXnL_)<*1Z=Q?6{Q3#Td+R_?>3(>o0 zxTJcQU2KwuM)X$3dx7gf@vGO8U+gnq^K&w(DI#@+sjZDx~7U7ps7wkTIf+%&kRu--PsAHWS-HymS%?*ic? z!!f2<17QjH%y5(`Mzlj99HvMUH0e7aoTf+@(Wg8M!kfU~DdNSkK77o1U@h)_NtD2)ZdwqYR^ zv)lSwG5am>Ho#-;@jhTHAOW8OjwG#^o$0t@7O{x95LPt1JaN%1w;)SWoj@h5hFdzR zo8|8GwUyhI&K~cnbY}bF;|OvB_<4NE>>r@K16+!A&6ZwEX7?b#KHwCvBEDp%fwBY~ z?nlY&yIqycoGIm6fx~bJ1_?QjqbMxJ;#nT3Fd^3v;>)^ zGOwun6)R;;;}*@tRm#jN8HuZuJqE&2;8@3%vQ_1#g3A=h5~&F8B}a+q<>4(XDb+k$ z`c1cz_N(Pe+P}yBN9 zYH>6b!q(7Kv-5)cR0kz3eRg1y_FiB!un$-S9!)A~-|MHOy&fiMQ;8*wSIClKwVCNe z%`!XD%&GB|+iBUMerTClemn*IB3{e>3Ce$f%OF2Dbf#qiTgmT5fD-T=FiHzlK>9cd zlsVwxSlLS*2jv9spM@jgqW1glM6J-etFEY}((OcT?I7R%Bwsn2{hiZ`X5$2Mwz<=| zmSDvySubJZR=W0c7Wc|$ec_sLjaaeG?nSZn98I^nV9lpHa1ZZ}Q@sTc^cdAkeIA5I zI##@4voBEsXJ5RVTaTulgnSxXFUGtFN+L^+-n`$|8%t2+sw*}XQ88CS<*1i4{NSWw zHLwk+0G|Y&7~J;)5mM3XCj*jNX^3fln}`eh9|>2=XBC z^?1Q}5tJVTXH%{326|ciaH|pEDqtrah*p3kiNDEpllVEc=}r4jg$Kcr(_EKnfBl*S zFStV|N~CfBGy3xu7n8!qOflqRjC&D;jlfNOr)g}w)osCkXh@r6XS1}X;<4r*;vH-L zao)A&N3r=e+71M*`S(HjAx#^+HFr`aoVL0j7i}1r1A-{%4N{S-a%I_>hq&r@JgG8& zH-7I0RNxqJ68H&l0pO5x)&MsF_tII9ZIkuB*tf5wPKKpCpJh(`l@#CYS5h_sR(yvxc^Uy`fQNzC>0rSmX+D-afLfeQPLd=a z?f+L&&$TW8{DvQ(Q~v)~Qh_HZ(N|JF5iwUeS<1a~w1}($;cAMMrbXmd5bgx-i8Rdp q{Z6XvR(Bp+uI?Pi<_X##X95!PYfxV8gN;roA^!zrOTAZ?D*ym=(|I`n diff --git a/packages/framework-info/tests/__snapshots__/main.test.ts.snap b/packages/framework-info/tests/__snapshots__/main.test.ts.snap new file mode 100644 index 0000000000..d037a38c61 --- /dev/null +++ b/packages/framework-info/tests/__snapshots__/main.test.ts.snap @@ -0,0 +1,283 @@ +// Vitest Snapshot v1 + +exports[`getFramework > Should allow getting a specific framework 1`] = ` +{ + "build": { + "commands": [ + "sapper export", + ], + "directory": "__sapper__/export", + }, + "category": "frontend_framework", + "dev": { + "commands": [ + "sapper dev", + ], + "pollingStrategies": [ + { + "name": "TCP", + }, + { + "name": "HTTP", + }, + ], + "port": 3000, + }, + "env": {}, + "id": "sapper", + "logo": { + "dark": "https://framework-info.netlify.app/logos/sapper/default.svg", + "default": "https://framework-info.netlify.app/logos/sapper/default.svg", + "light": "https://framework-info.netlify.app/logos/sapper/default.svg", + }, + "name": "Sapper", + "package": { + "name": "sapper", + "version": "unknown", + }, + "plugins": [], + "staticAssetsDirectory": "static", +} +`; + +exports[`getFrameworks > Should detect frameworks 1`] = ` +[ + { + "build": { + "commands": [ + "sapper export", + ], + "directory": "__sapper__/export", + }, + "category": "frontend_framework", + "dev": { + "commands": [ + "sapper dev", + ], + "pollingStrategies": [ + { + "name": "TCP", + }, + { + "name": "HTTP", + }, + ], + "port": 3000, + }, + "env": {}, + "id": "sapper", + "logo": { + "dark": "https://framework-info.netlify.app/logos/sapper/default.svg", + "default": "https://framework-info.netlify.app/logos/sapper/default.svg", + "light": "https://framework-info.netlify.app/logos/sapper/default.svg", + }, + "name": "Sapper", + "package": { + "name": "sapper", + "version": "3.4.3", + }, + "plugins": [], + "staticAssetsDirectory": "static", + }, +] +`; + +exports[`getFrameworks > Should return the version of a framework that is not detected by npm package 1`] = ` +[ + { + "build": { + "commands": [ + "bundle exec middleman build", + ], + "directory": "build", + }, + "category": "static_site_generator", + "dev": { + "commands": [ + "bundle exec middleman server", + ], + "pollingStrategies": [ + { + "name": "TCP", + }, + { + "name": "HTTP", + }, + ], + "port": 4567, + }, + "env": {}, + "id": "middleman", + "logo": { + "dark": "https://framework-info.netlify.app/logos/middleman/default.svg", + "default": "https://framework-info.netlify.app/logos/middleman/default.svg", + "light": "https://framework-info.netlify.app/logos/middleman/default.svg", + }, + "name": "Middleman", + "package": { + "name": undefined, + "version": "unknown", + }, + "plugins": [], + "staticAssetsDirectory": undefined, + }, +] +`; + +exports[`getFrameworks > Should return the version of each framework when multiple are detected 1`] = ` +[ + { + "build": { + "commands": [ + "vue-cli-service build", + ], + "directory": "dist", + }, + "category": "frontend_framework", + "dev": { + "commands": [ + "vue-cli-service serve", + ], + "pollingStrategies": [ + { + "name": "TCP", + }, + { + "name": "HTTP", + }, + ], + "port": 8080, + }, + "env": {}, + "id": "vue", + "logo": { + "dark": "https://framework-info.netlify.app/logos/vue/default.svg", + "default": "https://framework-info.netlify.app/logos/vue/default.svg", + "light": "https://framework-info.netlify.app/logos/vue/default.svg", + }, + "name": "Vue.js", + "package": { + "name": "@vue/cli-service", + "version": "1.2.3", + }, + "plugins": [], + "staticAssetsDirectory": undefined, + }, + { + "build": { + "commands": [ + "vuepress build", + ], + "directory": ".vuepress/dist", + }, + "category": "static_site_generator", + "dev": { + "commands": [ + "vuepress dev", + ], + "pollingStrategies": [ + { + "name": "TCP", + }, + { + "name": "HTTP", + }, + ], + "port": 8080, + }, + "env": {}, + "id": "vuepress", + "logo": { + "dark": "https://framework-info.netlify.app/logos/vuepress/default.svg", + "default": "https://framework-info.netlify.app/logos/vuepress/default.svg", + "light": "https://framework-info.netlify.app/logos/vuepress/default.svg", + }, + "name": "VuePress", + "package": { + "name": "vuepress", + "version": "4.5.6", + }, + "plugins": [], + "staticAssetsDirectory": undefined, + }, +] +`; + +exports[`getFrameworks > Should return the version of the framework when the installed package is hoisted to the root project directory 1`] = ` +[ + { + "build": { + "commands": [ + "next build", + ], + "directory": ".next", + }, + "category": "static_site_generator", + "dev": { + "commands": [ + "next", + ], + "pollingStrategies": [ + { + "name": "TCP", + }, + ], + "port": 3000, + }, + "env": {}, + "id": "next", + "logo": { + "dark": "https://framework-info.netlify.app/logos/nextjs/dark.svg", + "default": "https://framework-info.netlify.app/logos/nextjs/light.svg", + "light": "https://framework-info.netlify.app/logos/nextjs/light.svg", + }, + "name": "Next.js", + "package": { + "name": "next", + "version": "3.2.1", + }, + "plugins": [ + "@netlify/plugin-nextjs", + ], + "staticAssetsDirectory": undefined, + }, +] +`; + +exports[`getFrameworks > Should work if version cannot be detected 1`] = ` +[ + { + "build": { + "commands": [ + "docpad generate", + ], + "directory": "out", + }, + "category": "static_site_generator", + "dev": { + "commands": [ + "docpad run", + ], + "pollingStrategies": [ + { + "name": "TCP", + }, + { + "name": "HTTP", + }, + ], + "port": 9778, + }, + "env": {}, + "id": "docpad", + "logo": undefined, + "name": "DocPad", + "package": { + "name": "docpad", + "version": "unknown", + }, + "plugins": [], + "staticAssetsDirectory": undefined, + }, +] +`; diff --git a/packages/framework-info/test/detect.js b/packages/framework-info/tests/detect.test.ts similarity index 54% rename from packages/framework-info/test/detect.js rename to packages/framework-info/tests/detect.test.ts index 8f5ba72e1f..efacb9da85 100644 --- a/packages/framework-info/test/detect.js +++ b/packages/framework-info/tests/detect.test.ts @@ -1,51 +1,51 @@ import { version as nodeVersion } from 'process' -import test from 'ava' +import { expect, test } from 'vitest' import { getFrameworks } from './helpers/main.js' -test('Should detect dependencies', async (t) => { +test('Should detect dependencies', async () => { const frameworks = await getFrameworks('dependencies') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) -test('Should detect devDependencies', async (t) => { +test('Should detect devDependencies', async () => { const frameworks = await getFrameworks('dev_dependencies') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) -test('Should ignore empty framework.npmDependencies', async (t) => { +test('Should ignore empty framework.npmDependencies', async () => { const frameworks = await getFrameworks('empty_dependencies') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) -test('Should detect any of several framework.npmDependencies', async (t) => { +test('Should detect any of several framework.npmDependencies', async () => { const frameworks = await getFrameworks('several_dependencies') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) -test('Should ignore if matching any framework.excludedNpmDependencies', async (t) => { +test('Should ignore if matching any framework.excludedNpmDependencies', async () => { const frameworks = await getFrameworks('excluded_dependencies') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) -test('Should detect config files', async (t) => { +test('Should detect config files', async () => { const frameworks = await getFrameworks('config_files') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) if (nodeVersion !== 'v8.3.0') { - test('Should detect Next.js plugin for Next.js if when Node version >= 10.13.0', async (t) => { + test('Should detect Next.js plugin for Next.js if when Node version >= 10.13.0', async () => { const frameworks = await getFrameworks('next-plugin') - t.is(frameworks[0].id, 'next') - t.deepEqual(frameworks[0].plugins, ['@netlify/plugin-nextjs']) + expect(frameworks[0].id).toBe('next') + expect(frameworks[0].plugins).toEqual(['@netlify/plugin-nextjs']) }) } if (nodeVersion === 'v8.3.0') { - test('Should not detect Next.js plugin for Next.js if when Node version < 10.13.0', async (t) => { + test('Should not detect Next.js plugin for Next.js if when Node version < 10.13.0', async () => { const frameworks = await getFrameworks('next-plugin') - t.is(frameworks[0].id, 'next') - t.is(frameworks[0].plugins.length, 0) + expect(frameworks[0].id).toBe('next') + expect(frameworks[0].plugins).toHaveLength(0) }) } diff --git a/packages/framework-info/tests/dev.test.ts b/packages/framework-info/tests/dev.test.ts new file mode 100644 index 0000000000..586590e1e9 --- /dev/null +++ b/packages/framework-info/tests/dev.test.ts @@ -0,0 +1,51 @@ +import { expect, test } from 'vitest' + +import { getFrameworks } from './helpers/main.js' + +test('Should use package scripts as dev command', async () => { + const frameworks = await getFrameworks('use_scripts') + expect(frameworks).toHaveLength(1) + expect(frameworks[0].dev.commands).toEqual(['npm run dev', 'npm run start']) +}) + +test('Should allow package scripts names with colons', async () => { + const frameworks = await getFrameworks('colon_scripts') + expect(frameworks).toHaveLength(1) + expect(frameworks[0].dev.commands).toEqual(['npm run docs:dev']) +}) + +test('Should only use package scripts if it includes framework.dev.command', async () => { + const frameworks = await getFrameworks('dev_command_scripts') + expect(frameworks).toHaveLength(1) + expect(frameworks[0].dev.commands).toEqual(['npm run another']) +}) + +test('Should default dev.commands to framework.dev.command', async () => { + const frameworks = await getFrameworks('empty_scripts') + expect(frameworks).toHaveLength(1) + expect(frameworks[0].dev.commands).toEqual(['sapper dev']) +}) + +test('Should sort scripts in the format *:', async () => { + const frameworks = await getFrameworks('scripts-order/postfix-format') + expect(frameworks).toHaveLength(1) + expect(frameworks[0].dev.commands).toEqual(['npm run site:dev', 'npm run site:start', 'npm run site:build']) +}) + +test('Should sort scripts when dev command is a substring of build command', async () => { + const frameworks = await getFrameworks('scripts-order/command-substring') + expect(frameworks).toHaveLength(1) + expect(frameworks[0].dev.commands).toEqual(['npm run dev', 'npm run build']) +}) + +test('Should prioritize dev over serve', async () => { + const frameworks = await getFrameworks('scripts-order/vite-framework') + expect(frameworks).toHaveLength(1) + expect(frameworks[0].dev.commands).toEqual(['npm run dev', 'npm run serve', 'npm run build']) +}) + +test(`Should exclude 'netlify dev' script`, async () => { + const frameworks = await getFrameworks('excluded_script') + expect(frameworks).toHaveLength(1) + expect(frameworks[0].dev.commands).toEqual(['npm run build']) +}) diff --git a/packages/framework-info/test/fixtures/colon_scripts/package.json b/packages/framework-info/tests/fixtures/colon_scripts/package.json similarity index 100% rename from packages/framework-info/test/fixtures/colon_scripts/package.json rename to packages/framework-info/tests/fixtures/colon_scripts/package.json diff --git a/packages/framework-info/test/fixtures/config_files/config.rb b/packages/framework-info/tests/fixtures/config_files/config.rb similarity index 100% rename from packages/framework-info/test/fixtures/config_files/config.rb rename to packages/framework-info/tests/fixtures/config_files/config.rb diff --git a/packages/framework-info/test/fixtures/config_files/package.json b/packages/framework-info/tests/fixtures/config_files/package.json similarity index 100% rename from packages/framework-info/test/fixtures/config_files/package.json rename to packages/framework-info/tests/fixtures/config_files/package.json diff --git a/packages/framework-info/test/fixtures/dependencies/package.json b/packages/framework-info/tests/fixtures/dependencies/package.json similarity index 100% rename from packages/framework-info/test/fixtures/dependencies/package.json rename to packages/framework-info/tests/fixtures/dependencies/package.json diff --git a/packages/framework-info/test/fixtures/dev_command_scripts/package.json b/packages/framework-info/tests/fixtures/dev_command_scripts/package.json similarity index 100% rename from packages/framework-info/test/fixtures/dev_command_scripts/package.json rename to packages/framework-info/tests/fixtures/dev_command_scripts/package.json diff --git a/packages/framework-info/test/fixtures/dev_dependencies/package.json b/packages/framework-info/tests/fixtures/dev_dependencies/package.json similarity index 100% rename from packages/framework-info/test/fixtures/dev_dependencies/package.json rename to packages/framework-info/tests/fixtures/dev_dependencies/package.json diff --git a/packages/framework-info/test/fixtures/empty/.gitkeep b/packages/framework-info/tests/fixtures/empty/.gitkeep similarity index 100% rename from packages/framework-info/test/fixtures/empty/.gitkeep rename to packages/framework-info/tests/fixtures/empty/.gitkeep diff --git a/packages/framework-info/test/fixtures/empty/package.json b/packages/framework-info/tests/fixtures/empty/package.json similarity index 100% rename from packages/framework-info/test/fixtures/empty/package.json rename to packages/framework-info/tests/fixtures/empty/package.json diff --git a/packages/framework-info/test/fixtures/empty_dependencies/config.rb b/packages/framework-info/tests/fixtures/empty_dependencies/config.rb similarity index 100% rename from packages/framework-info/test/fixtures/empty_dependencies/config.rb rename to packages/framework-info/tests/fixtures/empty_dependencies/config.rb diff --git a/packages/framework-info/test/fixtures/empty_dependencies/package.json b/packages/framework-info/tests/fixtures/empty_dependencies/package.json similarity index 100% rename from packages/framework-info/test/fixtures/empty_dependencies/package.json rename to packages/framework-info/tests/fixtures/empty_dependencies/package.json diff --git a/packages/framework-info/test/fixtures/empty_scripts/package.json b/packages/framework-info/tests/fixtures/empty_scripts/package.json similarity index 100% rename from packages/framework-info/test/fixtures/empty_scripts/package.json rename to packages/framework-info/tests/fixtures/empty_scripts/package.json diff --git a/packages/framework-info/test/fixtures/excluded_dependencies/package.json b/packages/framework-info/tests/fixtures/excluded_dependencies/package.json similarity index 100% rename from packages/framework-info/test/fixtures/excluded_dependencies/package.json rename to packages/framework-info/tests/fixtures/excluded_dependencies/package.json diff --git a/packages/framework-info/test/fixtures/excluded_script/package.json b/packages/framework-info/tests/fixtures/excluded_script/package.json similarity index 100% rename from packages/framework-info/test/fixtures/excluded_script/package.json rename to packages/framework-info/tests/fixtures/excluded_script/package.json diff --git a/packages/framework-info/test/fixtures/invalid_dependencies/package.json b/packages/framework-info/tests/fixtures/invalid_dependencies/package.json similarity index 100% rename from packages/framework-info/test/fixtures/invalid_dependencies/package.json rename to packages/framework-info/tests/fixtures/invalid_dependencies/package.json diff --git a/packages/framework-info/test/fixtures/invalid_package/package.json b/packages/framework-info/tests/fixtures/invalid_package/package.json similarity index 100% rename from packages/framework-info/test/fixtures/invalid_package/package.json rename to packages/framework-info/tests/fixtures/invalid_package/package.json diff --git a/packages/framework-info/test/fixtures/invalid_scripts/package.json b/packages/framework-info/tests/fixtures/invalid_scripts/package.json similarity index 100% rename from packages/framework-info/test/fixtures/invalid_scripts/package.json rename to packages/framework-info/tests/fixtures/invalid_scripts/package.json diff --git a/packages/framework-info/test/fixtures/monorepos/app1/package.json b/packages/framework-info/tests/fixtures/monorepos/app1/package.json similarity index 100% rename from packages/framework-info/test/fixtures/monorepos/app1/package.json rename to packages/framework-info/tests/fixtures/monorepos/app1/package.json diff --git a/packages/framework-info/test/fixtures/monorepos/app2/package.json b/packages/framework-info/tests/fixtures/monorepos/app2/package.json similarity index 100% rename from packages/framework-info/test/fixtures/monorepos/app2/package.json rename to packages/framework-info/tests/fixtures/monorepos/app2/package.json diff --git a/packages/framework-info/test/fixtures/monorepos/node_modules/next/package.json b/packages/framework-info/tests/fixtures/monorepos/node_modules/next/package.json similarity index 100% rename from packages/framework-info/test/fixtures/monorepos/node_modules/next/package.json rename to packages/framework-info/tests/fixtures/monorepos/node_modules/next/package.json diff --git a/packages/framework-info/test/fixtures/multiple/node_modules/@vue/cli-service/package.json b/packages/framework-info/tests/fixtures/multiple/node_modules/@vue/cli-service/package.json similarity index 100% rename from packages/framework-info/test/fixtures/multiple/node_modules/@vue/cli-service/package.json rename to packages/framework-info/tests/fixtures/multiple/node_modules/@vue/cli-service/package.json diff --git a/packages/framework-info/test/fixtures/multiple/node_modules/vuepress/package.json b/packages/framework-info/tests/fixtures/multiple/node_modules/vuepress/package.json similarity index 100% rename from packages/framework-info/test/fixtures/multiple/node_modules/vuepress/package.json rename to packages/framework-info/tests/fixtures/multiple/node_modules/vuepress/package.json diff --git a/packages/framework-info/test/fixtures/multiple/package.json b/packages/framework-info/tests/fixtures/multiple/package.json similarity index 100% rename from packages/framework-info/test/fixtures/multiple/package.json rename to packages/framework-info/tests/fixtures/multiple/package.json diff --git a/packages/framework-info/test/fixtures/next-plugin/package.json b/packages/framework-info/tests/fixtures/next-plugin/package.json similarity index 100% rename from packages/framework-info/test/fixtures/next-plugin/package.json rename to packages/framework-info/tests/fixtures/next-plugin/package.json diff --git a/packages/framework-info/test/fixtures/no-version/package.json b/packages/framework-info/tests/fixtures/no-version/package.json similarity index 100% rename from packages/framework-info/test/fixtures/no-version/package.json rename to packages/framework-info/tests/fixtures/no-version/package.json diff --git a/packages/framework-info/test/fixtures/no_package/config.rb b/packages/framework-info/tests/fixtures/no_package/config.rb similarity index 100% rename from packages/framework-info/test/fixtures/no_package/config.rb rename to packages/framework-info/tests/fixtures/no_package/config.rb diff --git a/packages/framework-info/test/fixtures/package.json b/packages/framework-info/tests/fixtures/package.json similarity index 100% rename from packages/framework-info/test/fixtures/package.json rename to packages/framework-info/tests/fixtures/package.json diff --git a/packages/framework-info/test/fixtures/parent_package/package.json b/packages/framework-info/tests/fixtures/parent_package/package.json similarity index 100% rename from packages/framework-info/test/fixtures/parent_package/package.json rename to packages/framework-info/tests/fixtures/parent_package/package.json diff --git a/packages/framework-info/test/fixtures/scripts-order/build-first/package.json b/packages/framework-info/tests/fixtures/scripts-order/build-first/package.json similarity index 100% rename from packages/framework-info/test/fixtures/scripts-order/build-first/package.json rename to packages/framework-info/tests/fixtures/scripts-order/build-first/package.json diff --git a/packages/framework-info/test/fixtures/scripts-order/command-substring/package.json b/packages/framework-info/tests/fixtures/scripts-order/command-substring/package.json similarity index 100% rename from packages/framework-info/test/fixtures/scripts-order/command-substring/package.json rename to packages/framework-info/tests/fixtures/scripts-order/command-substring/package.json diff --git a/packages/framework-info/test/fixtures/scripts-order/dev-first/package.json b/packages/framework-info/tests/fixtures/scripts-order/dev-first/package.json similarity index 100% rename from packages/framework-info/test/fixtures/scripts-order/dev-first/package.json rename to packages/framework-info/tests/fixtures/scripts-order/dev-first/package.json diff --git a/packages/framework-info/test/fixtures/scripts-order/postfix-format/package.json b/packages/framework-info/tests/fixtures/scripts-order/postfix-format/package.json similarity index 100% rename from packages/framework-info/test/fixtures/scripts-order/postfix-format/package.json rename to packages/framework-info/tests/fixtures/scripts-order/postfix-format/package.json diff --git a/packages/framework-info/test/fixtures/scripts-order/vite-framework/package.json b/packages/framework-info/tests/fixtures/scripts-order/vite-framework/package.json similarity index 100% rename from packages/framework-info/test/fixtures/scripts-order/vite-framework/package.json rename to packages/framework-info/tests/fixtures/scripts-order/vite-framework/package.json diff --git a/packages/framework-info/test/fixtures/several_dependencies/package.json b/packages/framework-info/tests/fixtures/several_dependencies/package.json similarity index 100% rename from packages/framework-info/test/fixtures/several_dependencies/package.json rename to packages/framework-info/tests/fixtures/several_dependencies/package.json diff --git a/packages/framework-info/test/fixtures/simple/node_modules/sapper/package.json b/packages/framework-info/tests/fixtures/simple/node_modules/sapper/package.json similarity index 100% rename from packages/framework-info/test/fixtures/simple/node_modules/sapper/package.json rename to packages/framework-info/tests/fixtures/simple/node_modules/sapper/package.json diff --git a/packages/framework-info/test/fixtures/simple/package.json b/packages/framework-info/tests/fixtures/simple/package.json similarity index 100% rename from packages/framework-info/test/fixtures/simple/package.json rename to packages/framework-info/tests/fixtures/simple/package.json diff --git a/packages/framework-info/test/fixtures/syntax_package/package.json b/packages/framework-info/tests/fixtures/syntax_package/package.json similarity index 100% rename from packages/framework-info/test/fixtures/syntax_package/package.json rename to packages/framework-info/tests/fixtures/syntax_package/package.json diff --git a/packages/framework-info/test/fixtures/use_scripts/package.json b/packages/framework-info/tests/fixtures/use_scripts/package.json similarity index 100% rename from packages/framework-info/test/fixtures/use_scripts/package.json rename to packages/framework-info/tests/fixtures/use_scripts/package.json diff --git a/packages/framework-info/test/fixtures/yarn_scripts/package.json b/packages/framework-info/tests/fixtures/yarn_scripts/package.json similarity index 100% rename from packages/framework-info/test/fixtures/yarn_scripts/package.json rename to packages/framework-info/tests/fixtures/yarn_scripts/package.json diff --git a/packages/framework-info/test/fixtures/yarn_scripts/yarn.lock b/packages/framework-info/tests/fixtures/yarn_scripts/yarn.lock similarity index 100% rename from packages/framework-info/test/fixtures/yarn_scripts/yarn.lock rename to packages/framework-info/tests/fixtures/yarn_scripts/yarn.lock diff --git a/packages/framework-info/test/frameworks.js b/packages/framework-info/tests/frameworks.test.ts similarity index 76% rename from packages/framework-info/test/frameworks.js rename to packages/framework-info/tests/frameworks.test.ts index 7bc1c2b3f5..0cf342bbde 100644 --- a/packages/framework-info/test/frameworks.js +++ b/packages/framework-info/tests/frameworks.test.ts @@ -1,11 +1,11 @@ -import { promises as fs } from 'fs' -import { extname } from 'path' +import { fileURLToPath } from 'url' import Ajv from 'ajv' -import test from 'ava' -import { each } from 'test-each' +import glob from 'fast-glob' +import { describe, expect, test } from 'vitest' -import { FRAMEWORKS } from '../build/frameworks.js' +import { FRAMEWORK_NAMES } from '../src/frameworks/main.js' +import { FRAMEWORKS } from '../src/generated/frameworks.js' const FRAMEWORKS_DIR = new URL('../src/frameworks/', import.meta.url) @@ -134,18 +134,24 @@ const FRAMEWORK_JSON_SCHEMA = { }, } -each(FRAMEWORKS, (info, framework) => { - test(`Framework "${framework.id}" should have a valid shape`, (t) => { - t.is(validate(framework, FRAMEWORK_JSON_SCHEMA), true) - }) +test.each(FRAMEWORKS)('Framework $id should have a valid shape', (framework) => { + expect(validate(framework, FRAMEWORK_JSON_SCHEMA)).toBe(true) }) -test('each json file should be required in main.js FRAMEWORKS', async (t) => { - const filenames = await fs.readdir(FRAMEWORKS_DIR) - const jsonFiles = filenames.filter((filename) => extname(filename) === '.json') +describe('JSON files', async () => { + const jsonFiles = await glob('*.json', { cwd: fileURLToPath(FRAMEWORKS_DIR) }) + + test('each json file should be required in main.ts FRAMEWORKS', async () => { + expect(FRAMEWORKS).toHaveLength(jsonFiles.length) + FRAMEWORKS.forEach(({ id }) => { + expect(jsonFiles).toContain(`${id}.json`) + }) + }) - t.is(FRAMEWORKS.length, jsonFiles.length) - FRAMEWORKS.forEach(({ id }) => { - t.true(filenames.includes(`${id}.json`)) + test('each json file should be listed in main.ts FRAMEWORK_NAMES', async () => { + expect(FRAMEWORK_NAMES).toHaveLength(jsonFiles.length) + FRAMEWORK_NAMES.forEach((id) => { + expect(jsonFiles).toContain(`${id}.json`) + }) }) }) diff --git a/packages/framework-info/test/helpers/main.js b/packages/framework-info/tests/helpers/main.ts similarity index 100% rename from packages/framework-info/test/helpers/main.js rename to packages/framework-info/tests/helpers/main.ts diff --git a/packages/framework-info/tests/main.test.ts b/packages/framework-info/tests/main.test.ts new file mode 100644 index 0000000000..dc68b054d0 --- /dev/null +++ b/packages/framework-info/tests/main.test.ts @@ -0,0 +1,74 @@ +import { describe, expect, test } from 'vitest' + +import { getFrameworks, getFramework, hasFramework } from './helpers/main.js' + +describe('getFrameworks', () => { + test('Should detect frameworks', async () => { + const frameworks = await getFrameworks('simple') + expect(frameworks).toMatchSnapshot() + }) + + test('Should return an empty array when no framework is detected', async () => { + const frameworks = await getFrameworks('empty') + expect(frameworks).toHaveLength(0) + }) + + test('Should return several items when multiple frameworks are detected', async () => { + const frameworks = await getFrameworks('multiple') + expect(frameworks).toHaveLength(2) + }) + + test('Should return the version of each framework when multiple are detected', async () => { + const frameworks = await getFrameworks('multiple') + expect(frameworks).toMatchSnapshot() + }) + + test('Should return the version of a framework that is not detected by npm package', async () => { + const frameworks = await getFrameworks('no_package') + expect(frameworks).toMatchSnapshot() + }) + + test('Should return the version of the framework when the installed package is hoisted to the root project directory', async () => { + const frameworks = await getFrameworks('monorepos/app1') + expect(frameworks).toMatchSnapshot() + }) + + test('Should work if version cannot be detected', async () => { + const frameworks = await getFrameworks('no-version') + expect(frameworks).toMatchSnapshot() + }) +}) + +describe('getFramework', () => { + test('Should allow getting a specific framework', async () => { + const framework = await getFramework('simple', 'sapper') + expect(framework).toMatchSnapshot() + }) + + test('Should throw when passing an invalid framework', async () => { + await expect(getFramework('simple', 'doesNotExist')).rejects.toThrowError() + }) +}) + +describe('hasFramework', () => { + test('Should allow testing a specific framework', async () => { + expect(await hasFramework('simple', 'sapper')).toBe(true) + expect(await hasFramework('simple', 'nuxt')).toBe(false) + }) + + test('Should throw when testing an invalid framework', async () => { + await expect(hasFramework('simple', 'doesNotExist')).rejects.toThrowError() + }) + + test('Should sort framework ids in invalid framework error message', async () => { + try { + await hasFramework('simple', 'doesNotExist') + expect.fail('should throw') + } catch (error) { + const [, frameworksFromMessage] = error.message.match(/It should be one of: (.+)/) + const frameworksArray = frameworksFromMessage.split(', ') + + expect(frameworksArray).toEqual([...frameworksArray].sort()) + } + }) +}) diff --git a/packages/framework-info/tests/options.test.ts b/packages/framework-info/tests/options.test.ts new file mode 100644 index 0000000000..6dbe3215f7 --- /dev/null +++ b/packages/framework-info/tests/options.test.ts @@ -0,0 +1,21 @@ +import process from 'process' + +import { expect, test, vi } from 'vitest' + +import { listFrameworks } from '../src/main.js' + +import { FIXTURES_DIR } from './helpers/main.js' + +test('projectDir option defaults to process.cwd()', async () => { + const spyInstance = vi.spyOn(process, 'cwd').mockReturnValue(`${FIXTURES_DIR}/simple`) + const frameworks = await listFrameworks({}) + expect(frameworks).toHaveLength(1) + spyInstance.mockRestore() +}) + +test('Can trigger with no options', async () => { + const spyInstance = vi.spyOn(process, 'cwd').mockReturnValue(`${FIXTURES_DIR}/simple`) + const frameworks = await listFrameworks() + expect(frameworks).toHaveLength(1) + spyInstance.mockRestore() +}) diff --git a/packages/framework-info/test/package.js b/packages/framework-info/tests/package.test.ts similarity index 57% rename from packages/framework-info/test/package.js rename to packages/framework-info/tests/package.test.ts index a59198c8b0..37233cc561 100644 --- a/packages/framework-info/test/package.js +++ b/packages/framework-info/tests/package.test.ts @@ -1,49 +1,49 @@ -import test from 'ava' import cpy from 'cpy' import del from 'del' import { dir as getTmpDir } from 'tmp-promise' +import { expect, test } from 'vitest' import { listFrameworks } from '../src/main.js' import { getFrameworks, FIXTURES_DIR } from './helpers/main.js' -test('Should detect package.json in parent directories', async (t) => { +test('Should detect package.json in parent directories', async () => { const frameworks = await getFrameworks('parent_package/parent') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) -test('Should work without a package.json', async (t) => { +test('Should work without a package.json', async () => { const { path: tmpDir } = await getTmpDir() try { await cpy(`${FIXTURES_DIR}/no_package/**`, tmpDir) const frameworks = await listFrameworks({ projectDir: tmpDir }) - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) } finally { del(tmpDir, { force: true }) } }) -test('Should ignore invalid package.json', async (t) => { +test('Should ignore invalid package.json', async () => { const frameworks = await getFrameworks('invalid_package') - t.is(frameworks.length, 0) + expect(frameworks).toHaveLength(0) }) -test('Should ignore package.json with a wrong syntax', async (t) => { +test('Should ignore package.json with a wrong syntax', async () => { const frameworks = await getFrameworks('syntax_package') - t.is(frameworks.length, 0) + expect(frameworks).toHaveLength(0) }) -test('Should ignore invalid package.json dependencies', async (t) => { +test('Should ignore invalid package.json dependencies', async () => { const frameworks = await getFrameworks('invalid_dependencies') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) -test('Should ignore invalid package.json scripts', async (t) => { +test('Should ignore invalid package.json scripts', async () => { const frameworks = await getFrameworks('invalid_scripts') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) -test('Should ignore empty package.json scripts', async (t) => { +test('Should ignore empty package.json scripts', async () => { const frameworks = await getFrameworks('empty_scripts') - t.is(frameworks.length, 1) + expect(frameworks).toHaveLength(1) }) diff --git a/packages/framework-info/tests/run_script.test.ts b/packages/framework-info/tests/run_script.test.ts new file mode 100644 index 0000000000..0c2f7e5733 --- /dev/null +++ b/packages/framework-info/tests/run_script.test.ts @@ -0,0 +1,9 @@ +import { expect, test } from 'vitest' + +import { getFrameworks } from './helpers/main.js' + +test('Should use Yarn when there is a yarn.lock', async () => { + const frameworks = await getFrameworks('yarn_scripts') + expect(frameworks).toHaveLength(1) + expect(frameworks[0].dev.commands).toEqual(['yarn dev', 'yarn start']) +}) diff --git a/packages/framework-info/tsconfig.json b/packages/framework-info/tsconfig.json index 42af80dbea..b6f7555f2e 100644 --- a/packages/framework-info/tsconfig.json +++ b/packages/framework-info/tsconfig.json @@ -1,8 +1,14 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "noEmit": true /* Specify an output folder for all emitted files. */ + "outDir": "lib" /* Specify an output folder for all emitted files. */, + "strict": true, + "noImplicitAny": true, + "strictFunctionTypes": true, + "strictPropertyInitialization": true, + "useUnknownInCatchVariables": true, + "noImplicitReturns": true }, - "include": ["src/**/*.ts", "src/**/*.js"], - "exclude": ["test/**"] + "include": ["src/**/*.ts"], + "exclude": ["tests/**"] } diff --git a/packages/framework-info/vite.config.js b/packages/framework-info/vite.config.js index 6faa1cb4ef..c9155a6532 100644 --- a/packages/framework-info/vite.config.js +++ b/packages/framework-info/vite.config.js @@ -2,10 +2,13 @@ import { fileURLToPath } from 'node:url' import nodePolyfills from 'rollup-plugin-node-polyfills' -const CORE_FILE = fileURLToPath(new URL('src/core.js', import.meta.url)) +const CORE_FILE = fileURLToPath(new URL('src/core.ts', import.meta.url)) /** @type {import('vite').UserConfig} */ export default { + test: { + environment: 'node', + }, resolve: { alias: { path: 'rollup-plugin-node-polyfills/polyfills/path', diff --git a/packages/functions-utils/src/main.ts b/packages/functions-utils/src/main.ts index 4c47aa0b5d..504c0a201e 100644 --- a/packages/functions-utils/src/main.ts +++ b/packages/functions-utils/src/main.ts @@ -7,7 +7,7 @@ import { pathExists } from 'path-exists' // Add a Netlify Function file to the `functions` directory so it is processed // by `@netlify/plugin-functions-core` -export const add = async function (src?: string, dist?: string, { fail = defaultFail } = {}) { +export const add = async function (src?: string, dist?: string, { fail = defaultFail } = {}): Promise { if (src === undefined) { return fail('No function source directory was specified') } diff --git a/packages/nock-udp/src/main.ts b/packages/nock-udp/src/main.ts index b55816742b..e0c982b898 100644 --- a/packages/nock-udp/src/main.ts +++ b/packages/nock-udp/src/main.ts @@ -27,7 +27,7 @@ const validateIncomingMsg = function (buffer, offset, length, address) { } const getMockSocketSend = function ({ allowUnknown = false } = {}) { - const mockSocketSend = function (buffer, offset, length, port, host, callback) { + const mockSocketSend = function (this: Socket, buffer, offset, length, port, host, callback) { const address = `${host}:${port}` if (allowUnknown && !intercepts[address]) { // We allow extraneous connections, fallback to original use diff --git a/tsconfig.base.json b/tsconfig.base.json index c8abbc3f1b..5abd2ea0ff 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -85,11 +85,11 @@ "strictFunctionTypes": false /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */, "strictBindCallApply": false /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */, "strictPropertyInitialization": false /* Check for class properties that are declared but not set in the constructor. */, - "noImplicitThis": false /* Enable error reporting when 'this' is given the type 'any'. */, + "noImplicitThis": true /* Enable error reporting when 'this' is given the type 'any'. */, "useUnknownInCatchVariables": false /* Default catch clause variables as 'unknown' instead of 'any'. */, "alwaysStrict": false /* Ensure 'use strict' is always emitted. */, - "noUnusedLocals": false /* Enable error reporting when local variables aren't read. */, - "noUnusedParameters": false /* Raise an error when a function parameter isn't read. */, + "noUnusedLocals": true /* Enable error reporting when local variables aren't read. */, + "noUnusedParameters": true /* Raise an error when a function parameter isn't read. */, "exactOptionalPropertyTypes": false /* Interpret optional property types as written, rather than adding 'undefined'. */, "noImplicitReturns": false /* Enable error reporting for codepaths that do not explicitly return in a function. */, "noFallthroughCasesInSwitch": false /* Enable error reporting for fallthrough cases in switch statements. */,