mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-25 03:39:14 +00:00
Compare commits
27 Commits
@vercel/no
...
Rush-Works
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c236662fd8 | ||
|
|
cc7577a648 | ||
|
|
f3f3d7df5b | ||
|
|
0bafea6d51 | ||
|
|
5abb74eddd | ||
|
|
23d7eaccab | ||
|
|
2cb008e8ed | ||
|
|
b5c3610113 | ||
|
|
f23c7fc4fc | ||
|
|
3dc1ad6437 | ||
|
|
4dc0bef62b | ||
|
|
8b3c52b9e8 | ||
|
|
fc74300ad0 | ||
|
|
28f8a38e00 | ||
|
|
c318ce9695 | ||
|
|
5b36eaacff | ||
|
|
c9f7ca23a8 | ||
|
|
57e0db0f65 | ||
|
|
d5537500d8 | ||
|
|
4b1736b2f2 | ||
|
|
9da1c6fa66 | ||
|
|
a6c320846e | ||
|
|
4973814978 | ||
|
|
f1289ff263 | ||
|
|
3ff93279cd | ||
|
|
58f9d649a8 | ||
|
|
cadc082ad1 |
@@ -1,6 +1,5 @@
|
||||
import fs from 'fs/promises';
|
||||
import { join, dirname } from 'path';
|
||||
import execa from 'execa';
|
||||
import { getExampleList } from '../examples/example-list';
|
||||
import { mapOldToNew } from '../examples/map-old-to-new';
|
||||
|
||||
@@ -13,6 +12,12 @@ async function main() {
|
||||
await fs.rm(pubDir, { recursive: true, force: true });
|
||||
await fs.mkdir(pubDir);
|
||||
|
||||
await fs.cp(
|
||||
join(repoRoot, 'packages', 'frameworks', 'logos'),
|
||||
join(pubDir, 'framework-logos'),
|
||||
{ recursive: true, force: true }
|
||||
);
|
||||
|
||||
const examples = await getExampleList();
|
||||
const pathListAll = join(pubDir, 'list-all.json');
|
||||
await fs.writeFile(pathListAll, JSON.stringify(examples));
|
||||
@@ -41,10 +46,6 @@ async function main() {
|
||||
JSON.stringify([...existingExamples, ...oldExamples])
|
||||
);
|
||||
|
||||
const { stdout: sha } = await execa('git', ['rev-parse', '--short', 'HEAD'], {
|
||||
cwd: repoRoot,
|
||||
});
|
||||
|
||||
const tarballsDir = join(pubDir, 'tarballs');
|
||||
const packagesDir = join(repoRoot, 'packages');
|
||||
const packages = await fs.readdir(packagesDir);
|
||||
@@ -55,12 +56,21 @@ async function main() {
|
||||
'utf-8'
|
||||
);
|
||||
const packageJson = JSON.parse(packageJsonRaw);
|
||||
const tarballName = `${packageJson.name
|
||||
.replace('@', '')
|
||||
.replace('/', '-')}-v${packageJson.version}-${sha.trim()}.tgz`;
|
||||
const files = await fs.readdir(fullDir);
|
||||
const tarballName = files.find(f => /^vercel-.+\.tgz$/.test(f));
|
||||
if (!tarballName) {
|
||||
throw new Error(
|
||||
`Expected vercel-*.tgz in ${fullDir} but found ${JSON.stringify(
|
||||
files,
|
||||
null,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
const srcTarballPath = join(fullDir, tarballName);
|
||||
const destTarballPath = join(tarballsDir, `${packageJson.name}.tgz`);
|
||||
await fs.mkdir(dirname(destTarballPath), { recursive: true });
|
||||
await fs.copyFile(join(fullDir, tarballName), destTarballPath);
|
||||
await fs.copyFile(srcTarballPath, destTarballPath);
|
||||
}
|
||||
|
||||
console.log('Completed building static frontend.');
|
||||
|
||||
@@ -16,10 +16,6 @@ const frameworks = (_frameworks as Framework[])
|
||||
defaultRoutes: undefined,
|
||||
};
|
||||
|
||||
if (framework.logo) {
|
||||
framework.logo = `https://assets.vercel.com/zeit-inc/image/fetch/${framework.logo}`;
|
||||
}
|
||||
|
||||
return framework;
|
||||
});
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "12.2.5",
|
||||
"next": "12.3.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "8.22.0",
|
||||
"eslint-config-next": "12.2.5"
|
||||
"eslint": "8.23.0",
|
||||
"eslint-config-next": "12.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,28 +3,28 @@
|
||||
|
||||
|
||||
"@babel/runtime-corejs3@^7.10.2":
|
||||
version "7.18.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz#7bacecd1cb2dd694eacd32a91fcf7021c20770ae"
|
||||
integrity sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==
|
||||
version "7.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.19.0.tgz#0df75cb8e5ecba3ca9e658898694e5326d52397f"
|
||||
integrity sha512-JyXXoCu1N8GLuKc2ii8y5RGma5FMpFeO2nAQIe0Yzrbq+rQnN+sFj47auLblR5ka6aHNGPDgv8G/iI2Grb0ldQ==
|
||||
dependencies:
|
||||
core-js-pure "^3.20.2"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.10.2", "@babel/runtime@^7.18.9":
|
||||
version "7.18.9"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
|
||||
integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
|
||||
version "7.19.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
|
||||
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@eslint/eslintrc@^1.3.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
|
||||
integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==
|
||||
"@eslint/eslintrc@^1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.1.tgz#de0807bfeffc37b964a7d0400e0c348ce5a2543d"
|
||||
integrity sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
espree "^9.3.2"
|
||||
espree "^9.4.0"
|
||||
globals "^13.15.0"
|
||||
ignore "^5.2.0"
|
||||
import-fresh "^3.2.1"
|
||||
@@ -46,87 +46,92 @@
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d"
|
||||
integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==
|
||||
|
||||
"@humanwhocodes/module-importer@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
|
||||
integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
|
||||
|
||||
"@humanwhocodes/object-schema@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||
|
||||
"@next/env@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.5.tgz#d908c57b35262b94db3e431e869b72ac3e1ad3e3"
|
||||
integrity sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw==
|
||||
"@next/env@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.0.tgz#85f971fdc668cc312342761057c59cb8ab1abadf"
|
||||
integrity sha512-PTJpjAFVbzBQ9xXpzMTroShvD5YDIIy46jQ7d4LrWpY+/5a8H90Tm8hE3Hvkc5RBRspVo7kvEOnqQms0A+2Q6w==
|
||||
|
||||
"@next/eslint-plugin-next@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.5.tgz#4f3acccd2ed4f9300fbf9fd480cc8a0b261889a8"
|
||||
integrity sha512-VBjVbmqEzGiOTBq4+wpeVXt/KgknnGB6ahvC/AxiIGnN93/RCSyXhFRI4uSfftM2Ba3w7ZO7076bfKasZsA0fw==
|
||||
"@next/eslint-plugin-next@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.0.tgz#302c1f03618d5001ce92ea6826c329268759128e"
|
||||
integrity sha512-jVdq1qYTNDjUtulnE8/hkPv0pHILV4jMg5La99iaY/FFm20WxVnsAZtbNnMvlPbf8dc010oO304SX9yXbg5PAw==
|
||||
dependencies:
|
||||
glob "7.1.7"
|
||||
|
||||
"@next/swc-android-arm-eabi@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.5.tgz#903a5479ab4c2705d9c08d080907475f7bacf94d"
|
||||
integrity sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA==
|
||||
"@next/swc-android-arm-eabi@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.0.tgz#9a934904643591cb6f66eb09803a92d2b10ada13"
|
||||
integrity sha512-/PuirPnAKsYBw93w/7Q9hqy+KGOU9mjYprZ/faxMUJh/dc6v3rYLxkZKNG9nFPIW4QKNTCnhP40xF9hLnxO+xg==
|
||||
|
||||
"@next/swc-android-arm64@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.5.tgz#2f9a98ec4166c7860510963b31bda1f57a77c792"
|
||||
integrity sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg==
|
||||
"@next/swc-android-arm64@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.0.tgz#c1e3e24d0625efe88f45a2135c8f5c4dff594749"
|
||||
integrity sha512-OaI+FhAM6P9B6Ybwbn0Zl8YwWido0lLwhDBi9WiYCh4RQmIXAyVIoIJPHo4fP05+mXaJ/k1trvDvuURvHOq2qw==
|
||||
|
||||
"@next/swc-darwin-arm64@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz#31b1c3c659d54be546120c488a1e1bad21c24a1d"
|
||||
integrity sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg==
|
||||
"@next/swc-darwin-arm64@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.0.tgz#37a9f971b9ad620184af69f38243a36757126fb9"
|
||||
integrity sha512-9s4d3Mhii+WFce8o8Jok7WC3Bawkr9wEUU++SJRptjU1L5tsfYJMrSYCACHLhZujziNDLyExe4Hwwsccps1sfg==
|
||||
|
||||
"@next/swc-darwin-x64@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.5.tgz#2e44dd82b2b7fef88238d1bc4d3bead5884cedfd"
|
||||
integrity sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A==
|
||||
"@next/swc-darwin-x64@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.0.tgz#fb017f1066c8cf2b8da49ef3588c8731d8bf1bf3"
|
||||
integrity sha512-2scC4MqUTwGwok+wpVxP+zWp7WcCAVOtutki2E1n99rBOTnUOX6qXkgxSy083yBN6GqwuC/dzHeN7hIKjavfRA==
|
||||
|
||||
"@next/swc-freebsd-x64@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.5.tgz#e24e75d8c2581bfebc75e4f08f6ddbd116ce9dbd"
|
||||
integrity sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw==
|
||||
"@next/swc-freebsd-x64@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.0.tgz#e7955b016f41e0f95088e3459ff4197027871fbf"
|
||||
integrity sha512-xAlruUREij/bFa+qsE1tmsP28t7vz02N4ZDHt2lh3uJUniE0Ne9idyIDLc1Ed0IF2RjfgOp4ZVunuS3OM0sngw==
|
||||
|
||||
"@next/swc-linux-arm-gnueabihf@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.5.tgz#46d8c514d834d2b5f67086013f0bd5e3081e10b9"
|
||||
integrity sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg==
|
||||
"@next/swc-linux-arm-gnueabihf@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.0.tgz#d2233267bffaa24378245b328f2f8a01a37eab29"
|
||||
integrity sha512-jin2S4VT/cugc2dSZEUIabhYDJNgrUh7fufbdsaAezgcQzqfdfJqfxl4E9GuafzB4cbRPTaqA0V5uqbp0IyGkQ==
|
||||
|
||||
"@next/swc-linux-arm64-gnu@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.5.tgz#91f725ac217d3a1f4f9f53b553615ba582fd3d9f"
|
||||
integrity sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ==
|
||||
"@next/swc-linux-arm64-gnu@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.0.tgz#149a0cb877352ab63e81cf1dd53b37f382929d2a"
|
||||
integrity sha512-RqJHDKe0WImeUrdR0kayTkRWgp4vD/MS7g0r6Xuf8+ellOFH7JAAJffDW3ayuVZeMYOa7RvgNFcOoWnrTUl9Nw==
|
||||
|
||||
"@next/swc-linux-arm64-musl@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.5.tgz#e627e8c867920995810250303cd9b8e963598383"
|
||||
integrity sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg==
|
||||
"@next/swc-linux-arm64-musl@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.0.tgz#73ec7f121f56fd7cf99cf2b00cf41f62c4560e90"
|
||||
integrity sha512-nvNWoUieMjvDjpYJ/4SQe9lQs2xMj6ZRs8N+bmTrVu9leY2Fg3WD6W9p/1uU9hGO8u+OdF13wc4iRShu/WYIHg==
|
||||
|
||||
"@next/swc-linux-x64-gnu@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.5.tgz#83a5e224fbc4d119ef2e0f29d0d79c40cc43887e"
|
||||
integrity sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw==
|
||||
"@next/swc-linux-x64-gnu@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.0.tgz#6812e52ef21bfd091810f271dd61da11d82b66b9"
|
||||
integrity sha512-4ajhIuVU9PeQCMMhdDgZTLrHmjbOUFuIyg6J19hZqwEwDTSqQyrSLkbJs2Nd7IRiM6Ul/XyrtEFCpk4k+xD2+w==
|
||||
|
||||
"@next/swc-linux-x64-musl@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.5.tgz#be700d48471baac1ec2e9539396625584a317e95"
|
||||
integrity sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g==
|
||||
"@next/swc-linux-x64-musl@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.0.tgz#c9e7ffb6d44da330961c1ce651c5b03a1becfe22"
|
||||
integrity sha512-U092RBYbaGxoMAwpauePJEu2PuZSEoUCGJBvsptQr2/2XIMwAJDYM4c/M5NfYEsBr+yjvsYNsOpYfeQ88D82Yg==
|
||||
|
||||
"@next/swc-win32-arm64-msvc@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.5.tgz#a93e958133ad3310373fda33a79aa10af2a0aa97"
|
||||
integrity sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw==
|
||||
"@next/swc-win32-arm64-msvc@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.0.tgz#e0d9d26297f52b0d3b3c2f5138ddcce30601bc98"
|
||||
integrity sha512-pzSzaxjDEJe67bUok9Nxf9rykbJfHXW0owICFsPBsqHyc+cr8vpF7g9e2APTCddtVhvjkga9ILoZJ9NxWS7Yiw==
|
||||
|
||||
"@next/swc-win32-ia32-msvc@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.5.tgz#4f5f7ba0a98ff89a883625d4af0125baed8b2e19"
|
||||
integrity sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw==
|
||||
"@next/swc-win32-ia32-msvc@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.0.tgz#37daeac1acc68537b8e76cd81fde96dce11f78b4"
|
||||
integrity sha512-MQGUpMbYhQmTZ06a9e0hPQJnxFMwETo2WtyAotY3GEzbNCQVbCGhsvqEKcl+ZEHgShlHXUWvSffq1ZscY6gK7A==
|
||||
|
||||
"@next/swc-win32-x64-msvc@12.2.5":
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz#20fed129b04a0d3f632c6d0de135345bb623b1e4"
|
||||
integrity sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q==
|
||||
"@next/swc-win32-x64-msvc@12.3.0":
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.0.tgz#c1b983316307f8f55fee491942b5d244bd2036e2"
|
||||
integrity sha512-C/nw6OgQpEULWqs+wgMHXGvlJLguPRFFGqR2TAqWBerQ8J+Sg3z1ZTqwelkSi4FoqStGuZ2UdFHIDN1ySmR1xA==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
@@ -154,10 +159,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz#0c8b74c50f29ee44f423f7416829c0bf8bb5eb27"
|
||||
integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==
|
||||
|
||||
"@swc/helpers@0.4.3":
|
||||
version "0.4.3"
|
||||
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.3.tgz#16593dfc248c53b699d4b5026040f88ddb497012"
|
||||
integrity sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==
|
||||
"@swc/helpers@0.4.11":
|
||||
version "0.4.11"
|
||||
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.11.tgz#db23a376761b3d31c26502122f349a21b592c8de"
|
||||
integrity sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==
|
||||
dependencies:
|
||||
tslib "^2.4.0"
|
||||
|
||||
@@ -167,47 +172,47 @@
|
||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||
|
||||
"@typescript-eslint/parser@^5.21.0":
|
||||
version "5.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.34.0.tgz#ca710858ea85dbfd30c9b416a335dc49e82dbc07"
|
||||
integrity sha512-SZ3NEnK4usd2CXkoV3jPa/vo1mWX1fqRyIVUQZR4As1vyp4fneknBNJj+OFtV8WAVgGf+rOHMSqQbs2Qn3nFZQ==
|
||||
version "5.36.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.36.2.tgz#3ddf323d3ac85a25295a55fcb9c7a49ab4680ddd"
|
||||
integrity sha512-qS/Kb0yzy8sR0idFspI9Z6+t7mqk/oRjnAYfewG+VN73opAUvmYL3oPIMmgOX6CnQS6gmVIXGshlb5RY/R22pA==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "5.34.0"
|
||||
"@typescript-eslint/types" "5.34.0"
|
||||
"@typescript-eslint/typescript-estree" "5.34.0"
|
||||
"@typescript-eslint/scope-manager" "5.36.2"
|
||||
"@typescript-eslint/types" "5.36.2"
|
||||
"@typescript-eslint/typescript-estree" "5.36.2"
|
||||
debug "^4.3.4"
|
||||
|
||||
"@typescript-eslint/scope-manager@5.34.0":
|
||||
version "5.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.34.0.tgz#14efd13dc57602937e25f188fd911f118781e527"
|
||||
integrity sha512-HNvASMQlah5RsBW6L6c7IJ0vsm+8Sope/wu5sEAf7joJYWNb1LDbJipzmdhdUOnfrDFE6LR1j57x1EYVxrY4ow==
|
||||
"@typescript-eslint/scope-manager@5.36.2":
|
||||
version "5.36.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.36.2.tgz#a75eb588a3879ae659514780831370642505d1cd"
|
||||
integrity sha512-cNNP51L8SkIFSfce8B1NSUBTJTu2Ts4nWeWbFrdaqjmn9yKrAaJUBHkyTZc0cL06OFHpb+JZq5AUHROS398Orw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.34.0"
|
||||
"@typescript-eslint/visitor-keys" "5.34.0"
|
||||
"@typescript-eslint/types" "5.36.2"
|
||||
"@typescript-eslint/visitor-keys" "5.36.2"
|
||||
|
||||
"@typescript-eslint/types@5.34.0":
|
||||
version "5.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.34.0.tgz#217bf08049e9e7b86694d982e88a2c1566330c78"
|
||||
integrity sha512-49fm3xbbUPuzBIOcy2CDpYWqy/X7VBkxVN+DC21e0zIm3+61Z0NZi6J9mqPmSW1BDVk9FIOvuCFyUPjXz93sjA==
|
||||
"@typescript-eslint/types@5.36.2":
|
||||
version "5.36.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.36.2.tgz#a5066e500ebcfcee36694186ccc57b955c05faf9"
|
||||
integrity sha512-9OJSvvwuF1L5eS2EQgFUbECb99F0mwq501w0H0EkYULkhFa19Qq7WFbycdw1PexAc929asupbZcgjVIe6OK/XQ==
|
||||
|
||||
"@typescript-eslint/typescript-estree@5.34.0":
|
||||
version "5.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.34.0.tgz#ba7b83f4bf8ccbabf074bbf1baca7a58de3ccb9a"
|
||||
integrity sha512-mXHAqapJJDVzxauEkfJI96j3D10sd567LlqroyCeJaHnu42sDbjxotGb3XFtGPYKPD9IyLjhsoULML1oI3M86A==
|
||||
"@typescript-eslint/typescript-estree@5.36.2":
|
||||
version "5.36.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.36.2.tgz#0c93418b36c53ba0bc34c61fe9405c4d1d8fe560"
|
||||
integrity sha512-8fyH+RfbKc0mTspfuEjlfqA4YywcwQK2Amcf6TDOwaRLg7Vwdu4bZzyvBZp4bjt1RRjQ5MDnOZahxMrt2l5v9w==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.34.0"
|
||||
"@typescript-eslint/visitor-keys" "5.34.0"
|
||||
"@typescript-eslint/types" "5.36.2"
|
||||
"@typescript-eslint/visitor-keys" "5.36.2"
|
||||
debug "^4.3.4"
|
||||
globby "^11.1.0"
|
||||
is-glob "^4.0.3"
|
||||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@5.34.0":
|
||||
version "5.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.34.0.tgz#d0fb3e31033e82ddd5de048371ad39eb342b2d40"
|
||||
integrity sha512-O1moYjOSrab0a2fUvFpsJe0QHtvTC+cR+ovYpgKrAVXzqQyc74mv76TgY6z+aEtjQE2vgZux3CQVtGryqdcOAw==
|
||||
"@typescript-eslint/visitor-keys@5.36.2":
|
||||
version "5.36.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.36.2.tgz#2f8f78da0a3bad3320d2ac24965791ac39dace5a"
|
||||
integrity sha512-BtRvSR6dEdrNt7Net2/XDjbYKU5Ml6GqJgVfXT0CxTCJlnIqK7rAGreuWKMT2t8cFUT2Msv5oxw0GMRD7T5J7A==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.34.0"
|
||||
"@typescript-eslint/types" "5.36.2"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
acorn-jsx@^5.3.2:
|
||||
@@ -340,9 +345,9 @@ callsites@^3.0.0:
|
||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||
|
||||
caniuse-lite@^1.0.30001332:
|
||||
version "1.0.30001382"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001382.tgz#4d37f0d0b6fffb826c8e5e1c0f4bf8ce592db949"
|
||||
integrity sha512-2rtJwDmSZ716Pxm1wCtbPvHtbDWAreTPxXbkc5RkKglow3Ig/4GNGazDI9/BVnXbG/wnv6r3B5FEbkfg9OcTGg==
|
||||
version "1.0.30001393"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001393.tgz#1aa161e24fe6af2e2ccda000fc2b94be0b0db356"
|
||||
integrity sha512-N/od11RX+Gsk+1qY/jbPa0R6zJupEa0lxeBG598EbrtblxVCTJsQwbRBm6+V+rxpc5lHKdsXb9RY83cZIPLseA==
|
||||
|
||||
chalk@^4.0.0:
|
||||
version "4.1.2"
|
||||
@@ -370,9 +375,9 @@ concat-map@0.0.1:
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
|
||||
core-js-pure@^3.20.2:
|
||||
version "3.24.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.24.1.tgz#8839dde5da545521bf282feb7dc6d0b425f39fd3"
|
||||
integrity sha512-r1nJk41QLLPyozHUUPmILCEMtMw24NG4oWK6RbsDdjzQgg9ZvrUsPBj1MnG0wXXp1DCDU6j+wUvEmBSrtRbLXg==
|
||||
version "3.25.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.1.tgz#79546518ae87cc362c991d9c2d211f45107991ee"
|
||||
integrity sha512-7Fr74bliUDdeJCBMxkkIuQ4xfxn/SwrVg+HkJUAoNEXVqYLv55l6Af0dJ5Lq2YBUW9yKqSkLXaS5SYPK6MGa/A==
|
||||
|
||||
cross-spawn@^7.0.2:
|
||||
version "7.0.3"
|
||||
@@ -449,15 +454,15 @@ emoji-regex@^9.2.2:
|
||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||
|
||||
es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5:
|
||||
version "1.20.1"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
|
||||
integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
|
||||
version "1.20.2"
|
||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.2.tgz#8495a07bc56d342a3b8ea3ab01bd986700c2ccb3"
|
||||
integrity sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==
|
||||
dependencies:
|
||||
call-bind "^1.0.2"
|
||||
es-to-primitive "^1.2.1"
|
||||
function-bind "^1.1.1"
|
||||
function.prototype.name "^1.1.5"
|
||||
get-intrinsic "^1.1.1"
|
||||
get-intrinsic "^1.1.2"
|
||||
get-symbol-description "^1.0.0"
|
||||
has "^1.0.3"
|
||||
has-property-descriptors "^1.0.0"
|
||||
@@ -469,9 +474,9 @@ es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19
|
||||
is-shared-array-buffer "^1.0.2"
|
||||
is-string "^1.0.7"
|
||||
is-weakref "^1.0.2"
|
||||
object-inspect "^1.12.0"
|
||||
object-inspect "^1.12.2"
|
||||
object-keys "^1.1.1"
|
||||
object.assign "^4.1.2"
|
||||
object.assign "^4.1.4"
|
||||
regexp.prototype.flags "^1.4.3"
|
||||
string.prototype.trimend "^1.0.5"
|
||||
string.prototype.trimstart "^1.0.5"
|
||||
@@ -498,12 +503,12 @@ escape-string-regexp@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
eslint-config-next@12.2.5:
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.2.5.tgz#76ce83f18cc02f6f42ed407a127f83db54fabd3c"
|
||||
integrity sha512-SOowilkqPzW6DxKp3a3SYlrfPi5Ajs9MIzp9gVfUDxxH9QFM5ElkR1hX5m/iICJuvCbWgQqFBiA3mCMozluniw==
|
||||
eslint-config-next@12.3.0:
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.3.0.tgz#d887ab2d143fe1a2b308e9321e932a613e610800"
|
||||
integrity sha512-guHSkNyKnTBB8HU35COgAMeMV0E026BiYRYvyEVVaTOeFcnU3i1EI8/Da0Rl7H3Sgua5FEvoA0vYd2s8kdIUXg==
|
||||
dependencies:
|
||||
"@next/eslint-plugin-next" "12.2.5"
|
||||
"@next/eslint-plugin-next" "12.3.0"
|
||||
"@rushstack/eslint-patch" "^1.1.3"
|
||||
"@typescript-eslint/parser" "^5.21.0"
|
||||
eslint-import-resolver-node "^0.3.6"
|
||||
@@ -583,9 +588,9 @@ eslint-plugin-react-hooks@^4.5.0:
|
||||
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
|
||||
|
||||
eslint-plugin-react@^7.29.4:
|
||||
version "7.30.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22"
|
||||
integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==
|
||||
version "7.31.7"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.7.tgz#36fb1c611a7db5f757fce09cbbcc01682f8b0fbb"
|
||||
integrity sha512-8NldBTeYp/kQoTV1uT0XF6HcmDqbgZ0lNPkN0wlRw8DJKXEnaWu+oh/6gt3xIhzvQ35wB2Y545fJhIbJSZ2NNw==
|
||||
dependencies:
|
||||
array-includes "^3.1.5"
|
||||
array.prototype.flatmap "^1.3.0"
|
||||
@@ -627,14 +632,15 @@ eslint-visitor-keys@^3.3.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
|
||||
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
||||
|
||||
eslint@8.22.0:
|
||||
version "8.22.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.22.0.tgz#78fcb044196dfa7eef30a9d65944f6f980402c48"
|
||||
integrity sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==
|
||||
eslint@8.23.0:
|
||||
version "8.23.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.0.tgz#a184918d288820179c6041bb3ddcc99ce6eea040"
|
||||
integrity sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==
|
||||
dependencies:
|
||||
"@eslint/eslintrc" "^1.3.0"
|
||||
"@eslint/eslintrc" "^1.3.1"
|
||||
"@humanwhocodes/config-array" "^0.10.4"
|
||||
"@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
ajv "^6.10.0"
|
||||
chalk "^4.0.0"
|
||||
cross-spawn "^7.0.2"
|
||||
@@ -644,7 +650,7 @@ eslint@8.22.0:
|
||||
eslint-scope "^7.1.1"
|
||||
eslint-utils "^3.0.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
espree "^9.3.3"
|
||||
espree "^9.4.0"
|
||||
esquery "^1.4.0"
|
||||
esutils "^2.0.2"
|
||||
fast-deep-equal "^3.1.3"
|
||||
@@ -670,12 +676,11 @@ eslint@8.22.0:
|
||||
strip-ansi "^6.0.1"
|
||||
strip-json-comments "^3.1.0"
|
||||
text-table "^0.2.0"
|
||||
v8-compile-cache "^2.0.3"
|
||||
|
||||
espree@^9.3.2, espree@^9.3.3:
|
||||
version "9.3.3"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.3.tgz#2dd37c4162bb05f433ad3c1a52ddf8a49dc08e9d"
|
||||
integrity sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==
|
||||
espree@^9.4.0:
|
||||
version "9.4.0"
|
||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a"
|
||||
integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==
|
||||
dependencies:
|
||||
acorn "^8.8.0"
|
||||
acorn-jsx "^5.3.2"
|
||||
@@ -803,7 +808,7 @@ functions-have-names@^1.2.2:
|
||||
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
|
||||
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
|
||||
|
||||
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
|
||||
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598"
|
||||
integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==
|
||||
@@ -1195,38 +1200,38 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
next@12.2.5:
|
||||
version "12.2.5"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717"
|
||||
integrity sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA==
|
||||
next@12.3.0:
|
||||
version "12.3.0"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.3.0.tgz#0e4c1ed0092544c7e8f4c998ca57cf6529e286cb"
|
||||
integrity sha512-GpzI6me9V1+XYtfK0Ae9WD0mKqHyzQlGq1xH1rzNIYMASo4Tkl4rTe9jSqtBpXFhOS33KohXs9ZY38Akkhdciw==
|
||||
dependencies:
|
||||
"@next/env" "12.2.5"
|
||||
"@swc/helpers" "0.4.3"
|
||||
"@next/env" "12.3.0"
|
||||
"@swc/helpers" "0.4.11"
|
||||
caniuse-lite "^1.0.30001332"
|
||||
postcss "8.4.14"
|
||||
styled-jsx "5.0.4"
|
||||
styled-jsx "5.0.6"
|
||||
use-sync-external-store "1.2.0"
|
||||
optionalDependencies:
|
||||
"@next/swc-android-arm-eabi" "12.2.5"
|
||||
"@next/swc-android-arm64" "12.2.5"
|
||||
"@next/swc-darwin-arm64" "12.2.5"
|
||||
"@next/swc-darwin-x64" "12.2.5"
|
||||
"@next/swc-freebsd-x64" "12.2.5"
|
||||
"@next/swc-linux-arm-gnueabihf" "12.2.5"
|
||||
"@next/swc-linux-arm64-gnu" "12.2.5"
|
||||
"@next/swc-linux-arm64-musl" "12.2.5"
|
||||
"@next/swc-linux-x64-gnu" "12.2.5"
|
||||
"@next/swc-linux-x64-musl" "12.2.5"
|
||||
"@next/swc-win32-arm64-msvc" "12.2.5"
|
||||
"@next/swc-win32-ia32-msvc" "12.2.5"
|
||||
"@next/swc-win32-x64-msvc" "12.2.5"
|
||||
"@next/swc-android-arm-eabi" "12.3.0"
|
||||
"@next/swc-android-arm64" "12.3.0"
|
||||
"@next/swc-darwin-arm64" "12.3.0"
|
||||
"@next/swc-darwin-x64" "12.3.0"
|
||||
"@next/swc-freebsd-x64" "12.3.0"
|
||||
"@next/swc-linux-arm-gnueabihf" "12.3.0"
|
||||
"@next/swc-linux-arm64-gnu" "12.3.0"
|
||||
"@next/swc-linux-arm64-musl" "12.3.0"
|
||||
"@next/swc-linux-x64-gnu" "12.3.0"
|
||||
"@next/swc-linux-x64-musl" "12.3.0"
|
||||
"@next/swc-win32-arm64-msvc" "12.3.0"
|
||||
"@next/swc-win32-ia32-msvc" "12.3.0"
|
||||
"@next/swc-win32-x64-msvc" "12.3.0"
|
||||
|
||||
object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
||||
|
||||
object-inspect@^1.12.0, object-inspect@^1.9.0:
|
||||
object-inspect@^1.12.2, object-inspect@^1.9.0:
|
||||
version "1.12.2"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
|
||||
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
|
||||
@@ -1236,7 +1241,7 @@ object-keys@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
||||
|
||||
object.assign@^4.1.2, object.assign@^4.1.3:
|
||||
object.assign@^4.1.3, object.assign@^4.1.4:
|
||||
version "4.1.4"
|
||||
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
|
||||
integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
|
||||
@@ -1569,10 +1574,10 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||
|
||||
styled-jsx@5.0.4:
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.4.tgz#5b1bd0b9ab44caae3dd1361295559706e044aa53"
|
||||
integrity sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ==
|
||||
styled-jsx@5.0.6:
|
||||
version "5.0.6"
|
||||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.6.tgz#fa684790a9cc3badded14badea163418fe568f77"
|
||||
integrity sha512-xOeROtkK5MGMDimBQ3J6iPId8q0t/BDoG5XN6oKkZClVz9ISF/hihN8OCn2LggMU6N32aXnrXBdn3auSqNS9fA==
|
||||
|
||||
supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
@@ -1659,11 +1664,6 @@ use-sync-external-store@1.2.0:
|
||||
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
|
||||
integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
|
||||
|
||||
v8-compile-cache@^2.0.3:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||
integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
|
||||
|
||||
which-boxed-primitive@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "5.4.1",
|
||||
"version": "5.4.2",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
@@ -41,6 +41,7 @@ export interface Config {
|
||||
devCommand?: string;
|
||||
framework?: string | null;
|
||||
nodeVersion?: string;
|
||||
middleware?: boolean;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
@@ -341,6 +342,7 @@ export interface BuilderV2 {
|
||||
version: 2;
|
||||
build: BuildV2;
|
||||
prepareCache?: PrepareCache;
|
||||
shouldServe?: ShouldServe;
|
||||
}
|
||||
|
||||
export interface BuilderV3 {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "28.2.1",
|
||||
"version": "28.2.5",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -41,16 +41,16 @@
|
||||
"node": ">= 14"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/go": "2.2.4",
|
||||
"@vercel/hydrogen": "0.0.17",
|
||||
"@vercel/next": "3.1.23",
|
||||
"@vercel/node": "2.5.12",
|
||||
"@vercel/python": "3.1.13",
|
||||
"@vercel/redwood": "1.0.21",
|
||||
"@vercel/remix": "1.0.22",
|
||||
"@vercel/ruby": "1.3.30",
|
||||
"@vercel/static-build": "1.0.21",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/go": "2.2.5",
|
||||
"@vercel/hydrogen": "0.0.18",
|
||||
"@vercel/next": "3.1.25",
|
||||
"@vercel/node": "2.5.14",
|
||||
"@vercel/python": "3.1.14",
|
||||
"@vercel/redwood": "1.0.23",
|
||||
"@vercel/remix": "1.0.24",
|
||||
"@vercel/ruby": "1.3.31",
|
||||
"@vercel/static-build": "1.0.23",
|
||||
"update-notifier": "5.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -95,9 +95,9 @@
|
||||
"@types/which": "1.3.2",
|
||||
"@types/write-json-file": "2.2.1",
|
||||
"@types/yauzl-promise": "2.1.0",
|
||||
"@vercel/client": "12.2.3",
|
||||
"@vercel/frameworks": "1.1.3",
|
||||
"@vercel/fs-detectors": "2.1.0",
|
||||
"@vercel/client": "12.2.4",
|
||||
"@vercel/frameworks": "1.1.5",
|
||||
"@vercel/fs-detectors": "3.2.0",
|
||||
"@vercel/fun": "1.0.4",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@zeit/source-map-support": "0.6.2",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { resolve, join } from 'path';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
import DevServer from '../../util/dev/server';
|
||||
import parseListen from '../../util/dev/parse-listen';
|
||||
import { parseListen } from '../../util/dev/parse-listen';
|
||||
import { ProjectEnvVariable } from '../../types';
|
||||
import Client from '../../util/client';
|
||||
import { getLinkedProject } from '../../util/projects/link';
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { URL } from 'url';
|
||||
import plural from 'pluralize';
|
||||
import npa from 'npm-package-arg';
|
||||
import { satisfies } from 'semver';
|
||||
import { dirname, join } from 'path';
|
||||
import { mkdirp, outputJSON, readJSON, symlink } from 'fs-extra';
|
||||
import { isStaticRuntime } from '@vercel/fs-detectors';
|
||||
import {
|
||||
BuilderV2,
|
||||
BuilderV3,
|
||||
@@ -13,6 +16,9 @@ import { VERCEL_DIR } from '../projects/link';
|
||||
import { Output } from '../output';
|
||||
import readJSONFile from '../read-json-file';
|
||||
import { CantParseJSONFile } from '../errors-ts';
|
||||
import { errorToString, isErrnoException, isError } from '../is-error';
|
||||
import cmd from '../output/cmd';
|
||||
import code from '../output/code';
|
||||
|
||||
export interface BuilderWithPkg {
|
||||
path: string;
|
||||
@@ -81,7 +87,7 @@ export async function resolveBuilders(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (name === '@vercel/static' || name === '@now/static') {
|
||||
if (isStaticRuntime(name)) {
|
||||
// `@vercel/static` is a special-case built-in builder
|
||||
builders.set(name, {
|
||||
builder: staticBuilder,
|
||||
@@ -201,15 +207,54 @@ async function installBuilders(
|
||||
if (err.code !== 'EEXIST') throw err;
|
||||
}
|
||||
|
||||
output.debug(`Installing Builders: ${Array.from(buildersToAdd).join(', ')}`);
|
||||
await spawnAsync('yarn', ['add', '@vercel/build-utils', ...buildersToAdd], {
|
||||
cwd: buildersDir,
|
||||
});
|
||||
output.log(
|
||||
`Installing ${plural('Builder', buildersToAdd.size)}: ${Array.from(
|
||||
buildersToAdd
|
||||
).join(', ')}`
|
||||
);
|
||||
try {
|
||||
await spawnAsync(
|
||||
'npm',
|
||||
['install', '@vercel/build-utils', ...buildersToAdd],
|
||||
{
|
||||
cwd: buildersDir,
|
||||
stdio: 'pipe',
|
||||
}
|
||||
);
|
||||
} catch (err: unknown) {
|
||||
if (isError(err)) {
|
||||
(err as any).link =
|
||||
'https://vercel.link/builder-dependencies-install-failed';
|
||||
if (isErrnoException(err) && err.code === 'ENOENT') {
|
||||
// `npm` is not installed
|
||||
err.message = `Please install ${cmd('npm')} before continuing`;
|
||||
} else {
|
||||
const message = errorToString(err);
|
||||
const notFound = /GET (.*) - Not found/.exec(message);
|
||||
if (notFound) {
|
||||
const url = new URL(notFound[1]);
|
||||
const packageName = decodeURIComponent(url.pathname.slice(1));
|
||||
err.message = `The package ${code(
|
||||
packageName
|
||||
)} is not published on the npm registry`;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Symlink `@now/build-utils` -> `@vercel/build-utils` to support legacy Builders
|
||||
const nowScopePath = join(buildersDir, 'node_modules/@now');
|
||||
await mkdirp(nowScopePath);
|
||||
await symlink('../@vercel/build-utils', join(nowScopePath, 'build-utils'));
|
||||
|
||||
try {
|
||||
await symlink('../@vercel/build-utils', join(nowScopePath, 'build-utils'));
|
||||
} catch (err: unknown) {
|
||||
if (!isErrnoException(err) || err.code !== 'EEXIST') {
|
||||
// Throw unless the error is due to the symlink already existing
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// Cross-reference any builderSpecs from the saved `package.json` file,
|
||||
// in case they were installed from a URL
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import minimatch from 'minimatch';
|
||||
import { BuildV2, Files } from '@vercel/build-utils';
|
||||
import { shouldServe as defaultShouldServe } from '@vercel/build-utils';
|
||||
import type { BuildV2, Files, ShouldServe } from '@vercel/build-utils';
|
||||
|
||||
export const version = 2;
|
||||
|
||||
@@ -39,3 +40,18 @@ export const build: BuildV2 = async ({ entrypoint, files, config }) => {
|
||||
|
||||
return { output };
|
||||
};
|
||||
|
||||
export const shouldServe: ShouldServe = _opts => {
|
||||
const opts = { ..._opts };
|
||||
const {
|
||||
config: { zeroConfig, outputDirectory },
|
||||
} = opts;
|
||||
|
||||
// Add the output directory prefix
|
||||
if (zeroConfig && outputDirectory) {
|
||||
opts.entrypoint = `${outputDirectory}/${opts.entrypoint}`;
|
||||
opts.requestPath = `${outputDirectory}/${opts.requestPath}`;
|
||||
}
|
||||
|
||||
return defaultShouldServe(opts);
|
||||
};
|
||||
|
||||
@@ -1,412 +0,0 @@
|
||||
import chalk from 'chalk';
|
||||
import execa from 'execa';
|
||||
import semver from 'semver';
|
||||
import npa from 'npm-package-arg';
|
||||
import pluralize from 'pluralize';
|
||||
import { basename, join } from 'path';
|
||||
import XDGAppPaths from 'xdg-app-paths';
|
||||
import { mkdirp, readJSON, writeJSON } from 'fs-extra';
|
||||
import { NowBuildError, PackageJson } from '@vercel/build-utils';
|
||||
import cliPkg from '../pkg';
|
||||
|
||||
import cmd from '../output/cmd';
|
||||
import { Output } from '../output';
|
||||
import { NoBuilderCacheError } from '../errors-ts';
|
||||
|
||||
import * as staticBuilder from './static-builder';
|
||||
import { BuilderWithPackage } from './types';
|
||||
import { isErrnoException } from '../is-error';
|
||||
|
||||
const require_: typeof require = eval('require');
|
||||
|
||||
const registryTypes = new Set(['version', 'tag', 'range']);
|
||||
|
||||
const createStaticBuilder = (scope: string): BuilderWithPackage => {
|
||||
return {
|
||||
runInProcess: true,
|
||||
requirePath: `${scope}/static`,
|
||||
builder: Object.freeze(staticBuilder),
|
||||
package: Object.freeze({ name: `@${scope}/static`, version: '' }),
|
||||
};
|
||||
};
|
||||
|
||||
const localBuilders: { [key: string]: BuilderWithPackage } = {
|
||||
'@now/static': createStaticBuilder('now'),
|
||||
'@vercel/static': createStaticBuilder('vercel'),
|
||||
};
|
||||
|
||||
export const cacheDirPromise = prepareCacheDir();
|
||||
export const builderDirPromise = prepareBuilderDir();
|
||||
|
||||
/**
|
||||
* Prepare cache directory for installing Vercel runtimes.
|
||||
*/
|
||||
export async function prepareCacheDir() {
|
||||
const designated = XDGAppPaths('com.vercel.cli').cache();
|
||||
|
||||
if (!designated) {
|
||||
throw new NoBuilderCacheError();
|
||||
}
|
||||
|
||||
const cacheDir = join(designated, 'dev');
|
||||
await mkdirp(cacheDir);
|
||||
return cacheDir;
|
||||
}
|
||||
|
||||
export async function prepareBuilderDir() {
|
||||
const builderDir = join(await cacheDirPromise, 'builders');
|
||||
await mkdirp(builderDir);
|
||||
|
||||
// Create an empty `package.json` file, only if one does not already exist
|
||||
try {
|
||||
const buildersPkg = join(builderDir, 'package.json');
|
||||
await writeJSON(buildersPkg, { private: true }, { flag: 'wx' });
|
||||
} catch (err: unknown) {
|
||||
if (!isErrnoException(err) || err.code !== 'EEXIST') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
return builderDir;
|
||||
}
|
||||
|
||||
function getNpmVersion(use = ''): string {
|
||||
const parsed = npa(use);
|
||||
if (registryTypes.has(parsed.type)) {
|
||||
return parsed.fetchSpec || '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
export function getBuildUtils(packages: string[]): string {
|
||||
const version = packages
|
||||
.map(getNpmVersion)
|
||||
.some(ver => ver.includes('canary'))
|
||||
? 'canary'
|
||||
: 'latest';
|
||||
|
||||
return `@vercel/build-utils@${version}`;
|
||||
}
|
||||
|
||||
function parseVersionSafe(rawSpec: string) {
|
||||
try {
|
||||
return semver.parse(rawSpec);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function filterPackage(
|
||||
builderSpec: string,
|
||||
buildersPkg: PackageJson,
|
||||
cliPkg: Partial<PackageJson>
|
||||
) {
|
||||
if (builderSpec in localBuilders) return false;
|
||||
const parsed = npa(builderSpec);
|
||||
const parsedVersion = parseVersionSafe(parsed.rawSpec);
|
||||
|
||||
// Skip install of Runtimes that are part of Vercel CLI's `dependencies`
|
||||
if (isBundledBuilder(parsed, cliPkg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip install of already installed Runtime with exact version match
|
||||
if (
|
||||
parsed.name &&
|
||||
parsed.type === 'version' &&
|
||||
parsedVersion &&
|
||||
buildersPkg.dependencies &&
|
||||
parsedVersion.version == buildersPkg.dependencies[parsed.name]
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install a list of builders to the cache directory.
|
||||
*/
|
||||
export async function installBuilders(
|
||||
packagesSet: Set<string>,
|
||||
output: Output,
|
||||
builderDir?: string
|
||||
): Promise<void> {
|
||||
const packages = Array.from(packagesSet);
|
||||
if (
|
||||
packages.length === 0 ||
|
||||
(packages.length === 1 &&
|
||||
Object.hasOwnProperty.call(localBuilders, packages[0]))
|
||||
) {
|
||||
// Static deployment, no builders to install
|
||||
return;
|
||||
}
|
||||
if (!builderDir) {
|
||||
builderDir = await builderDirPromise;
|
||||
}
|
||||
const buildersPkgPath = join(builderDir, 'package.json');
|
||||
const buildersPkgBefore = await readJSON(buildersPkgPath);
|
||||
const depsBefore = {
|
||||
...buildersPkgBefore.devDependencies,
|
||||
...buildersPkgBefore.dependencies,
|
||||
};
|
||||
|
||||
// Filter out any packages that come packaged with Vercel CLI
|
||||
const packagesToInstall = packages.filter(p =>
|
||||
filterPackage(p, buildersPkgBefore, cliPkg)
|
||||
);
|
||||
|
||||
if (packagesToInstall.length === 0) {
|
||||
output.debug('No Runtimes need to be installed');
|
||||
return;
|
||||
}
|
||||
|
||||
packagesToInstall.push(getBuildUtils(packages));
|
||||
|
||||
await npmInstall(builderDir, output, packagesToInstall, false);
|
||||
|
||||
const updatedPackages: string[] = [];
|
||||
const buildersPkgAfter = await readJSON(buildersPkgPath);
|
||||
const depsAfter = {
|
||||
...buildersPkgAfter.devDependencies,
|
||||
...buildersPkgAfter.dependencies,
|
||||
};
|
||||
for (const [name, version] of Object.entries(depsAfter)) {
|
||||
if (version !== depsBefore[name]) {
|
||||
output.debug(`Runtime "${name}" updated to version \`${version}\``);
|
||||
updatedPackages.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
purgeRequireCache(updatedPackages, builderDir, output);
|
||||
}
|
||||
|
||||
async function npmInstall(
|
||||
cwd: string,
|
||||
output: Output,
|
||||
packagesToInstall: string[],
|
||||
silent: boolean
|
||||
) {
|
||||
const sortedPackages = packagesToInstall.sort();
|
||||
|
||||
if (!silent) {
|
||||
output.spinner(
|
||||
`Installing ${pluralize(
|
||||
'Runtime',
|
||||
sortedPackages.length
|
||||
)}: ${sortedPackages.join(', ')}`
|
||||
);
|
||||
}
|
||||
|
||||
output.debug(`Running npm install in ${cwd}`);
|
||||
|
||||
try {
|
||||
const args = [
|
||||
'install',
|
||||
'--save-exact',
|
||||
'--no-package-lock',
|
||||
'--no-audit',
|
||||
'--no-progress',
|
||||
];
|
||||
if (process.stderr.isTTY) {
|
||||
// Force colors in the npm child process
|
||||
// https://docs.npmjs.com/misc/config#color
|
||||
args.push('--color=always');
|
||||
}
|
||||
args.push(...sortedPackages);
|
||||
const result = await execa('npm', args, {
|
||||
cwd,
|
||||
reject: false,
|
||||
stdio: output.isDebugEnabled() ? 'inherit' : 'pipe',
|
||||
});
|
||||
if (result.failed) {
|
||||
output.stopSpinner();
|
||||
if (result.stdout) {
|
||||
console.log(result.stdout);
|
||||
}
|
||||
if (result.stderr) {
|
||||
console.error(result.stderr);
|
||||
}
|
||||
throw new NowBuildError({
|
||||
message:
|
||||
(result as any).code === 'ENOENT'
|
||||
? `Command not found: ${chalk.cyan(
|
||||
'npm'
|
||||
)}\nPlease ensure that ${cmd('npm')} is properly installed`
|
||||
: 'Failed to install `vercel dev` dependencies',
|
||||
code: 'NPM_INSTALL_ERROR',
|
||||
link: 'https://vercel.link/npm-install-failed-dev',
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
output.stopSpinner();
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateBuilders(
|
||||
packagesSet: Set<string>,
|
||||
output: Output,
|
||||
builderDir?: string
|
||||
): Promise<string[]> {
|
||||
if (!builderDir) {
|
||||
builderDir = await builderDirPromise;
|
||||
}
|
||||
|
||||
const updatedPackages: string[] = [];
|
||||
const packages = Array.from(packagesSet);
|
||||
const buildersPkgPath = join(builderDir, 'package.json');
|
||||
const buildersPkgBefore = await readJSON(buildersPkgPath);
|
||||
const depsBefore = {
|
||||
...buildersPkgBefore.devDependencies,
|
||||
...buildersPkgBefore.dependencies,
|
||||
};
|
||||
|
||||
const packagesToUpdate = packages.filter(p => {
|
||||
if (p in localBuilders) return false;
|
||||
|
||||
// If it's a builder that is part of Vercel CLI's
|
||||
// `dependencies` then don't update it
|
||||
if (isBundledBuilder(npa(p), cliPkg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if (packagesToUpdate.length > 0) {
|
||||
packagesToUpdate.push(getBuildUtils(packages));
|
||||
|
||||
await npmInstall(builderDir, output, packagesToUpdate, true);
|
||||
|
||||
const buildersPkgAfter = await readJSON(buildersPkgPath);
|
||||
const depsAfter = {
|
||||
...buildersPkgAfter.devDependencies,
|
||||
...buildersPkgAfter.dependencies,
|
||||
};
|
||||
for (const [name, version] of Object.entries(depsAfter)) {
|
||||
if (version !== depsBefore[name]) {
|
||||
output.debug(`Runtime "${name}" updated to version \`${version}\``);
|
||||
updatedPackages.push(name);
|
||||
}
|
||||
}
|
||||
|
||||
purgeRequireCache(updatedPackages, builderDir, output);
|
||||
}
|
||||
|
||||
return updatedPackages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a builder from the cache directory.
|
||||
*/
|
||||
export async function getBuilder(
|
||||
builderPkg: string,
|
||||
output: Output,
|
||||
builderDir?: string,
|
||||
isRetry = false
|
||||
): Promise<BuilderWithPackage> {
|
||||
let builderWithPkg: BuilderWithPackage = localBuilders[builderPkg];
|
||||
if (!builderWithPkg) {
|
||||
if (!builderDir) {
|
||||
builderDir = await builderDirPromise;
|
||||
}
|
||||
let requirePath: string;
|
||||
const parsed = npa(builderPkg);
|
||||
|
||||
// First check if it's a bundled Runtime in Vercel CLI's `node_modules`
|
||||
const bundledBuilder = isBundledBuilder(parsed, cliPkg);
|
||||
if (bundledBuilder && parsed.name) {
|
||||
requirePath = parsed.name;
|
||||
} else {
|
||||
const buildersPkg = await readJSON(join(builderDir, 'package.json'));
|
||||
const pkgName = getPackageName(parsed, buildersPkg) || builderPkg;
|
||||
requirePath = join(builderDir, 'node_modules', pkgName);
|
||||
}
|
||||
|
||||
try {
|
||||
output.debug(`Requiring runtime: "${requirePath}"`);
|
||||
const mod = require_(requirePath);
|
||||
const pkg = require_(join(requirePath, 'package.json'));
|
||||
builderWithPkg = {
|
||||
requirePath,
|
||||
builder: Object.freeze(mod),
|
||||
package: Object.freeze(pkg),
|
||||
};
|
||||
} catch (err: unknown) {
|
||||
if (
|
||||
isErrnoException(err) &&
|
||||
err.code === 'MODULE_NOT_FOUND' &&
|
||||
!isRetry
|
||||
) {
|
||||
output.debug(
|
||||
`Attempted to require ${requirePath}, but it is not installed`
|
||||
);
|
||||
const pkgSet = new Set([builderPkg]);
|
||||
await installBuilders(pkgSet, output, builderDir);
|
||||
|
||||
// Run `getBuilder()` again now that the builder has been installed
|
||||
return getBuilder(builderPkg, output, builderDir, true);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
// If it's a bundled builder, then cache the require call
|
||||
if (bundledBuilder) {
|
||||
localBuilders[builderPkg] = builderWithPkg;
|
||||
}
|
||||
}
|
||||
return builderWithPkg;
|
||||
}
|
||||
|
||||
export function isBundledBuilder(
|
||||
parsed: npa.Result,
|
||||
{ dependencies = {} }: PackageJson
|
||||
): boolean {
|
||||
if (!parsed.name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const inCliDependencyList = !!dependencies[parsed.name];
|
||||
const inScope = parsed.scope === '@vercel';
|
||||
const isVersionedReference = ['tag', 'version', 'range'].includes(
|
||||
parsed.type
|
||||
);
|
||||
|
||||
return inCliDependencyList && inScope && isVersionedReference;
|
||||
}
|
||||
|
||||
function getPackageName(
|
||||
parsed: npa.Result,
|
||||
buildersPkg: PackageJson
|
||||
): string | null {
|
||||
if (registryTypes.has(parsed.type)) {
|
||||
return parsed.name;
|
||||
}
|
||||
const deps: PackageJson.DependencyMap = {
|
||||
...buildersPkg.devDependencies,
|
||||
...buildersPkg.dependencies,
|
||||
};
|
||||
for (const [name, dep] of Object.entries(deps)) {
|
||||
if (dep === parsed.raw || basename(dep) === basename(parsed.raw)) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function purgeRequireCache(
|
||||
packages: string[],
|
||||
builderDir: string,
|
||||
output: Output
|
||||
) {
|
||||
// The `require()` cache for the builder's assets must be purged
|
||||
const packagesPaths = packages.map(b => join(builderDir, 'node_modules', b));
|
||||
for (const id of Object.keys(require_.cache)) {
|
||||
for (const path of packagesPaths) {
|
||||
if (id.startsWith(path)) {
|
||||
output.debug(`Purging require cache for "${id}"`);
|
||||
delete require_.cache[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
FileFsRef,
|
||||
normalizePath,
|
||||
} from '@vercel/build-utils';
|
||||
import { isOfficialRuntime } from '@vercel/fs-detectors';
|
||||
import { isStaticRuntime } from '@vercel/fs-detectors';
|
||||
import plural from 'pluralize';
|
||||
import minimatch from 'minimatch';
|
||||
|
||||
@@ -26,7 +26,6 @@ import { relative } from '../path-helpers';
|
||||
import { LambdaSizeExceededError } from '../errors-ts';
|
||||
|
||||
import DevServer from './server';
|
||||
import { getBuilder } from './builder-cache';
|
||||
import {
|
||||
VercelConfig,
|
||||
BuildMatch,
|
||||
@@ -41,6 +40,7 @@ import {
|
||||
import { normalizeRoutes } from '@vercel/routing-utils';
|
||||
import getUpdateCommand from '../get-update-command';
|
||||
import { getTitleName } from '../pkg-name';
|
||||
import { importBuilders } from '../build/import-builders';
|
||||
|
||||
interface BuildMessage {
|
||||
type: string;
|
||||
@@ -108,18 +108,18 @@ export async function executeBuild(
|
||||
filesRemoved?: string[]
|
||||
): Promise<void> {
|
||||
const {
|
||||
builderWithPkg: { runInProcess, requirePath, builder, package: pkg },
|
||||
builderWithPkg: { path: requirePath, builder, pkg },
|
||||
} = match;
|
||||
const { entrypoint } = match;
|
||||
const { entrypoint, use } = match;
|
||||
const isStatic = isStaticRuntime(use);
|
||||
const { envConfigs, cwd: workPath, devCacheDir } = devServer;
|
||||
const debug = devServer.output.isDebugEnabled();
|
||||
|
||||
const startTime = Date.now();
|
||||
const showBuildTimestamp =
|
||||
!isOfficialRuntime('static', match.use) && (!isInitialBuild || debug);
|
||||
const showBuildTimestamp = !isStatic && (!isInitialBuild || debug);
|
||||
|
||||
if (showBuildTimestamp) {
|
||||
devServer.output.log(`Building ${match.use}:${entrypoint}`);
|
||||
devServer.output.log(`Building ${use}:${entrypoint}`);
|
||||
devServer.output.debug(
|
||||
`Using \`${pkg.name}${pkg.version ? `@${pkg.version}` : ''}\``
|
||||
);
|
||||
@@ -130,7 +130,7 @@ export async function executeBuild(
|
||||
let result: BuildResult;
|
||||
|
||||
let { buildProcess } = match;
|
||||
if (!runInProcess && !buildProcess) {
|
||||
if (!isStatic && !buildProcess) {
|
||||
buildProcess = await createBuildProcess(
|
||||
match,
|
||||
envConfigs,
|
||||
@@ -158,7 +158,7 @@ export async function executeBuild(
|
||||
},
|
||||
};
|
||||
|
||||
let buildResultOrOutputs: BuilderOutputs | BuildResult | BuildResultV3;
|
||||
let buildResultOrOutputs;
|
||||
if (buildProcess) {
|
||||
buildProcess.send({
|
||||
type: 'build',
|
||||
@@ -198,16 +198,12 @@ export async function executeBuild(
|
||||
}
|
||||
|
||||
// Sort out build result to builder v2 shape
|
||||
if (!builder.version || builder.version === 1) {
|
||||
if (!builder.version || (builder as any).version === 1) {
|
||||
// `BuilderOutputs` map was returned (Now Builder v1 behavior)
|
||||
result = {
|
||||
output: buildResultOrOutputs as BuilderOutputs,
|
||||
routes: [],
|
||||
watch: [],
|
||||
distPath:
|
||||
typeof buildResultOrOutputs.distPath === 'string'
|
||||
? buildResultOrOutputs.distPath
|
||||
: undefined,
|
||||
};
|
||||
} else if (builder.version === 2) {
|
||||
result = buildResultOrOutputs as BuildResult;
|
||||
@@ -253,7 +249,7 @@ export async function executeBuild(
|
||||
} else {
|
||||
throw new Error(
|
||||
`${getTitleName()} CLI does not support builder version ${
|
||||
builder.version
|
||||
(builder as any).version
|
||||
}.\nPlease run \`${await getUpdateCommand()}\` to update to the latest CLI.`
|
||||
);
|
||||
}
|
||||
@@ -383,7 +379,7 @@ export async function executeBuild(
|
||||
if (showBuildTimestamp) {
|
||||
const endTime = Date.now();
|
||||
devServer.output.log(
|
||||
`Built ${match.use}:${entrypoint} [${ms(endTime - startTime)}]`
|
||||
`Built ${use}:${entrypoint} [${ms(endTime - startTime)}]`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -405,6 +401,8 @@ export async function getBuildMatches(
|
||||
|
||||
const noMatches: Builder[] = [];
|
||||
const builds = vercelConfig.builds || [{ src: '**', use: '@vercel/static' }];
|
||||
const builderSpecs = new Set(builds.map(b => b.use).filter(Boolean));
|
||||
const buildersWithPkgs = await importBuilders(builderSpecs, cwd, output);
|
||||
|
||||
for (const buildConfig of builds) {
|
||||
let { src = '**', use, config = {} } = buildConfig;
|
||||
@@ -439,6 +437,8 @@ export async function getBuildMatches(
|
||||
for (const file of files) {
|
||||
src = relative(cwd, file);
|
||||
|
||||
const entrypoint = mapToEntrypoint.get(src) || src;
|
||||
|
||||
// Remove the output directory prefix
|
||||
if (config.zeroConfig && config.outputDirectory) {
|
||||
const outputMatch = config.outputDirectory + '/';
|
||||
@@ -447,11 +447,15 @@ export async function getBuildMatches(
|
||||
}
|
||||
}
|
||||
|
||||
const builderWithPkg = await getBuilder(use, output);
|
||||
const builderWithPkg = buildersWithPkgs.get(use);
|
||||
if (!builderWithPkg) {
|
||||
throw new Error(`Failed to load Builder "${use}"`);
|
||||
}
|
||||
|
||||
matches.push({
|
||||
...buildConfig,
|
||||
src,
|
||||
entrypoint: mapToEntrypoint.get(src) || src,
|
||||
entrypoint,
|
||||
builderWithPkg,
|
||||
buildOutput: {},
|
||||
buildResults: new Map(),
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import { parse } from 'url';
|
||||
import { ListenSpec } from './types';
|
||||
|
||||
export default function parseListen(
|
||||
str: string,
|
||||
defaultPort = 3000
|
||||
): ListenSpec {
|
||||
export function parseListen(str: string, defaultPort = 3000): ListenSpec {
|
||||
let port = Number(str);
|
||||
|
||||
if (!isNaN(port)) {
|
||||
@@ -50,3 +47,7 @@ export default function parseListen(
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function replaceLocalhost(address: string): string {
|
||||
return address.replace('[::]', 'localhost').replace('0.0.0.0', 'localhost');
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import ms from 'ms';
|
||||
import url, { URL } from 'url';
|
||||
import http from 'http';
|
||||
import fs from 'fs-extra';
|
||||
@@ -62,11 +61,6 @@ import { devRouter, getRoutesTypes } from './router';
|
||||
import getMimeType from './mime-type';
|
||||
import { executeBuild, getBuildMatches, shutdownBuilder } from './builder';
|
||||
import { generateErrorMessage, generateHttpStatusDescription } from './errors';
|
||||
import {
|
||||
installBuilders,
|
||||
updateBuilders,
|
||||
builderDirPromise,
|
||||
} from './builder-cache';
|
||||
|
||||
// HTML templates
|
||||
import errorTemplate from './templates/error';
|
||||
@@ -101,7 +95,9 @@ import {
|
||||
isError,
|
||||
isSpawnError,
|
||||
} from '../is-error';
|
||||
import isURL from './is-url';
|
||||
import { pickOverrides } from '../projects/project-settings';
|
||||
import { replaceLocalhost } from './parse-listen';
|
||||
|
||||
const frontendRuntimeSet = new Set(
|
||||
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
|
||||
@@ -134,9 +130,18 @@ export default class DevServer {
|
||||
public proxy: httpProxy;
|
||||
public envConfigs: EnvConfigs;
|
||||
public files: BuilderInputs;
|
||||
public address: string;
|
||||
public devCacheDir: string;
|
||||
|
||||
private _address: URL | undefined;
|
||||
public get address(): URL {
|
||||
if (!this._address) {
|
||||
throw new Error(
|
||||
'Invalid access to `address` because `start` has not yet populated `this.address`.'
|
||||
);
|
||||
}
|
||||
return this._address;
|
||||
}
|
||||
|
||||
public devCacheDir: string;
|
||||
private currentDevCommand?: string;
|
||||
private caseSensitive: boolean;
|
||||
private apiDir: string | null;
|
||||
@@ -152,7 +157,7 @@ export default class DevServer {
|
||||
private filter: (path: string) => boolean;
|
||||
private podId: string;
|
||||
private devProcess?: ChildProcess;
|
||||
private devProcessPort?: number;
|
||||
private devProcessOrigin?: string;
|
||||
private devServerPids: Set<number>;
|
||||
private originalProjectSettings?: ProjectSettings;
|
||||
private projectSettings?: ProjectSettings;
|
||||
@@ -160,8 +165,6 @@ export default class DevServer {
|
||||
private vercelConfigWarning: boolean;
|
||||
private getVercelConfigPromise: Promise<VercelConfig> | null;
|
||||
private blockingBuildsPromise: Promise<void> | null;
|
||||
private updateBuildersPromise: Promise<void> | null;
|
||||
private updateBuildersTimeout: NodeJS.Timeout | undefined;
|
||||
private startPromise: Promise<void> | null;
|
||||
|
||||
private systemEnvValues: string[];
|
||||
@@ -174,17 +177,22 @@ export default class DevServer {
|
||||
this.systemEnvValues = options.systemEnvValues || [];
|
||||
this.projectEnvs = options.projectEnvs || [];
|
||||
this.files = {};
|
||||
this.address = '';
|
||||
this.originalProjectSettings = options.projectSettings;
|
||||
this.projectSettings = options.projectSettings;
|
||||
this.caseSensitive = false;
|
||||
this.apiDir = null;
|
||||
this.apiExtensions = new Set();
|
||||
|
||||
this.proxy = httpProxy.createProxyServer({
|
||||
changeOrigin: true,
|
||||
ws: true,
|
||||
xfwd: true,
|
||||
});
|
||||
this.proxy.on('proxyRes', proxyRes => {
|
||||
// override "server" header, like production
|
||||
proxyRes.headers['server'] = 'Vercel';
|
||||
});
|
||||
|
||||
this.server = http.createServer(this.devServerHandler);
|
||||
this.server.timeout = 0; // Disable timeout
|
||||
this.stopping = false;
|
||||
@@ -195,7 +203,6 @@ export default class DevServer {
|
||||
this.vercelConfigWarning = false;
|
||||
this.getVercelConfigPromise = null;
|
||||
this.blockingBuildsPromise = null;
|
||||
this.updateBuildersPromise = null;
|
||||
this.startPromise = null;
|
||||
|
||||
this.watchAggregationId = null;
|
||||
@@ -477,33 +484,6 @@ export default class DevServer {
|
||||
);
|
||||
}
|
||||
|
||||
async invalidateBuildMatches(
|
||||
vercelConfig: VercelConfig,
|
||||
updatedBuilders: string[]
|
||||
): Promise<void> {
|
||||
if (updatedBuilders.length === 0) {
|
||||
this.output.debug('No builders were updated');
|
||||
return;
|
||||
}
|
||||
|
||||
// Delete any build matches that have the old builder required already
|
||||
for (const buildMatch of this.buildMatches.values()) {
|
||||
const {
|
||||
src,
|
||||
builderWithPkg: { package: pkg },
|
||||
} = buildMatch;
|
||||
if (isOfficialRuntime('static', pkg.name)) continue;
|
||||
if (pkg.name && updatedBuilders.includes(pkg.name)) {
|
||||
shutdownBuilder(buildMatch, this.output);
|
||||
this.buildMatches.delete(src);
|
||||
this.output.debug(`Invalidated build match for "${src}"`);
|
||||
}
|
||||
}
|
||||
|
||||
// Re-add the build matches that were just removed, but with the new builder
|
||||
await this.updateBuildMatches(vercelConfig);
|
||||
}
|
||||
|
||||
async getLocalEnv(fileName: string, base?: Env): Promise<Env> {
|
||||
// TODO: use the file watcher to only invalidate the env `dotfile`
|
||||
// once a change to the `fileName` occurs
|
||||
@@ -707,7 +687,7 @@ export default class DevServer {
|
||||
this.projectEnvs || [],
|
||||
this.systemEnvValues || [],
|
||||
this.projectSettings?.autoExposeSystemEnvs,
|
||||
new URL(this.address).host
|
||||
this.address.host
|
||||
);
|
||||
|
||||
allEnv = { ...cloudEnv };
|
||||
@@ -842,7 +822,7 @@ export default class DevServer {
|
||||
injectSystemValuesInDotenv(env: Env): Env {
|
||||
for (const name of Object.keys(env)) {
|
||||
if (name === 'VERCEL_URL') {
|
||||
env['VERCEL_URL'] = new URL(this.address).host;
|
||||
env['VERCEL_URL'] = this.address.host;
|
||||
} else if (name === 'VERCEL_REGION') {
|
||||
env['VERCEL_REGION'] = 'dev1';
|
||||
}
|
||||
@@ -915,9 +895,7 @@ export default class DevServer {
|
||||
}
|
||||
}
|
||||
|
||||
this.address = address
|
||||
.replace('[::]', 'localhost')
|
||||
.replace('127.0.0.1', 'localhost');
|
||||
this._address = new URL(replaceLocalhost(address));
|
||||
|
||||
const vercelConfig = await this.getVercelConfig();
|
||||
const devCommandPromise = this.runDevCommand();
|
||||
@@ -934,30 +912,8 @@ export default class DevServer {
|
||||
}
|
||||
}
|
||||
|
||||
const builders = new Set<string>(
|
||||
(vercelConfig.builds || [])
|
||||
.filter((b: Builder) => b.use)
|
||||
.map((b: Builder) => b.use)
|
||||
);
|
||||
|
||||
await installBuilders(builders, this.output);
|
||||
await this.updateBuildMatches(vercelConfig, true);
|
||||
|
||||
// Updating builders happens lazily, and any builders that were updated
|
||||
// get their "build matches" invalidated so that the new version is used.
|
||||
this.updateBuildersTimeout = setTimeout(() => {
|
||||
this.updateBuildersPromise = updateBuilders(builders, this.output)
|
||||
.then(updatedBuilders => {
|
||||
this.updateBuildersPromise = null;
|
||||
this.invalidateBuildMatches(vercelConfig, updatedBuilders);
|
||||
})
|
||||
.catch(err => {
|
||||
this.updateBuildersPromise = null;
|
||||
this.output.prettyError(err);
|
||||
this.output.debug(err.stack);
|
||||
});
|
||||
}, ms('30s'));
|
||||
|
||||
// Builders that do not define a `shouldServe()` function need to be
|
||||
// executed at boot-up time in order to get the initial assets and/or routes
|
||||
// that can be served by the builder.
|
||||
@@ -1007,37 +963,37 @@ export default class DevServer {
|
||||
// Configure the server to forward WebSocket "upgrade" events to the proxy.
|
||||
this.server.on('upgrade', async (req, socket, head) => {
|
||||
await this.startPromise;
|
||||
if (!this.devProcessPort) {
|
||||
if (!this.devProcessOrigin) {
|
||||
this.output.debug(
|
||||
`Detected "upgrade" event, but closing socket because no frontend dev server is running`
|
||||
);
|
||||
socket.destroy();
|
||||
return;
|
||||
}
|
||||
const target = `http://127.0.0.1:${this.devProcessPort}`;
|
||||
const target = this.devProcessOrigin;
|
||||
this.output.debug(`Detected "upgrade" event, proxying to ${target}`);
|
||||
this.proxy.ws(req, socket, head, { target });
|
||||
});
|
||||
|
||||
await devCommandPromise;
|
||||
|
||||
this.output.ready(`Available at ${link(this.address)}`);
|
||||
let addressFormatted = this.address.toString();
|
||||
if (this.address.pathname === '/' && this.address.protocol === 'http:') {
|
||||
// log address without trailing slash to maintain backwards compatibility
|
||||
addressFormatted = addressFormatted.replace(/\/$/, '');
|
||||
}
|
||||
this.output.ready(`Available at ${link(addressFormatted)}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the `vercel dev` server, and cleans up any temporary resources.
|
||||
*/
|
||||
async stop(exitCode?: number): Promise<void> {
|
||||
const { devProcess } = this;
|
||||
const { debug } = this.output;
|
||||
if (this.stopping) return;
|
||||
|
||||
this.stopping = true;
|
||||
|
||||
if (typeof this.updateBuildersTimeout !== 'undefined') {
|
||||
clearTimeout(this.updateBuildersTimeout);
|
||||
}
|
||||
|
||||
const { devProcess } = this;
|
||||
const { debug } = this.output;
|
||||
const ops: Promise<any>[] = [];
|
||||
|
||||
for (const match of this.buildMatches.values()) {
|
||||
@@ -1055,18 +1011,10 @@ export default class DevServer {
|
||||
ops.push(this.watcher.close());
|
||||
}
|
||||
|
||||
if (this.updateBuildersPromise) {
|
||||
debug(`Waiting for builders update to complete`);
|
||||
ops.push(this.updateBuildersPromise);
|
||||
}
|
||||
|
||||
for (const pid of this.devServerPids) {
|
||||
ops.push(this.killBuilderDevServer(pid));
|
||||
}
|
||||
|
||||
// Ensure that the builders module cache is created
|
||||
ops.push(builderDirPromise);
|
||||
|
||||
try {
|
||||
await Promise.all(ops);
|
||||
} catch (err: unknown) {
|
||||
@@ -1465,8 +1413,9 @@ export default class DevServer {
|
||||
// the middleware server for every HTTP request?
|
||||
const { envConfigs, files, devCacheDir, cwd: workPath } = this;
|
||||
try {
|
||||
startMiddlewareResult =
|
||||
await middleware.builderWithPkg.builder.startDevServer?.({
|
||||
const { builder } = middleware.builderWithPkg;
|
||||
if (builder.version === 3) {
|
||||
startMiddlewareResult = await builder.startDevServer?.({
|
||||
files,
|
||||
entrypoint: middleware.entrypoint,
|
||||
workPath,
|
||||
@@ -1480,6 +1429,7 @@ export default class DevServer {
|
||||
buildEnv: { ...envConfigs.buildEnv },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (startMiddlewareResult) {
|
||||
const { port, pid } = startMiddlewareResult;
|
||||
@@ -1560,15 +1510,34 @@ export default class DevServer {
|
||||
}
|
||||
|
||||
if (rewritePath) {
|
||||
// TODO: add validation?
|
||||
debug(`Detected rewrite path from middleware: "${rewritePath}"`);
|
||||
prevUrl = rewritePath;
|
||||
|
||||
// Retain orginal pathname, but override query parameters from the rewrite
|
||||
const beforeRewriteUrl = req.url || '/';
|
||||
const rewriteUrlParsed = url.parse(beforeRewriteUrl);
|
||||
rewriteUrlParsed.search = url.parse(rewritePath).search;
|
||||
req.url = url.format(rewriteUrlParsed);
|
||||
|
||||
if (isURL(rewritePath)) {
|
||||
const rewriteUrlParsed = new URL(rewritePath);
|
||||
|
||||
// `this.address` already has localhost normalized from ip4 and ip6 values
|
||||
if (this.address.origin === rewriteUrlParsed.origin) {
|
||||
// remove origin, leaving the path
|
||||
req.url =
|
||||
rewritePath.slice(rewriteUrlParsed.origin.length) || '/';
|
||||
prevUrl = req.url;
|
||||
} else {
|
||||
// Proxy to absolute URL with different origin
|
||||
debug(`ProxyPass: ${rewritePath}`);
|
||||
this.setResponseHeaders(res, requestId);
|
||||
proxyPass(req, res, rewritePath, this, requestId);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Retain orginal pathname, but override query parameters from the rewrite
|
||||
const rewriteUrlParsed = url.parse(beforeRewriteUrl);
|
||||
rewriteUrlParsed.search = url.parse(rewritePath).search;
|
||||
req.url = url.format(rewriteUrlParsed);
|
||||
}
|
||||
|
||||
debug(
|
||||
`Rewrote incoming HTTP URL from "${beforeRewriteUrl}" to "${req.url}"`
|
||||
);
|
||||
@@ -1617,12 +1586,16 @@ export default class DevServer {
|
||||
missRoutes,
|
||||
phase
|
||||
);
|
||||
prevUrl =
|
||||
routeResult.continue && routeResult.dest
|
||||
? getReqUrl(routeResult)
|
||||
: req.url;
|
||||
prevHeaders =
|
||||
routeResult.continue && routeResult.headers ? routeResult.headers : {};
|
||||
|
||||
if (routeResult.continue) {
|
||||
if (routeResult.dest) {
|
||||
prevUrl = getReqUrl(routeResult);
|
||||
}
|
||||
|
||||
if (routeResult.headers) {
|
||||
prevHeaders = routeResult.headers;
|
||||
}
|
||||
}
|
||||
|
||||
if (routeResult.isDestUrl) {
|
||||
// Mix the `routes` result dest query params into the req path
|
||||
@@ -1795,8 +1768,8 @@ export default class DevServer {
|
||||
|
||||
if (!match) {
|
||||
// If the dev command is started, then proxy to it
|
||||
if (this.devProcessPort) {
|
||||
const upstream = `http://127.0.0.1:${this.devProcessPort}`;
|
||||
if (this.devProcessOrigin) {
|
||||
const upstream = this.devProcessOrigin;
|
||||
debug(`Proxying to frontend dev server: ${upstream}`);
|
||||
|
||||
// Add the Vercel platform proxy request headers
|
||||
@@ -1869,8 +1842,8 @@ export default class DevServer {
|
||||
// up a single-serve dev HTTP server that vercel dev will proxy this HTTP request
|
||||
// to. Once the proxied request is finished, vercel dev shuts down the dev
|
||||
// server child process.
|
||||
const { builder, package: builderPkg } = match.builderWithPkg;
|
||||
if (typeof builder.startDevServer === 'function') {
|
||||
const { builder, pkg: builderPkg } = match.builderWithPkg;
|
||||
if (builder.version === 3 && typeof builder.startDevServer === 'function') {
|
||||
let devServerResult: StartDevServerResult = null;
|
||||
try {
|
||||
const { envConfigs, files, devCacheDir, cwd: workPath } = this;
|
||||
@@ -1975,7 +1948,7 @@ export default class DevServer {
|
||||
// - when there is no asset
|
||||
// - when the asset is not a Lambda (the dev server must take care of all static files)
|
||||
if (
|
||||
this.devProcessPort &&
|
||||
this.devProcessOrigin &&
|
||||
(!foundAsset || (foundAsset && foundAsset.asset.type !== 'Lambda'))
|
||||
) {
|
||||
debug('Proxying to frontend dev server');
|
||||
@@ -1987,14 +1960,7 @@ export default class DevServer {
|
||||
}
|
||||
|
||||
this.setResponseHeaders(res, requestId);
|
||||
return proxyPass(
|
||||
req,
|
||||
res,
|
||||
`http://127.0.0.1:${this.devProcessPort}`,
|
||||
this,
|
||||
requestId,
|
||||
false
|
||||
);
|
||||
return proxyPass(req, res, this.devProcessOrigin, this, requestId, false);
|
||||
}
|
||||
|
||||
if (!foundAsset) {
|
||||
@@ -2301,7 +2267,6 @@ export default class DevServer {
|
||||
|
||||
this.output.debug(`Spawning dev command: ${command}`);
|
||||
|
||||
const devPort = new URL(this.address).port;
|
||||
const proxyPort = new RegExp(port.toString(), 'g');
|
||||
const p = spawnCommand(command, {
|
||||
stdio: ['inherit', 'pipe', 'pipe'],
|
||||
@@ -2318,17 +2283,16 @@ export default class DevServer {
|
||||
p.stdout.setEncoding('utf8');
|
||||
|
||||
p.stdout.on('data', (data: string) => {
|
||||
process.stdout.write(data.replace(proxyPort, devPort));
|
||||
process.stdout.write(data.replace(proxyPort, this.address.port));
|
||||
});
|
||||
|
||||
p.on('exit', (code, signal) => {
|
||||
this.output.debug(`Dev command exited with "${signal || code}"`);
|
||||
this.devProcessPort = undefined;
|
||||
this.devProcessOrigin = undefined;
|
||||
});
|
||||
|
||||
await checkForPort(port, 1000 * 60 * 5);
|
||||
|
||||
this.devProcessPort = port;
|
||||
const devProcessHost = await checkForPort(port, 1000 * 60 * 5);
|
||||
this.devProcessOrigin = `http://${devProcessHost}:${port}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2616,15 +2580,29 @@ function needsBlockingBuild(buildMatch: BuildMatch): boolean {
|
||||
return typeof builder.shouldServe !== 'function';
|
||||
}
|
||||
|
||||
async function checkForPort(port: number, timeout: number): Promise<void> {
|
||||
const opts = { host: '127.0.0.1' };
|
||||
async function checkForPort(port: number, timeout: number): Promise<string> {
|
||||
let host;
|
||||
const start = Date.now();
|
||||
while (!(await isPortReachable(port, opts))) {
|
||||
while (!(host = await getReachableHostOnPort(port))) {
|
||||
if (Date.now() - start > timeout) {
|
||||
throw new Error(`Detecting port ${port} timed out after ${timeout}ms`);
|
||||
break;
|
||||
}
|
||||
await sleep(100);
|
||||
}
|
||||
if (!host) {
|
||||
throw new Error(`Detecting port ${port} timed out after ${timeout}ms`);
|
||||
}
|
||||
return host;
|
||||
}
|
||||
|
||||
async function getReachableHostOnPort(port: number): Promise<string | false> {
|
||||
const optsIpv4 = { host: '127.0.0.1' };
|
||||
const optsIpv6 = { host: '::1' };
|
||||
const results = await Promise.all([
|
||||
isPortReachable(port, optsIpv6).then(r => r && `[${optsIpv6.host}]`),
|
||||
isPortReachable(port, optsIpv4).then(r => r && optsIpv4.host),
|
||||
]);
|
||||
return results.find(Boolean) || false;
|
||||
}
|
||||
|
||||
function filterFrontendBuilds(build: Builder) {
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import {
|
||||
FileFsRef,
|
||||
BuildOptions,
|
||||
shouldServe as defaultShouldServe,
|
||||
ShouldServeOptions,
|
||||
} from '@vercel/build-utils';
|
||||
import { BuildResult } from './types';
|
||||
|
||||
export const version = 2;
|
||||
|
||||
export function build({
|
||||
files,
|
||||
entrypoint,
|
||||
config: { zeroConfig, outputDirectory },
|
||||
}: BuildOptions): BuildResult {
|
||||
const path =
|
||||
zeroConfig && outputDirectory
|
||||
? `${outputDirectory}/${entrypoint}`
|
||||
: entrypoint;
|
||||
return {
|
||||
output: {
|
||||
[entrypoint]: files[path] as FileFsRef,
|
||||
},
|
||||
routes: [],
|
||||
watch: [path],
|
||||
};
|
||||
}
|
||||
|
||||
export function shouldServe(_opts: ShouldServeOptions) {
|
||||
const opts = { ..._opts };
|
||||
let {
|
||||
config: { zeroConfig, outputDirectory },
|
||||
} = opts;
|
||||
|
||||
// Add the output directory prefix
|
||||
if (zeroConfig && outputDirectory) {
|
||||
opts.entrypoint = `${outputDirectory}/${opts.entrypoint}`;
|
||||
opts.requestPath = `${outputDirectory}/${opts.requestPath}`;
|
||||
}
|
||||
|
||||
return defaultShouldServe(opts);
|
||||
}
|
||||
@@ -12,12 +12,12 @@ import {
|
||||
FileBlob,
|
||||
FileFsRef,
|
||||
Lambda,
|
||||
PackageJson,
|
||||
} from '@vercel/build-utils';
|
||||
import { VercelConfig } from '@vercel/client';
|
||||
import { HandleValue, Route } from '@vercel/routing-utils';
|
||||
import { Output } from '../output';
|
||||
import { ProjectEnvVariable, ProjectSettings } from '../../types';
|
||||
import { BuilderWithPkg } from '../build/import-builders';
|
||||
|
||||
export { VercelConfig };
|
||||
|
||||
@@ -48,7 +48,7 @@ export interface EnvConfigs {
|
||||
export interface BuildMatch extends BuildConfig {
|
||||
entrypoint: string;
|
||||
src: string;
|
||||
builderWithPkg: BuilderWithPackage;
|
||||
builderWithPkg: BuilderWithPkg;
|
||||
buildOutput: BuilderOutputs;
|
||||
buildResults: Map<string | null, BuildResult>;
|
||||
buildTimestamp: number;
|
||||
@@ -122,13 +122,6 @@ export interface BuildResultV4 {
|
||||
distPath?: string;
|
||||
}
|
||||
|
||||
export interface BuilderWithPackage {
|
||||
runInProcess?: boolean;
|
||||
requirePath: string;
|
||||
builder: Readonly<Builder>;
|
||||
package: Readonly<PackageJson>;
|
||||
}
|
||||
|
||||
export interface HttpHeadersConfig {
|
||||
[name: string]: string;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
export const config = {
|
||||
runtime: 'experimental-edge',
|
||||
};
|
||||
|
||||
export default async function edge(request: Request, event: Event) {
|
||||
return new Response('heyo');
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<h1>Hello from Index</h1>
|
||||
@@ -0,0 +1,21 @@
|
||||
export const config = {
|
||||
runtime: 'experimental-edge',
|
||||
};
|
||||
|
||||
export default async function edge(request: Request, event: Event) {
|
||||
if (request.url.indexOf('/index.html') > -1) {
|
||||
return new Response(null, {
|
||||
headers: {
|
||||
'x-middleware-rewrite': '/does-not-exist.html',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (request.url.indexOf('/api/edge') > -1) {
|
||||
return new Response(null, {
|
||||
headers: {
|
||||
'x-middleware-rewrite': '/api/does-not-exist',
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,15 @@
|
||||
export default req => {
|
||||
const url = new URL(req.url);
|
||||
|
||||
const rewriteTo = url.searchParams.get('to');
|
||||
if (rewriteTo) {
|
||||
return new Response(null, {
|
||||
headers: {
|
||||
'x-middleware-rewrite': rewriteTo,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (url.pathname === '/') {
|
||||
// Pass-through "index.html" page
|
||||
return new Response(null, {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite --port $PORT",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview"
|
||||
},
|
||||
|
||||
3
packages/cli/test/dev/fixtures/vite-dev/vercel.json
Normal file
3
packages/cli/test/dev/fixtures/vite-dev/vercel.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"devCommand": "vite --port $PORT --host ::1"
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import url from 'url';
|
||||
import fs from 'fs-extra';
|
||||
import { join } from 'path';
|
||||
import listen from 'async-listen';
|
||||
import stripAnsi from 'strip-ansi';
|
||||
import { createServer } from 'http';
|
||||
|
||||
const {
|
||||
@@ -723,12 +724,15 @@ test('[vercel dev] should support custom 404 routes', async () => {
|
||||
test('[vercel dev] prints `npm install` errors', async () => {
|
||||
const dir = fixture('runtime-not-installed');
|
||||
const result = await exec(dir);
|
||||
expect(result.stderr.includes('npm ERR! 404')).toBeTruthy();
|
||||
expect(
|
||||
result.stderr.includes('Failed to install `vercel dev` dependencies')
|
||||
stripAnsi(result.stderr).includes(
|
||||
'Error: The package `@vercel/does-not-exist` is not published on the npm registry'
|
||||
)
|
||||
).toBeTruthy();
|
||||
expect(
|
||||
result.stderr.includes('https://vercel.link/npm-install-failed-dev')
|
||||
result.stderr.includes(
|
||||
'https://vercel.link/builder-dependencies-install-failed'
|
||||
)
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
|
||||
@@ -445,11 +445,7 @@ test(
|
||||
test(
|
||||
'[vercel dev] Middleware that has no response',
|
||||
testFixtureStdio('middleware-no-response', async (testPath: any) => {
|
||||
await testPath(
|
||||
500,
|
||||
'/api/hello',
|
||||
'A server error has occurred\n\nEDGE_FUNCTION_INVOCATION_FAILED'
|
||||
);
|
||||
await testPath(200, '/api/hello', 'hello from a serverless function');
|
||||
})
|
||||
);
|
||||
|
||||
@@ -461,9 +457,42 @@ test(
|
||||
await testPath(200, '/another', '<h1>Another</h1>');
|
||||
await testPath(200, '/another.html', '<h1>Another</h1>');
|
||||
await testPath(200, '/foo', '<h1>Another</h1>');
|
||||
// different origin
|
||||
await testPath(200, '?to=http://example.com', /Example Domain/);
|
||||
})
|
||||
);
|
||||
|
||||
test('[vercel dev] Middleware rewrites with same origin', async () => {
|
||||
const directory = fixture('middleware-rewrite');
|
||||
const { dev, port, readyResolver } = await testFixture(directory);
|
||||
|
||||
try {
|
||||
dev.unref();
|
||||
await readyResolver;
|
||||
|
||||
let response = await fetch(
|
||||
`http://localhost:${port}?to=http://localhost:${port}`
|
||||
);
|
||||
validateResponseHeaders(response);
|
||||
expect(response.status).toBe(200);
|
||||
expect(await response.text()).toMatch(/<h1>Index<\/h1>/);
|
||||
|
||||
response = await fetch(
|
||||
`http://localhost:${port}?to=http://127.0.0.1:${port}`
|
||||
);
|
||||
validateResponseHeaders(response);
|
||||
expect(response.status).toBe(200);
|
||||
expect(await response.text()).toMatch(/<h1>Index<\/h1>/);
|
||||
|
||||
response = await fetch(`http://localhost:${port}?to=http://[::1]:${port}`);
|
||||
validateResponseHeaders(response);
|
||||
expect(response.status).toBe(200);
|
||||
expect(await response.text()).toMatch(/<h1>Index<\/h1>/);
|
||||
} finally {
|
||||
await dev.kill('SIGTERM');
|
||||
}
|
||||
});
|
||||
|
||||
test(
|
||||
'[vercel dev] Middleware that rewrites with custom query params',
|
||||
testFixtureStdio('middleware-rewrite-query', async (testPath: any) => {
|
||||
@@ -481,6 +510,14 @@ test(
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[vercel dev] Middleware that rewrites to 404s',
|
||||
testFixtureStdio('middleware-rewrite-404', async (testPath: any) => {
|
||||
await testPath(404, '/api/edge', /NOT_FOUND/);
|
||||
await testPath(404, '/index.html', /NOT_FOUND/);
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[vercel dev] Middleware that redirects',
|
||||
testFixtureStdio('middleware-redirect', async (testPath: any) => {
|
||||
|
||||
@@ -13,6 +13,7 @@ const {
|
||||
|
||||
jest.setTimeout(6 * 60 * 1000);
|
||||
|
||||
const isCI = !!process.env.CI;
|
||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||
const isCanary = () => getDistTag(cliVersion) === 'canary';
|
||||
|
||||
@@ -52,7 +53,7 @@ function fetchWithRetry(url, opts = {}) {
|
||||
return res;
|
||||
},
|
||||
{
|
||||
retries: opts.retries || 3,
|
||||
retries: opts.retries ?? 3,
|
||||
factor: 1,
|
||||
}
|
||||
);
|
||||
@@ -150,9 +151,9 @@ async function testPath(
|
||||
fetchOpts = {}
|
||||
) {
|
||||
const opts = {
|
||||
retries: isCI ? 5 : 0,
|
||||
...fetchOpts,
|
||||
redirect: 'manual-dont-change',
|
||||
retries: 5,
|
||||
status,
|
||||
};
|
||||
const url = `${origin}${path}`;
|
||||
@@ -330,7 +331,7 @@ function testFixtureStdio(
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify(projectSettings),
|
||||
retries: 3,
|
||||
retries: isCI ? 3 : 0,
|
||||
status: 200,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -69,7 +69,7 @@ export function useDeploymentMissingProjectSettings() {
|
||||
framework: {
|
||||
name: 'Other',
|
||||
slug: null,
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/other.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/other.svg',
|
||||
description: 'No framework or an unoptimized framework.',
|
||||
settings: {
|
||||
installCommand: {
|
||||
|
||||
@@ -895,6 +895,12 @@ describe('build', () => {
|
||||
});
|
||||
|
||||
it('should apply project settings overrides from "vercel.json"', async () => {
|
||||
if (process.platform === 'win32') {
|
||||
// this test runs a build command with `mkdir -p` which is unsupported on Windows
|
||||
console.log('Skipping test on Windows');
|
||||
return;
|
||||
}
|
||||
|
||||
const cwd = fixture('project-settings-override');
|
||||
const output = join(cwd, '.vercel/output');
|
||||
try {
|
||||
|
||||
@@ -28,24 +28,72 @@ describe('importBuilders()', () => {
|
||||
});
|
||||
|
||||
it('should import 3rd party Builders', async () => {
|
||||
if (process.platform === 'win32') {
|
||||
// this test creates symlinks which require admin by default on Windows
|
||||
console.log('Skipping test on Windows');
|
||||
return;
|
||||
}
|
||||
|
||||
const cwd = await getWriteableDirectory();
|
||||
try {
|
||||
const spec = 'vercel-deno@2.0.1';
|
||||
const specs = new Set([spec]);
|
||||
const tarballSpec = 'https://test2020-h5hdll5dz-tootallnate.vercel.app';
|
||||
const specs = new Set([spec, tarballSpec]);
|
||||
const builders = await importBuilders(specs, cwd, client.output);
|
||||
expect(builders.size).toEqual(1);
|
||||
expect(builders.size).toEqual(2);
|
||||
expect(builders.get(spec)?.pkg.name).toEqual('vercel-deno');
|
||||
expect(builders.get(spec)?.pkg.version).toEqual('2.0.1');
|
||||
expect(builders.get(spec)?.pkgPath).toEqual(
|
||||
join(cwd, '.vercel/builders/node_modules/vercel-deno/package.json')
|
||||
);
|
||||
expect(typeof builders.get(spec)?.builder.build).toEqual('function');
|
||||
expect(builders.get(tarballSpec)?.pkg.name).toEqual('vercel-bash');
|
||||
expect(builders.get(tarballSpec)?.pkg.version).toEqual('4.1.0');
|
||||
expect(builders.get(tarballSpec)?.pkgPath).toEqual(
|
||||
join(cwd, '.vercel/builders/node_modules/vercel-bash/package.json')
|
||||
);
|
||||
expect(typeof builders.get(tarballSpec)?.builder.build).toEqual(
|
||||
'function'
|
||||
);
|
||||
await expect(client.stderr).toOutput(
|
||||
'> Installing Builders: vercel-deno@2.0.1, https://test2020-h5hdll5dz-tootallnate.vercel.app'
|
||||
);
|
||||
} finally {
|
||||
await remove(cwd);
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw when importing a Builder that is not on npm registry', async () => {
|
||||
let err: Error | undefined;
|
||||
const cwd = await getWriteableDirectory();
|
||||
try {
|
||||
const spec = '@vercel/does-not-exist@0.0.1';
|
||||
const specs = new Set([spec]);
|
||||
await importBuilders(specs, cwd, client.output);
|
||||
} catch (_err) {
|
||||
err = _err;
|
||||
} finally {
|
||||
await remove(cwd);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
throw new Error('Expected `err` to be defined');
|
||||
}
|
||||
|
||||
expect(err.message).toEqual(
|
||||
'The package `@vercel/does-not-exist` is not published on the npm registry'
|
||||
);
|
||||
expect((err as any).link).toEqual(
|
||||
'https://vercel.link/builder-dependencies-install-failed'
|
||||
);
|
||||
});
|
||||
|
||||
it('should import legacy `@now/build-utils` Builders', async () => {
|
||||
if (process.platform === 'win32') {
|
||||
// this test creates symlinks which require admin by default on Windows
|
||||
console.log('Skipping test on Windows');
|
||||
return;
|
||||
}
|
||||
|
||||
const cwd = await getWriteableDirectory();
|
||||
try {
|
||||
const spec = '@frontity/now@1.2.0';
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
import npa from 'npm-package-arg';
|
||||
import {
|
||||
filterPackage,
|
||||
getBuildUtils,
|
||||
isBundledBuilder,
|
||||
} from '../../../../src/util/dev/builder-cache';
|
||||
|
||||
describe('filterPackage', () => {
|
||||
const cliPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': '0.0.1',
|
||||
},
|
||||
};
|
||||
|
||||
it('should filter package that does not appear in CLI package.json', () => {
|
||||
const result = filterPackage('@vercel/other', {}, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should not filter "latest", cached canary', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': '0.0.1-canary.0',
|
||||
},
|
||||
};
|
||||
const result = filterPackage('@vercel/build-utils', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should filter install "canary", cached stable', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': '0.0.1',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'@vercel/build-utils@canary',
|
||||
buildersPkg,
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should filter install "latest", cached stable', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': '0.0.1',
|
||||
},
|
||||
};
|
||||
const result = filterPackage('@vercel/build-utils', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should filter install "canary", cached canary', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': '0.0.1-canary.0',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'@vercel/build-utils@canary',
|
||||
buildersPkg,
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should filter install URL, cached stable', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': '0.0.1',
|
||||
},
|
||||
};
|
||||
const result = filterPackage('https://tarball.now.sh', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should filter install URL, cached canary', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': '0.0.1-canary.0',
|
||||
},
|
||||
};
|
||||
const result = filterPackage('https://tarball.now.sh', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should filter install "latest", cached URL - canary', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'@vercel/build-utils': 'https://tarball.now.sh',
|
||||
},
|
||||
};
|
||||
const result = filterPackage('@vercel/build-utils', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should filter install not bundled version, cached same version', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'not-bundled-package': '0.0.1',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'not-bundled-package@0.0.1',
|
||||
buildersPkg,
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should filter install not bundled version, cached different version', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'not-bundled-package': '0.0.9',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'not-bundled-package@0.0.1',
|
||||
buildersPkg,
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should filter install not bundled stable, cached version', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'not-bundled-package': '0.0.1',
|
||||
},
|
||||
};
|
||||
const result = filterPackage('not-bundled-package', buildersPkg, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should filter install not bundled tagged, cached tagged', () => {
|
||||
const buildersPkg = {
|
||||
dependencies: {
|
||||
'not-bundled-package': '16.9.0-alpha.0',
|
||||
},
|
||||
};
|
||||
const result = filterPackage(
|
||||
'not-bundled-package@alpha',
|
||||
buildersPkg,
|
||||
cliPkg
|
||||
);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBuildUtils', () => {
|
||||
const tests: [string[], string][] = [
|
||||
[['@vercel/static', '@vercel/node@canary'], 'canary'],
|
||||
[['@vercel/static', '@vercel/node@0.7.4-canary.0'], 'canary'],
|
||||
[['@vercel/static', '@vercel/node@0.8.0'], 'latest'],
|
||||
[['@vercel/static', '@vercel/node'], 'latest'],
|
||||
[['@vercel/static'], 'latest'],
|
||||
[['@vercel/md@canary'], 'canary'],
|
||||
[['custom-builder'], 'latest'],
|
||||
[['custom-builder@canary'], 'canary'],
|
||||
[['canary-bird'], 'latest'],
|
||||
[['canary-bird@4.0.0'], 'latest'],
|
||||
[['canary-bird@canary'], 'canary'],
|
||||
[['@canary/bird'], 'latest'],
|
||||
[['@canary/bird@0.1.0'], 'latest'],
|
||||
[['@canary/bird@canary'], 'canary'],
|
||||
[['https://example.com'], 'latest'],
|
||||
[[''], 'latest'],
|
||||
];
|
||||
|
||||
for (const [input, expected] of tests) {
|
||||
it(`should install "${expected}" with input ${JSON.stringify(
|
||||
input
|
||||
)}`, () => {
|
||||
const result = getBuildUtils(input);
|
||||
expect(result).toEqual(`@vercel/build-utils@${expected}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('isBundledBuilder', () => {
|
||||
const cliPkg = {
|
||||
dependencies: {
|
||||
'@vercel/node': '0.0.1',
|
||||
},
|
||||
};
|
||||
|
||||
it('should not detect when dependency does not appear in CLI package.json', () => {
|
||||
const parsed = npa('@vercel/node');
|
||||
const result = isBundledBuilder(parsed, {});
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should detect "canary" tagged releases', () => {
|
||||
const parsed = npa('@vercel/node@canary');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should detect "canary" versioned releases', () => {
|
||||
const parsed = npa('@vercel/node@1.6.1-canary.0');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should detect latest releases', () => {
|
||||
const parsed = npa('@vercel/node');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should detect "latest" tagged releases', () => {
|
||||
const parsed = npa('@vercel/node@latest');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should detect versioned releases', () => {
|
||||
const parsed = npa('@vercel/node@1.6.1');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should NOT detect URL releases', () => {
|
||||
const parsed = npa('https://example.com');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should NOT detect git url releases', () => {
|
||||
const parsed = npa('git://example.com/repo.git');
|
||||
const result = isBundledBuilder(parsed, cliPkg);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,7 @@
|
||||
import parseListen from '../../../../src/util/dev/parse-listen';
|
||||
import {
|
||||
parseListen,
|
||||
replaceLocalhost,
|
||||
} from '../../../../src/util/dev/parse-listen';
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
|
||||
@@ -69,3 +72,15 @@ describe('parseListen', () => {
|
||||
expect(err.message).toEqual('Unknown `--listen` scheme (protocol): bad:');
|
||||
});
|
||||
});
|
||||
|
||||
describe('replaceLocalhost', () => {
|
||||
test.each([
|
||||
{ input: 'http://192.168.0.1:1234', output: 'http://192.168.0.1:1234' },
|
||||
{ input: 'http://127.0.0.1:4000', output: 'http://127.0.0.1:4000' },
|
||||
{ input: 'http://[::1]:3001', output: 'http://[::1]:3001' },
|
||||
{ input: 'http://0.0.0.0:3000', output: 'http://localhost:3000' },
|
||||
{ input: 'http://[::]:3002', output: 'http://localhost:3002' },
|
||||
])('"$input" → "$output"', ({ input, output }) => {
|
||||
expect(replaceLocalhost(input)).toEqual(output);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "12.2.3",
|
||||
"version": "12.2.4",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -43,7 +43,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/routing-utils": "2.0.2",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
|
||||
@@ -1 +1 @@
|
||||
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22.428.013c-.103.01-.431.042-.727.066C14.883.693 8.497 4.37 4.453 10.024A23.754 23.754 0 0 0 .216 20.51C.023 21.828 0 22.217 0 24.005c0 1.787.023 2.177.216 3.495 1.304 9.012 7.718 16.584 16.417 19.39 1.558.501 3.2.844 5.068 1.05.727.08 3.87.08 4.598 0 3.224-.356 5.954-1.154 8.648-2.529.412-.21.492-.267.436-.314-.038-.028-1.797-2.388-3.909-5.24l-3.838-5.184-4.809-7.117c-2.646-3.913-4.824-7.112-4.842-7.112-.019-.005-.038 3.157-.047 7.018-.014 6.76-.019 7.033-.103 7.192-.122.23-.216.324-.413.427-.15.075-.282.09-.99.09h-.812l-.216-.137a.878.878 0 0 1-.314-.342l-.099-.211.01-9.407.014-9.41.145-.184c.075-.098.235-.225.347-.286.193-.094.268-.103 1.08-.103.957 0 1.116.038 1.365.31.07.075 2.674 3.997 5.79 8.721s7.376 11.175 9.469 14.342l3.8 5.756.192-.127c1.704-1.107 3.505-2.683 4.932-4.325a23.888 23.888 0 0 0 5.65-12.268c.192-1.319.215-1.708.215-3.495 0-1.788-.023-2.177-.216-3.495-1.304-9.013-7.718-16.584-16.417-19.39C29.832.623 28.199.28 26.369.074c-.45-.047-3.551-.099-3.94-.061zm9.825 14.515a.947.947 0 0 1 .474.554c.038.122.047 2.73.038 8.608l-.014 8.436-1.488-2.28-1.492-2.28v-6.132c0-3.964.019-6.193.047-6.3a.957.957 0 0 1 .465-.592c.192-.098.262-.108 1-.108.694 0 .816.01.97.094z" fill="#fff"/></svg>
|
||||
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="mask" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="48" height="48"><circle cx="24" cy="24" r="24" fill="#000"/></mask><g mask="url(#mask)"><circle cx="24" cy="24" r="23.2" fill="#000" stroke="#fff" stroke-width="1.6"/><path d="M39.8687 42.0055L18.4378 14.4H14.3999V33.592H17.6302V18.5023L37.333 43.9587C38.222 43.3637 39.069 42.7108 39.8687 42.0055Z" fill="url(#gradient0)"/><rect x="30.6667" y="14.4" width="3.2" height="19.2" fill="url(#gradient1)"/></g><defs><linearGradient id="gradient0" x1="29.0666" y1="31.0667" x2="38.5332" y2="42.8" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="gradient1" x1="32.2667" y1="14.4" x2="32.2132" y2="28.5001" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient></defs></svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 997 B |
@@ -1 +1 @@
|
||||
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22.428.013c-.103.01-.431.042-.727.066C14.883.693 8.497 4.37 4.453 10.024A23.754 23.754 0 0 0 .216 20.51C.023 21.828 0 22.217 0 24.005c0 1.787.023 2.177.216 3.495 1.304 9.012 7.718 16.584 16.417 19.39 1.558.501 3.2.844 5.068 1.05.727.08 3.87.08 4.598 0 3.224-.356 5.954-1.154 8.648-2.529.412-.21.492-.267.436-.314-.038-.028-1.797-2.388-3.909-5.24l-3.838-5.184-4.809-7.117c-2.646-3.913-4.824-7.112-4.842-7.112-.019-.005-.038 3.157-.047 7.018-.014 6.76-.019 7.033-.103 7.192-.122.23-.216.324-.413.427-.15.075-.282.09-.99.09h-.812l-.216-.137a.878.878 0 0 1-.314-.342l-.099-.211.01-9.407.014-9.41.145-.184c.075-.098.235-.225.347-.286.193-.094.268-.103 1.08-.103.957 0 1.116.038 1.365.31.07.075 2.674 3.997 5.79 8.721s7.376 11.175 9.469 14.342l3.8 5.756.192-.127c1.704-1.107 3.505-2.683 4.932-4.325a23.888 23.888 0 0 0 5.65-12.268c.192-1.319.215-1.708.215-3.495 0-1.788-.023-2.177-.216-3.495-1.304-9.013-7.718-16.584-16.417-19.39C29.832.623 28.199.28 26.369.074c-.45-.047-3.551-.099-3.94-.061zm9.825 14.515a.947.947 0 0 1 .474.554c.038.122.047 2.73.038 8.608l-.014 8.436-1.488-2.28-1.492-2.28v-6.132c0-3.964.019-6.193.047-6.3a.957.957 0 0 1 .465-.592c.192-.098.262-.108 1-.108.694 0 .816.01.97.094z" fill="#000"/></svg>
|
||||
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="mask" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="48" height="48"><circle cx="24" cy="24" r="24" fill="#000"/></mask><g mask="url(#mask)"><circle cx="24" cy="24" r="23.2" fill="#000" stroke="#000" stroke-width="1.6"/><path d="M39.8687 42.0055L18.4378 14.4H14.3999V33.592H17.6302V18.5023L37.333 43.9587C38.222 43.3637 39.069 42.7108 39.8687 42.0055Z" fill="url(#gradient0)"/><rect x="30.6667" y="14.4" width="3.2" height="19.2" fill="url(#gradient1)"/></g><defs><linearGradient id="gradient0" x1="29.0666" y1="31.0667" x2="38.5332" y2="42.8" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="gradient1" x1="32.2667" y1="14.4" x2="32.2132" y2="28.5001" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient></defs></svg>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 997 B |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/frameworks",
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.5",
|
||||
"main": "./dist/frameworks.js",
|
||||
"types": "./dist/frameworks.d.ts",
|
||||
"files": [
|
||||
|
||||
@@ -21,7 +21,7 @@ export const frameworks = [
|
||||
name: 'Blitz.js',
|
||||
slug: 'blitzjs',
|
||||
demo: 'https://blitz-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/blitz.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/blitz.svg',
|
||||
tagline: 'Blitz.js: The Fullstack React Framework',
|
||||
description:
|
||||
'A brand new Blitz.js app - the result of running `npx blitz new`.',
|
||||
@@ -58,9 +58,9 @@ export const frameworks = [
|
||||
name: 'Next.js',
|
||||
slug: 'nextjs',
|
||||
demo: 'https://nextjs-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/next.svg',
|
||||
darkModeLogo:
|
||||
'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next-dark.svg',
|
||||
'https://api-frameworks.vercel.sh/framework-logos/next-dark.svg',
|
||||
screenshot:
|
||||
'https://assets.vercel.com/image/upload/v1647366075/front/import/nextjs.png',
|
||||
tagline:
|
||||
@@ -108,7 +108,7 @@ export const frameworks = [
|
||||
name: 'Gatsby.js',
|
||||
slug: 'gatsby',
|
||||
demo: 'https://gatsby.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/gatsby.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/gatsby.svg',
|
||||
tagline:
|
||||
'Gatsby helps developers build blazing fast websites and apps with React.',
|
||||
description: 'A Gatsby starter app with an API Route.',
|
||||
@@ -195,7 +195,7 @@ export const frameworks = [
|
||||
name: 'Remix',
|
||||
slug: 'remix',
|
||||
demo: 'https://remix-run-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/remix-no-shadow.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/remix-no-shadow.svg',
|
||||
tagline: 'Build Better Websites',
|
||||
description: 'A new Remix app — the result of running `npx create-remix`.',
|
||||
website: 'https://remix.run',
|
||||
@@ -232,9 +232,9 @@ export const frameworks = [
|
||||
name: 'Astro',
|
||||
slug: 'astro',
|
||||
demo: 'https://astro-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/astro.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/astro.svg',
|
||||
darkModeLogo:
|
||||
'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/astro-dark.svg',
|
||||
'https://api-frameworks.vercel.sh/framework-logos/astro-dark.svg',
|
||||
tagline:
|
||||
'Astro is a new kind of static site builder for the modern web. Powerful developer experience meets lightweight output.',
|
||||
description: 'An Astro site, using the basics starter kit.',
|
||||
@@ -286,7 +286,7 @@ export const frameworks = [
|
||||
name: 'Hexo',
|
||||
slug: 'hexo',
|
||||
demo: 'https://hexo-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/hexo.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/hexo.svg',
|
||||
tagline:
|
||||
'Hexo is a fast, simple & powerful blog framework powered by Node.js.',
|
||||
description: 'A Hexo site, created with the Hexo CLI.',
|
||||
@@ -323,7 +323,7 @@ export const frameworks = [
|
||||
name: 'Eleventy',
|
||||
slug: 'eleventy',
|
||||
demo: 'https://eleventy-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/eleventy.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/eleventy.svg',
|
||||
tagline:
|
||||
'11ty is a simpler static site generator written in JavaScript, created to be an alternative to Jekyll.',
|
||||
description: 'An Eleventy site, created with npm init.',
|
||||
@@ -361,7 +361,7 @@ export const frameworks = [
|
||||
name: 'Docusaurus 2',
|
||||
slug: 'docusaurus-2',
|
||||
demo: 'https://docusaurus-2-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/docusaurus.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/docusaurus.svg',
|
||||
tagline:
|
||||
'Docusaurus makes it easy to maintain Open Source documentation websites.',
|
||||
description:
|
||||
@@ -449,7 +449,7 @@ export const frameworks = [
|
||||
name: 'Docusaurus 1',
|
||||
slug: 'docusaurus',
|
||||
demo: 'https://docusaurus-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/docusaurus.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/docusaurus.svg',
|
||||
tagline:
|
||||
'Docusaurus makes it easy to maintain Open Source documentation websites.',
|
||||
description:
|
||||
@@ -501,7 +501,7 @@ export const frameworks = [
|
||||
name: 'Preact',
|
||||
slug: 'preact',
|
||||
demo: 'https://preact-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/preact.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/preact.svg',
|
||||
tagline:
|
||||
'Preact is a fast 3kB alternative to React with the same modern API.',
|
||||
description: 'A Preact app, created with the Preact CLI.',
|
||||
@@ -547,7 +547,7 @@ export const frameworks = [
|
||||
name: 'SolidStart',
|
||||
slug: 'solidstart',
|
||||
demo: 'https://solid-start-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/solid.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/solid.svg',
|
||||
tagline: 'Simple and performant reactivity for building user interfaces.',
|
||||
description: 'A Solid app, created with SolidStart.',
|
||||
website: 'https://solidjs.com',
|
||||
@@ -587,7 +587,7 @@ export const frameworks = [
|
||||
name: 'Dojo',
|
||||
slug: 'dojo',
|
||||
demo: 'https://dojo-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/dojo.png',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/dojo.png',
|
||||
tagline: 'Dojo is a modern progressive, TypeScript first framework.',
|
||||
description:
|
||||
"A Dojo app, created with the Dojo CLI's cli-create-app command.",
|
||||
@@ -649,7 +649,7 @@ export const frameworks = [
|
||||
name: 'Ember.js',
|
||||
slug: 'ember',
|
||||
demo: 'https://ember-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/ember.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/ember.svg',
|
||||
tagline:
|
||||
'Ember.js helps webapp developers be more productive out of the box.',
|
||||
description: 'An Ember app, created with the Ember CLI.',
|
||||
@@ -695,7 +695,7 @@ export const frameworks = [
|
||||
name: 'Vue.js',
|
||||
slug: 'vue',
|
||||
demo: 'https://vue-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/vue.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/vue.svg',
|
||||
tagline:
|
||||
'Vue.js is a versatile JavaScript framework that is as approachable as it is performant.',
|
||||
description: 'A Vue.js app, created with the Vue CLI.',
|
||||
@@ -752,7 +752,7 @@ export const frameworks = [
|
||||
name: 'Scully',
|
||||
slug: 'scully',
|
||||
demo: 'https://scully-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/scullyio-logo.png',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/scullyio-logo.png',
|
||||
tagline: 'Scully is a static site generator for Angular.',
|
||||
description: 'The Static Site Generator for Angular apps.',
|
||||
website: 'https://github.com/scullyio/scully',
|
||||
@@ -788,7 +788,7 @@ export const frameworks = [
|
||||
name: 'Ionic Angular',
|
||||
slug: 'ionic-angular',
|
||||
demo: 'https://ionic-angular-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/ionic.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/ionic.svg',
|
||||
tagline:
|
||||
'Ionic Angular allows you to build mobile PWAs with Angular and the Ionic Framework.',
|
||||
description: 'An Ionic Angular site, created with the Ionic CLI.',
|
||||
@@ -833,7 +833,7 @@ export const frameworks = [
|
||||
name: 'Angular',
|
||||
slug: 'angular',
|
||||
demo: 'https://angular-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/angular.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/angular.svg',
|
||||
tagline:
|
||||
'Angular is a TypeScript-based cross-platform framework from Google.',
|
||||
description: 'An Angular app, created with the Angular CLI.',
|
||||
@@ -893,7 +893,7 @@ export const frameworks = [
|
||||
name: 'Polymer',
|
||||
slug: 'polymer',
|
||||
demo: 'https://polymer-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/polymer.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/polymer.svg',
|
||||
tagline:
|
||||
'Polymer is an open-source webapps library from Google, for building using Web Components.',
|
||||
description: 'A Polymer app, created with the Polymer CLI.',
|
||||
@@ -950,7 +950,7 @@ export const frameworks = [
|
||||
name: 'Svelte',
|
||||
slug: 'svelte',
|
||||
demo: 'https://svelte.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/svelte.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/svelte.svg',
|
||||
tagline:
|
||||
'Svelte lets you write high performance reactive apps with significantly less boilerplate.',
|
||||
description: 'A basic Svelte app using the default template.',
|
||||
@@ -1001,7 +1001,7 @@ export const frameworks = [
|
||||
name: 'SvelteKit',
|
||||
slug: 'sveltekit',
|
||||
demo: 'https://sveltekit-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/svelte.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/svelte.svg',
|
||||
screenshot:
|
||||
'https://assets.vercel.com/image/upload/v1647366075/front/import/sveltekit.png',
|
||||
tagline:
|
||||
@@ -1040,7 +1040,7 @@ export const frameworks = [
|
||||
name: 'Ionic React',
|
||||
slug: 'ionic-react',
|
||||
demo: 'https://ionic-react-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/ionic.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/ionic.svg',
|
||||
tagline:
|
||||
'Ionic React allows you to build mobile PWAs with React and the Ionic Framework.',
|
||||
description: 'An Ionic React site, created with the Ionic CLI.',
|
||||
@@ -1101,7 +1101,7 @@ export const frameworks = [
|
||||
name: 'Create React App',
|
||||
slug: 'create-react-app',
|
||||
demo: 'https://create-react-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/react.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/react.svg',
|
||||
tagline: 'Create React App allows you to get going with React in no time.',
|
||||
description: 'A client-side React app created with create-react-app.',
|
||||
website: 'https://create-react-app.dev',
|
||||
@@ -1168,7 +1168,7 @@ export const frameworks = [
|
||||
name: 'Gridsome',
|
||||
slug: 'gridsome',
|
||||
demo: 'https://gridsome-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/gridsome.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/gridsome.svg',
|
||||
tagline:
|
||||
'Gridsome is a Vue.js-powered framework for building websites & apps that are fast by default.',
|
||||
description: 'A Gridsome app, created with the Gridsome CLI.',
|
||||
@@ -1205,7 +1205,7 @@ export const frameworks = [
|
||||
name: 'UmiJS',
|
||||
slug: 'umijs',
|
||||
demo: 'https://umijs-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/umi.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/umi.svg',
|
||||
tagline:
|
||||
'UmiJS is an extensible enterprise-level React application framework.',
|
||||
description: 'An UmiJS app, created using the Umi CLI.',
|
||||
@@ -1251,7 +1251,7 @@ export const frameworks = [
|
||||
name: 'Sapper',
|
||||
slug: 'sapper',
|
||||
demo: 'https://sapper-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/svelte.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/svelte.svg',
|
||||
tagline:
|
||||
'Sapper is a framework for building high-performance universal web apps with Svelte.',
|
||||
description: 'A Sapper app, using the Sapper template.',
|
||||
@@ -1288,7 +1288,7 @@ export const frameworks = [
|
||||
name: 'Saber',
|
||||
slug: 'saber',
|
||||
demo: 'https://saber-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/saber.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/saber.svg',
|
||||
tagline:
|
||||
'Saber is a framework for building static sites in Vue.js that supports data from any source.',
|
||||
description: 'A Saber site, created with npm init.',
|
||||
@@ -1339,7 +1339,7 @@ export const frameworks = [
|
||||
name: 'Stencil',
|
||||
slug: 'stencil',
|
||||
demo: 'https://stencil.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/stencil.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/stencil.svg',
|
||||
tagline:
|
||||
'Stencil is a powerful toolchain for building Progressive Web Apps and Design Systems.',
|
||||
description: 'A Stencil site, created with the Stencil CLI.',
|
||||
@@ -1400,7 +1400,7 @@ export const frameworks = [
|
||||
name: 'Nuxt.js',
|
||||
slug: 'nuxtjs',
|
||||
demo: 'https://nuxtjs-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/nuxt.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/nuxt.svg',
|
||||
screenshot:
|
||||
'https://assets.vercel.com/image/upload/v1647366075/front/import/nuxtjs.png',
|
||||
tagline:
|
||||
@@ -1460,7 +1460,7 @@ export const frameworks = [
|
||||
name: 'RedwoodJS',
|
||||
slug: 'redwoodjs',
|
||||
demo: 'https://redwood-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/redwoodjs.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/redwoodjs.svg',
|
||||
tagline: 'RedwoodJS is a full-stack framework for the Jamstack.',
|
||||
description: 'A RedwoodJS app, bootstraped with create-redwood-app.',
|
||||
website: 'https://redwoodjs.com',
|
||||
@@ -1497,7 +1497,7 @@ export const frameworks = [
|
||||
name: 'Hugo',
|
||||
slug: 'hugo',
|
||||
demo: 'https://hugo-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/hugo.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/hugo.svg',
|
||||
tagline:
|
||||
'Hugo is the world’s fastest framework for building websites, written in Go.',
|
||||
description: 'A Hugo site, created with the Hugo CLI.',
|
||||
@@ -1550,7 +1550,7 @@ export const frameworks = [
|
||||
name: 'Jekyll',
|
||||
slug: 'jekyll',
|
||||
demo: 'https://jekyll-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/jekyll.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/jekyll.svg',
|
||||
tagline:
|
||||
'Jekyll makes it super easy to transform your plain text into static websites and blogs.',
|
||||
description: 'A Jekyll site, created with the Jekyll CLI.',
|
||||
@@ -1591,7 +1591,7 @@ export const frameworks = [
|
||||
name: 'Brunch',
|
||||
slug: 'brunch',
|
||||
demo: 'https://brunch-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/brunch.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/brunch.svg',
|
||||
tagline:
|
||||
'Brunch is a fast and simple webapp build tool with seamless incremental compilation for rapid development.',
|
||||
description: 'A Brunch app, created with the Brunch CLI.',
|
||||
@@ -1625,7 +1625,7 @@ export const frameworks = [
|
||||
name: 'Middleman',
|
||||
slug: 'middleman',
|
||||
demo: 'https://middleman-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/middleman.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/middleman.svg',
|
||||
tagline:
|
||||
'Middleman is a static site generator that uses all the shortcuts and tools in modern web development.',
|
||||
description: 'A Middleman app, created with the Middleman CLI.',
|
||||
@@ -1660,7 +1660,7 @@ export const frameworks = [
|
||||
name: 'Zola',
|
||||
slug: 'zola',
|
||||
demo: 'https://zola-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/zola.png',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/zola.png',
|
||||
tagline: 'Everything you need to make a static site engine in one binary.',
|
||||
description: 'A Zola app, created with the "Getting Started" tutorial.',
|
||||
website: 'https://www.getzola.org',
|
||||
@@ -1694,7 +1694,7 @@ export const frameworks = [
|
||||
name: 'Vite',
|
||||
slug: 'vite',
|
||||
demo: 'https://vite-vue-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/vite.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/vite.svg',
|
||||
tagline:
|
||||
'Vite is a new breed of frontend build tool that significantly improves the frontend development experience.',
|
||||
description: 'A Vue.js app, created with Vite.',
|
||||
@@ -1732,7 +1732,7 @@ export const frameworks = [
|
||||
name: 'Parcel',
|
||||
slug: 'parcel',
|
||||
demo: 'https://parcel-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/parcel.png',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/parcel.png',
|
||||
tagline:
|
||||
'Parcel is a zero configuration build tool for the web that scales to projects of any size and complexity.',
|
||||
description: 'A vanilla web app built with Parcel.',
|
||||
@@ -1779,16 +1779,22 @@ export const frameworks = [
|
||||
name: 'Sanity',
|
||||
slug: 'sanity',
|
||||
demo: 'https://sanity-studio-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/sanity.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/sanity.svg',
|
||||
tagline: 'The structured content platform.',
|
||||
description: 'A Sanity Studio',
|
||||
website: 'https://www.sanity.io',
|
||||
envPrefix: 'SANITY_STUDIO_',
|
||||
detectors: {
|
||||
every: [
|
||||
some: [
|
||||
{
|
||||
path: 'sanity.json',
|
||||
},
|
||||
{
|
||||
path: 'sanity.config.js',
|
||||
},
|
||||
{
|
||||
path: 'sanity.config.ts',
|
||||
},
|
||||
],
|
||||
},
|
||||
settings: {
|
||||
@@ -1822,7 +1828,7 @@ export const frameworks = [
|
||||
name: 'Hydrogen',
|
||||
slug: 'hydrogen',
|
||||
demo: 'https://hydrogen-template.vercel.app',
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/hydrogen.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/hydrogen.svg',
|
||||
tagline: 'React framework for headless commerce',
|
||||
description: 'React framework for headless commerce',
|
||||
website: 'https://hydrogen.shopify.dev',
|
||||
@@ -1856,7 +1862,7 @@ export const frameworks = [
|
||||
{
|
||||
name: 'Other',
|
||||
slug: null,
|
||||
logo: 'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/other.svg',
|
||||
logo: 'https://api-frameworks.vercel.sh/framework-logos/other.svg',
|
||||
description: 'No framework or an unoptimized framework.',
|
||||
settings: {
|
||||
installCommand: {
|
||||
|
||||
@@ -53,12 +53,12 @@ export interface Framework {
|
||||
slug: string | null;
|
||||
/**
|
||||
* A URL to the logo of the framework
|
||||
* @example "https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next.svg"
|
||||
* @example "https://api-frameworks.vercel.sh/framework-logos/next.svg"
|
||||
*/
|
||||
logo: string;
|
||||
/**
|
||||
* An additional URL to the logo of the framework optimized for dark mode
|
||||
* @example "https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/next-dark.svg"
|
||||
* @example "https://api-frameworks.vercel.sh/framework-logos/next-dark.svg"
|
||||
*/
|
||||
darkModeLogo?: string;
|
||||
/**
|
||||
|
||||
33
packages/frameworks/test/frameworks.unit.test.ts
vendored
33
packages/frameworks/test/frameworks.unit.test.ts
vendored
@@ -10,6 +10,8 @@ import frameworkList from '../src/frameworks';
|
||||
// bump timeout for Windows as network can be slower
|
||||
jest.setTimeout(15 * 1000);
|
||||
|
||||
const logoPrefix = 'https://api-frameworks.vercel.sh/framework-logos/';
|
||||
|
||||
const SchemaFrameworkDetectionItem = {
|
||||
type: 'array',
|
||||
items: [
|
||||
@@ -172,14 +174,33 @@ describe('frameworks', () => {
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('ensure logo', async () => {
|
||||
it('ensure logo starts with url prefix', async () => {
|
||||
const invalid = frameworkList
|
||||
.map(f => f.logo)
|
||||
.filter(logo => {
|
||||
return logo && !logo.startsWith(logoPrefix);
|
||||
});
|
||||
|
||||
expect(invalid).toEqual([]);
|
||||
});
|
||||
|
||||
it('ensure darkModeLogo starts with url prefix', async () => {
|
||||
const invalid = frameworkList
|
||||
.map(f => f.darkModeLogo)
|
||||
.filter(darkModeLogo => {
|
||||
return darkModeLogo && !darkModeLogo.startsWith(logoPrefix);
|
||||
});
|
||||
|
||||
expect(invalid).toEqual([]);
|
||||
});
|
||||
|
||||
it('ensure logo file exists in ./packages/frameworks/logos/', async () => {
|
||||
const missing = frameworkList
|
||||
.map(f => f.logo)
|
||||
.filter(url => {
|
||||
const prefix =
|
||||
'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/';
|
||||
const name = url.replace(prefix, '');
|
||||
return existsSync(join(__dirname, '..', 'logos', name)) === false;
|
||||
.filter(logo => {
|
||||
const filename = logo.slice(logoPrefix.length);
|
||||
const filepath = join(__dirname, '..', 'logos', filename);
|
||||
return existsSync(filepath) === false;
|
||||
});
|
||||
|
||||
expect(missing).toEqual([]);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/fs-detectors",
|
||||
"version": "2.1.0",
|
||||
"version": "3.2.0",
|
||||
"description": "Vercel filesystem detectors",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -19,7 +19,7 @@
|
||||
"test-unit": "yarn test"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/frameworks": "1.1.3",
|
||||
"@vercel/frameworks": "1.1.5",
|
||||
"@vercel/routing-utils": "2.0.2",
|
||||
"glob": "8.0.3",
|
||||
"js-yaml": "4.1.0",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { posix as posixPath } from 'path';
|
||||
|
||||
export interface Stat {
|
||||
name: string;
|
||||
path: string;
|
||||
@@ -76,12 +78,43 @@ export abstract class DetectorFilesystem {
|
||||
|
||||
/**
|
||||
* Returns a list of Stat objects from the current working directory.
|
||||
* @param dirPath The path of the directory to read.
|
||||
* @param options.potentialFiles optional. Array of potential file names (relative to the path). If provided, these will be used to mark the filesystem caches as existing or not existing.
|
||||
*/
|
||||
public readdir = async (name: string): Promise<Stat[]> => {
|
||||
let p = this.readdirCache.get(name);
|
||||
public readdir = async (
|
||||
dirPath: string,
|
||||
options?: { potentialFiles?: string[] }
|
||||
): Promise<Stat[]> => {
|
||||
let p = this.readdirCache.get(dirPath);
|
||||
if (!p) {
|
||||
p = this._readdir(name);
|
||||
this.readdirCache.set(name, p);
|
||||
p = this._readdir(dirPath);
|
||||
this.readdirCache.set(dirPath, p);
|
||||
|
||||
const directoryContent = await p;
|
||||
const directoryFiles = new Set<string>();
|
||||
|
||||
for (const file of directoryContent) {
|
||||
if (file.type === 'file') {
|
||||
// we know this file exists, mark it as so on the filesystem
|
||||
this.fileCache.set(file.path, Promise.resolve(true));
|
||||
this.pathCache.set(file.path, Promise.resolve(true));
|
||||
directoryFiles.add(file.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (options?.potentialFiles) {
|
||||
// calculate the set of paths that truly do not exist
|
||||
const filesThatDoNotExist = options.potentialFiles.filter(
|
||||
path => !directoryFiles.has(path)
|
||||
);
|
||||
for (const filePath of filesThatDoNotExist) {
|
||||
const fullFilePath =
|
||||
dirPath === '/' ? filePath : posixPath.join(dirPath, filePath);
|
||||
// we know this file does not exist, mark it as so on the filesystem
|
||||
this.fileCache.set(fullFilePath, Promise.resolve(false));
|
||||
this.pathCache.set(fullFilePath, Promise.resolve(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
return p;
|
||||
};
|
||||
@@ -98,10 +131,9 @@ export abstract class DetectorFilesystem {
|
||||
* @param name the name of the file to write
|
||||
* @param content The content of the file
|
||||
*/
|
||||
public writeFile(name: string, content?: string): void {
|
||||
if (content)
|
||||
this.readFileCache.set(name, Promise.resolve(Buffer.from(content)));
|
||||
public writeFile = async (name: string, content: string): Promise<void> => {
|
||||
this.readFileCache.set(name, Promise.resolve(Buffer.from(content)));
|
||||
this.fileCache.set(name, Promise.resolve(true));
|
||||
this.pathCache.set(name, Promise.resolve(true));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -31,6 +31,28 @@ export const monorepoManagers: Array<
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Nx',
|
||||
slug: 'nx',
|
||||
detectors: {
|
||||
every: [
|
||||
{
|
||||
path: 'nx.json',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Rush',
|
||||
slug: 'rush',
|
||||
detectors: {
|
||||
every: [
|
||||
{
|
||||
path: 'rush.json',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export default monorepoManagers;
|
||||
|
||||
@@ -33,6 +33,12 @@ export async function getWorkspacePackagePaths({
|
||||
case 'pnpm':
|
||||
results = await getPnpmWorkspacePackagePaths({ fs: workspaceFs });
|
||||
break;
|
||||
case 'rush':
|
||||
// /common/temp is the location that Rush defaults adding the pnpm workspace file
|
||||
results = await getPnpmWorkspacePackagePaths({
|
||||
fs: fs.chdir('/common/temp'),
|
||||
});
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown workspace implementation: ${type}`);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface GetWorkspaceOptions {
|
||||
cwd?: string;
|
||||
}
|
||||
|
||||
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm';
|
||||
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm' | 'rush';
|
||||
|
||||
export type Workspace = {
|
||||
type: WorkspaceType;
|
||||
|
||||
@@ -59,6 +59,18 @@ export const workspaceManagers: Array<
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'rush',
|
||||
slug: 'rush',
|
||||
detectors: {
|
||||
every: [
|
||||
{
|
||||
path: 'rush.json',
|
||||
matchContent: '"useWorkspaces":\\strue',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'default',
|
||||
slug: 'yarn',
|
||||
|
||||
119
packages/fs-detectors/test/fixtures/39-nx-monorepo/apps/app/project.json
vendored
Normal file
119
packages/fs-detectors/test/fixtures/39-nx-monorepo/apps/app/project.json
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"projectType": "application",
|
||||
"generators": {
|
||||
"@nrwl/workspace:component": {
|
||||
"style": "scss"
|
||||
}
|
||||
},
|
||||
"sourceRoot": "apps/products/src",
|
||||
"prefix": "nx-example",
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"aot": true,
|
||||
"outputPath": "dist/apps/products",
|
||||
"index": "apps/products/src/index.html",
|
||||
"main": "apps/products/src/main.ts",
|
||||
"polyfills": "apps/products/src/polyfills.ts",
|
||||
"tsConfig": "apps/products/tsconfig.app.json",
|
||||
"assets": [
|
||||
"apps/products/src/_redirects",
|
||||
{
|
||||
"input": "libs/shared/assets/src/assets",
|
||||
"glob": "**/*",
|
||||
"output": "assets"
|
||||
},
|
||||
{
|
||||
"input": "libs/shared/assets/src",
|
||||
"glob": "favicon.ico",
|
||||
"output": "."
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"libs/shared/styles/src/index.scss",
|
||||
"libs/shared/header/index.scss",
|
||||
"node_modules/normalize.css/normalize.css"
|
||||
],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "apps/products/src/environments/environment.ts",
|
||||
"with": "apps/products/src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "2mb",
|
||||
"maximumError": "5mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "6kb"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"outputs": ["{options.outputPath}"]
|
||||
},
|
||||
"serve": {
|
||||
"executor": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "products:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "products:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"executor": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "products:build"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"apps/products/src/**/*.ts",
|
||||
"apps/products/src/**/*.html"
|
||||
]
|
||||
},
|
||||
"outputs": ["{options.outputFile}"]
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nrwl/jest:jest",
|
||||
"options": {
|
||||
"jestConfig": "apps/products/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"outputs": ["coverage/apps/products"]
|
||||
},
|
||||
"deploy": {
|
||||
"executor": "@nrwl/workspace:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "npx ts-node --project tools/tsconfig.tools.json tools/scripts/deploy --siteName nrwl-nx-examples-products --outputPath dist/apps/products"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": ["type:app", "scope:products"],
|
||||
"implicitDependencies": ["shared-assets", "shared-styles"]
|
||||
}
|
||||
51
packages/fs-detectors/test/fixtures/39-nx-monorepo/nx.json
vendored
Normal file
51
packages/fs-detectors/test/fixtures/39-nx-monorepo/nx.json
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"implicitDependencies": {
|
||||
"package.json": {
|
||||
"dependencies": "*",
|
||||
"devDependencies": "*"
|
||||
},
|
||||
".eslintrc.json": "*"
|
||||
},
|
||||
"affected": {
|
||||
"defaultBase": "master"
|
||||
},
|
||||
"npmScope": "nx-example",
|
||||
"tasksRunnerOptions": {
|
||||
"default": {
|
||||
"runner": "@nrwl/nx-cloud",
|
||||
"options": {
|
||||
"accessToken": "YmM1MGMwMTUtNzAyYi00ZjM4LWExNGUtZDM2ZjYyNzNiODAxfHJlYWQ=",
|
||||
"cacheableOperations": ["build", "lint", "test"],
|
||||
"parallel": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"warnings": {
|
||||
"versionMismatch": false
|
||||
},
|
||||
"packageManager": "yarn",
|
||||
"analytics": false
|
||||
},
|
||||
"generators": {
|
||||
"@nrwl/angular:application": {
|
||||
"unitTestRunner": "jest",
|
||||
"e2eTestRunner": "cypress"
|
||||
},
|
||||
"@nrwl/angular:library": {
|
||||
"unitTestRunner": "jest"
|
||||
},
|
||||
"@nrwl/angular": {
|
||||
"convert-tslint-to-eslint": {
|
||||
"removeTSLintIfNoMoreTSLintTargets": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "app",
|
||||
"$schema": "./node_modules/nx/schemas/nx-schema.json",
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"]
|
||||
}
|
||||
}
|
||||
}
|
||||
27
packages/fs-detectors/test/fixtures/40-rush-monorepo/rush.json
vendored
Normal file
27
packages/fs-detectors/test/fixtures/40-rush-monorepo/rush.json
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",
|
||||
|
||||
"rushVersion": "5.76.1",
|
||||
|
||||
"pnpmVersion": "6.7.1",
|
||||
|
||||
"pnpmOptions": {
|
||||
"useWorkspaces": true
|
||||
},
|
||||
|
||||
"nodeSupportedVersionRange": ">=12.13.0 <13.0.0 || >=14.15.0 <15.0.0 || >=16.13.0 <17.0.0",
|
||||
|
||||
"gitPolicy": {},
|
||||
|
||||
"repository": {},
|
||||
"eventHooks": {
|
||||
"preRushInstall": [],
|
||||
|
||||
"postRushInstall": [],
|
||||
"preRushBuild": [],
|
||||
|
||||
"postRushBuild": []
|
||||
},
|
||||
"variants": [],
|
||||
"projects": []
|
||||
}
|
||||
@@ -8,6 +8,8 @@ describe('monorepo-managers', () => {
|
||||
['28-turborepo-with-yarn-workspaces', 'turbo'],
|
||||
['31-turborepo-in-package-json', 'turbo'],
|
||||
['22-pnpm', null],
|
||||
['39-nx-monorepo', 'nx'],
|
||||
['40-rush-monorepo', 'rush'],
|
||||
])('with detectFramework', (fixturePath, frameworkSlug) => {
|
||||
const testName = frameworkSlug
|
||||
? `should detect a ${frameworkSlug} workspace for ${fixturePath}`
|
||||
|
||||
@@ -135,11 +135,18 @@ describe('DetectorFilesystem', () => {
|
||||
};
|
||||
|
||||
const fs = new VirtualFilesystem(files);
|
||||
const hasPathSpy = jest.spyOn(fs, '_hasPath');
|
||||
|
||||
expect(await fs.readdir('/')).toEqual([
|
||||
expect(await fs.readdir('/', { potentialFiles: ['config.rb'] })).toEqual([
|
||||
{ name: 'package.json', path: 'package.json', type: 'file' },
|
||||
{ name: 'packages', path: 'packages', type: 'dir' },
|
||||
]);
|
||||
expect(await fs.hasPath('package.json')).toBe(true);
|
||||
expect(hasPathSpy).not.toHaveBeenCalled();
|
||||
expect(await fs.hasPath('config.rb')).toBe(false);
|
||||
expect(hasPathSpy).not.toHaveBeenCalled();
|
||||
expect(await fs.hasPath('tsconfig.json')).toBe(false);
|
||||
expect(hasPathSpy).toHaveBeenCalled();
|
||||
|
||||
expect(await fs.readdir('packages')).toEqual([
|
||||
{ name: 'app1', path: 'packages/app1', type: 'dir' },
|
||||
@@ -151,24 +158,37 @@ describe('DetectorFilesystem', () => {
|
||||
{ name: 'app2', path: 'packages/app2', type: 'dir' },
|
||||
]);
|
||||
|
||||
expect(await fs.readdir('packages/app1')).toEqual([
|
||||
expect(
|
||||
await fs.readdir('packages/app1', { potentialFiles: ['package.json'] })
|
||||
).toEqual([
|
||||
{
|
||||
name: 'package.json',
|
||||
path: 'packages/app1/package.json',
|
||||
type: 'file',
|
||||
},
|
||||
]);
|
||||
|
||||
hasPathSpy.mock.calls.length = 0;
|
||||
expect(await fs.hasPath('packages/app1/package.json')).toBe(true);
|
||||
expect(hasPathSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should be able to write files', async () => {
|
||||
const files = {};
|
||||
const fs = new VirtualFilesystem(files);
|
||||
const hasPathSpy = jest.spyOn(fs, '_hasPath');
|
||||
const isFileSpy = jest.spyOn(fs, '_isFile');
|
||||
const readFileSpy = jest.spyOn(fs, '_readFile');
|
||||
|
||||
fs.writeFile('file.txt', 'Hello World');
|
||||
await fs.writeFile('file.txt', 'Hello World');
|
||||
|
||||
expect(await fs.readFile('file.txt')).toEqual(Buffer.from('Hello World'));
|
||||
expect(await fs.hasPath('file.txt')).toBe(true);
|
||||
expect(await fs.isFile('file.txt')).toBe(true);
|
||||
// We expect that the fs returned values from it's caches instead of calling the underlying functions
|
||||
expect(hasPathSpy).not.toHaveBeenCalled();
|
||||
expect(isFileSpy).not.toHaveBeenCalled();
|
||||
expect(readFileSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should be able to change directories', async () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/go",
|
||||
"version": "2.2.4",
|
||||
"version": "2.2.5",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/go",
|
||||
@@ -35,7 +35,7 @@
|
||||
"@types/jest": "28.1.6",
|
||||
"@types/node-fetch": "^2.3.0",
|
||||
"@types/tar": "^4.0.0",
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"async-retry": "1.3.1",
|
||||
"execa": "^1.0.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/hydrogen",
|
||||
"version": "0.0.17",
|
||||
"version": "0.0.18",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -21,7 +21,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "27.5.1",
|
||||
"@types/node": "*",
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"typescript": "4.6.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "3.1.23",
|
||||
"version": "3.1.25",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
@@ -44,8 +44,8 @@
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/text-table": "0.2.1",
|
||||
"@types/webpack-sources": "3.2.0",
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/nft": "0.21.0",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/nft": "0.22.1",
|
||||
"@vercel/routing-utils": "2.0.2",
|
||||
"async-sema": "3.0.1",
|
||||
"buffer-crc32": "0.2.13",
|
||||
|
||||
@@ -2636,7 +2636,10 @@ async function getServerlessPages(params: {
|
||||
for (const [entry, normalizedEntry] of Object.entries(
|
||||
params.appPathRoutesManifest
|
||||
)) {
|
||||
const normalizedPath = `${path.join('.', normalizedEntry)}.js`;
|
||||
const normalizedPath = `${path.join(
|
||||
'.',
|
||||
normalizedEntry === '/' ? '/index' : normalizedEntry
|
||||
)}.js`;
|
||||
const globPath = `${path.join('.', entry)}.js`;
|
||||
|
||||
if (appPaths[globPath]) {
|
||||
|
||||
@@ -2352,7 +2352,22 @@ export async function getMiddlewareBundle({
|
||||
|
||||
for (const worker of workerConfigs.values()) {
|
||||
const edgeFile = worker.edgeFunction.name;
|
||||
const shortPath = edgeFile.replace(/^pages\//, '');
|
||||
let shortPath = edgeFile;
|
||||
|
||||
// Replacing the folder prefix for the page
|
||||
//
|
||||
// For `pages/`, use file base name directly:
|
||||
// pages/index -> index
|
||||
// For `app/`, use folder name, handle the root page as index:
|
||||
// app/route/page -> route
|
||||
// app/page -> index
|
||||
// app/index/page -> index/index
|
||||
if (shortPath.startsWith('pages/')) {
|
||||
shortPath = shortPath.replace(/^pages\//, '');
|
||||
} else if (shortPath.startsWith('app/') && shortPath.endsWith('/page')) {
|
||||
shortPath =
|
||||
shortPath.replace(/^app\//, '').replace(/(^|\/)page$/, '') || 'index';
|
||||
}
|
||||
|
||||
worker.edgeFunction.name = shortPath;
|
||||
source.edgeFunctions[shortPath] = worker.edgeFunction;
|
||||
|
||||
7
packages/next/test/fixtures/00-app-dir-edge/app/edge/page.server.js
vendored
Normal file
7
packages/next/test/fixtures/00-app-dir-edge/app/edge/page.server.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export default function Page() {
|
||||
return <p>edge</p>;
|
||||
}
|
||||
|
||||
export const config = {
|
||||
runtime: 'experimental-edge',
|
||||
};
|
||||
7
packages/next/test/fixtures/00-app-dir-edge/app/index/page.server.js
vendored
Normal file
7
packages/next/test/fixtures/00-app-dir-edge/app/index/page.server.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export default function page() {
|
||||
return 'index/page';
|
||||
}
|
||||
|
||||
export const config = {
|
||||
runtime: 'experimental-edge',
|
||||
};
|
||||
7
packages/next/test/fixtures/00-app-dir-edge/app/page.server.js
vendored
Normal file
7
packages/next/test/fixtures/00-app-dir-edge/app/page.server.js
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
export default function page() {
|
||||
return 'page';
|
||||
}
|
||||
|
||||
export const config = {
|
||||
runtime: 'experimental-edge',
|
||||
};
|
||||
9
packages/next/test/fixtures/00-app-dir-edge/next.config.js
vendored
Normal file
9
packages/next/test/fixtures/00-app-dir-edge/next.config.js
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
experimental: {
|
||||
appDir: true,
|
||||
runtime: 'experimental-edge',
|
||||
serverComponents: true,
|
||||
legacyBrowsers: false,
|
||||
browsersListForSwc: true,
|
||||
},
|
||||
};
|
||||
7
packages/next/test/fixtures/00-app-dir-edge/package.json
vendored
Normal file
7
packages/next/test/fixtures/00-app-dir-edge/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "canary",
|
||||
"react": "experimental",
|
||||
"react-dom": "experimental"
|
||||
}
|
||||
}
|
||||
15
packages/next/test/fixtures/00-app-dir-edge/vercel.json
vendored
Normal file
15
packages/next/test/fixtures/00-app-dir-edge/vercel.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"builds": [
|
||||
{
|
||||
"src": "package.json",
|
||||
"use": "@vercel/next"
|
||||
}
|
||||
],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/edge",
|
||||
"status": 200,
|
||||
"mustContain": "edge"
|
||||
}
|
||||
]
|
||||
}
|
||||
3
packages/next/test/fixtures/00-app-dir/app/page.server.js
vendored
Normal file
3
packages/next/test/fixtures/00-app-dir/app/page.server.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Page() {
|
||||
return <p>index app page</p>;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "https://files-26yo0dy1b-ijjk-testing.vercel.app",
|
||||
"next": "canary",
|
||||
"react": "experimental",
|
||||
"react-dom": "experimental"
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import Link from 'next/link';
|
||||
export default function Page(props) {
|
||||
return (
|
||||
<>
|
||||
<p>hello from pages/index</p>
|
||||
<Link href="/dashboard">Dashboard</Link>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
{
|
||||
"path": "/",
|
||||
"status": 200,
|
||||
"mustContain": "hello from pages/index"
|
||||
"mustContain": "index app page"
|
||||
},
|
||||
{
|
||||
"path": "/blog/123",
|
||||
|
||||
@@ -17,7 +17,6 @@ it('should build with app-dir correctly', async () => {
|
||||
for (const key of Object.keys(buildResult.output)) {
|
||||
if (buildResult.output[key].type === 'Lambda') {
|
||||
lambdas.add(buildResult.output[key]);
|
||||
console.log('found lambda', key);
|
||||
}
|
||||
}
|
||||
expect(lambdas.size).toBe(1);
|
||||
@@ -27,6 +26,26 @@ it('should build with app-dir correctly', async () => {
|
||||
expect(buildResult.output['dashboard/deployments/[id]']).toBeDefined();
|
||||
});
|
||||
|
||||
it('should build with app-dir in edg runtime correctly', async () => {
|
||||
const { buildResult } = await runBuildLambda(
|
||||
path.join(__dirname, '../fixtures/00-app-dir-edge')
|
||||
);
|
||||
|
||||
console.log('buildResult', buildResult);
|
||||
const edgeFunctions = new Set();
|
||||
|
||||
for (const key of Object.keys(buildResult.output)) {
|
||||
if (buildResult.output[key].type === 'EdgeFunction') {
|
||||
edgeFunctions.add(buildResult.output[key]);
|
||||
}
|
||||
}
|
||||
|
||||
expect(edgeFunctions.size).toBe(3);
|
||||
expect(buildResult.output['edge']).toBeDefined();
|
||||
expect(buildResult.output['index']).toBeDefined();
|
||||
expect(buildResult.output['index/index']).toBeDefined();
|
||||
});
|
||||
|
||||
it('should show error from basePath with legacy monorepo build', async () => {
|
||||
let error;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/node",
|
||||
"version": "2.5.12",
|
||||
"version": "2.5.14",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
|
||||
@@ -29,12 +29,12 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@edge-runtime/vm": "1.1.0-beta.23",
|
||||
"@edge-runtime/vm": "1.1.0-beta.32",
|
||||
"@types/node": "*",
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/node-bridge": "3.0.0",
|
||||
"@vercel/static-config": "2.0.3",
|
||||
"edge-runtime": "1.1.0-beta.23",
|
||||
"edge-runtime": "1.1.0-beta.32",
|
||||
"esbuild": "0.14.47",
|
||||
"exit-hook": "2.2.1",
|
||||
"node-fetch": "2.6.7",
|
||||
@@ -53,7 +53,7 @@
|
||||
"@types/node-fetch": "^2.6.1",
|
||||
"@types/test-listen": "1.1.0",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/nft": "0.22.0",
|
||||
"@vercel/nft": "0.22.1",
|
||||
"content-type": "1.0.4",
|
||||
"cookie": "0.4.0",
|
||||
"etag": "1.8.1",
|
||||
|
||||
@@ -151,7 +151,8 @@ async function serializeRequest(message: IncomingMessage) {
|
||||
|
||||
async function compileUserCode(
|
||||
entrypointPath: string,
|
||||
entrypointLabel: string
|
||||
entrypointLabel: string,
|
||||
isMiddleware: boolean
|
||||
): Promise<undefined | { userCode: string; wasmAssets: WasmAssets }> {
|
||||
const { wasmAssets, plugin: edgeWasmPlugin } = createEdgeWasmPlugin();
|
||||
try {
|
||||
@@ -176,6 +177,8 @@ async function compileUserCode(
|
||||
const userCode = `
|
||||
${compiledFile.text};
|
||||
|
||||
const isMiddleware = ${isMiddleware};
|
||||
|
||||
addEventListener('fetch', async (event) => {
|
||||
try {
|
||||
let serializedRequest = await event.request.text();
|
||||
@@ -205,7 +208,16 @@ async function compileUserCode(
|
||||
let response = await edgeHandler(event.request, event);
|
||||
|
||||
if (!response) {
|
||||
throw new Error('Edge Function "${entrypointLabel}" did not return a response.');
|
||||
if (isMiddleware) {
|
||||
// allow empty responses to pass through
|
||||
response = new Response(null, {
|
||||
headers: {
|
||||
'x-middleware-next': '1',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
throw new Error('Edge Function "${entrypointLabel}" did not return a response.');
|
||||
}
|
||||
}
|
||||
|
||||
return event.respondWith(response);
|
||||
@@ -280,9 +292,14 @@ async function createEdgeRuntime(params?: {
|
||||
|
||||
async function createEdgeEventHandler(
|
||||
entrypointPath: string,
|
||||
entrypointLabel: string
|
||||
entrypointLabel: string,
|
||||
isMiddleware: boolean
|
||||
): Promise<(request: IncomingMessage) => Promise<VercelProxyResponse>> {
|
||||
const userCode = await compileUserCode(entrypointPath, entrypointLabel);
|
||||
const userCode = await compileUserCode(
|
||||
entrypointPath,
|
||||
entrypointLabel,
|
||||
isMiddleware
|
||||
);
|
||||
const server = await createEdgeRuntime(userCode);
|
||||
|
||||
return async function (request: IncomingMessage) {
|
||||
@@ -352,7 +369,11 @@ async function createEventHandler(
|
||||
// an Edge Function, otherwise needs to be opted-in via
|
||||
// `export const config = { runtime: 'experimental-edge' }`
|
||||
if (config.middleware === true || runtime === 'experimental-edge') {
|
||||
return createEdgeEventHandler(entrypointPath, entrypoint);
|
||||
return createEdgeEventHandler(
|
||||
entrypointPath,
|
||||
entrypoint,
|
||||
config.middleware || false
|
||||
);
|
||||
}
|
||||
|
||||
return createServerlessEventHandler(entrypointPath, options);
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
export default function handler(_req, res) {
|
||||
// This build.js asset should be included but not the dep.js asset
|
||||
// because this is readFile(), not require(). It also shouldn't transpile
|
||||
// with babel because it should be considered an asset.
|
||||
const file = join(process.cwd(), 'assets', 'build.js');
|
||||
const content = readFileSync(file, 'utf8');
|
||||
res.setHeader('Content-Type', 'application/javascript');
|
||||
return res.end(content);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
import dep from './dep.js';
|
||||
@@ -1,3 +0,0 @@
|
||||
// This file should not be included because the
|
||||
// api/index.js is performing a readFile(), not require().
|
||||
export const dep = 'dep1';
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"probes": [
|
||||
{
|
||||
"path": "/api",
|
||||
"mustContain": "import dep from './dep.js';"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/python",
|
||||
"version": "3.1.13",
|
||||
"version": "3.1.14",
|
||||
"main": "./dist/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",
|
||||
@@ -22,7 +22,7 @@
|
||||
"devDependencies": {
|
||||
"@types/execa": "^0.9.0",
|
||||
"@types/jest": "27.4.1",
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"execa": "^1.0.0",
|
||||
"typescript": "4.3.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/redwood",
|
||||
"version": "1.0.21",
|
||||
"version": "1.0.23",
|
||||
"main": "./dist/index.js",
|
||||
"license": "MIT",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -19,7 +19,7 @@
|
||||
"test-unit": "yarn test test/prepare-cache.test.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/nft": "0.22.0",
|
||||
"@vercel/nft": "0.22.1",
|
||||
"@vercel/routing-utils": "2.0.2",
|
||||
"semver": "6.1.1"
|
||||
},
|
||||
@@ -27,6 +27,6 @@
|
||||
"@types/aws-lambda": "8.10.19",
|
||||
"@types/node": "*",
|
||||
"@types/semver": "6.0.0",
|
||||
"@vercel/build-utils": "5.4.1"
|
||||
"@vercel/build-utils": "5.4.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/remix",
|
||||
"version": "1.0.22",
|
||||
"version": "1.0.24",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"homepage": "https://vercel.com/docs",
|
||||
@@ -20,12 +20,12 @@
|
||||
"default-server.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@vercel/nft": "0.22.0"
|
||||
"@vercel/nft": "0.22.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "27.5.1",
|
||||
"@types/node": "*",
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"typescript": "4.6.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@vercel/ruby",
|
||||
"author": "Nathan Cahill <nathan@nathancahill.com>",
|
||||
"version": "1.3.30",
|
||||
"version": "1.3.31",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/ruby",
|
||||
@@ -22,7 +22,7 @@
|
||||
"devDependencies": {
|
||||
"@types/fs-extra": "8.0.0",
|
||||
"@types/semver": "6.0.0",
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"execa": "2.0.4",
|
||||
"fs-extra": "^7.0.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/static-build",
|
||||
"version": "1.0.21",
|
||||
"version": "1.0.23",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/build-step",
|
||||
@@ -36,8 +36,8 @@
|
||||
"@types/ms": "0.7.31",
|
||||
"@types/node-fetch": "2.5.4",
|
||||
"@types/promise-timeout": "1.3.0",
|
||||
"@vercel/build-utils": "5.4.1",
|
||||
"@vercel/frameworks": "1.1.3",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/frameworks": "1.1.5",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@vercel/routing-utils": "2.0.2",
|
||||
"fs-extra": "10.0.0",
|
||||
|
||||
63
yarn.lock
63
yarn.lock
@@ -719,10 +719,10 @@
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "0.3.9"
|
||||
|
||||
"@edge-runtime/format@^1.1.0-beta.23":
|
||||
version "1.1.0-beta.23"
|
||||
resolved "https://registry.yarnpkg.com/@edge-runtime/format/-/format-1.1.0-beta.23.tgz#c28fddee0c45a62be63f691a01306c611c99e739"
|
||||
integrity sha512-TuY7ywLzp2XQQZpM8cX1dzm2QMK2juvtpMVR8K61utL2qvokzJ4gBYLcPSKhH0EWAt4WwgymNVRX0cpdSLAqAg==
|
||||
"@edge-runtime/format@^1.1.0-beta.32":
|
||||
version "1.1.0-beta.32"
|
||||
resolved "https://registry.yarnpkg.com/@edge-runtime/format/-/format-1.1.0-beta.32.tgz#6f0d5a8726cc54ebb2b1dcb86fe25c0ff093731d"
|
||||
integrity sha512-wpQtbgHJuSF1fvDV6Gxg2L7uNpzhQnRl91DREgOdRfa3S8y9AANjPi1/g3GPBGPiGZoX2Fv+MKV6RgY5/jLfJA==
|
||||
|
||||
"@edge-runtime/jest-environment@1.1.0-beta.7":
|
||||
version "1.1.0-beta.7"
|
||||
@@ -736,22 +736,22 @@
|
||||
jest-mock "28.1.1"
|
||||
jest-util "28.1.1"
|
||||
|
||||
"@edge-runtime/primitives@^1.1.0-beta.23":
|
||||
version "1.1.0-beta.23"
|
||||
resolved "https://registry.yarnpkg.com/@edge-runtime/primitives/-/primitives-1.1.0-beta.23.tgz#b9b8d83e3dce63286cf80b8d5ece43f32420c4ab"
|
||||
integrity sha512-0vHcZZwyxjmw/so9irYtA82/+nAlJRs+1WpRYBx7iae1FOGCPM4BIKEmboWmwTuj7c6avz9kIbptokdMUPgV9A==
|
||||
"@edge-runtime/primitives@^1.1.0-beta.32":
|
||||
version "1.1.0-beta.33"
|
||||
resolved "https://registry.yarnpkg.com/@edge-runtime/primitives/-/primitives-1.1.0-beta.33.tgz#9bd0d866addfdc98ec32ff3ca0f6d24f412a5c03"
|
||||
integrity sha512-mAZw/YRhwkaPVYwSwOTJTMMzZxfuLze6VEepsrVO/4yjnxriOf2GREgLal6OBtTcEEC44q4lqS+OSd0QaSFZEQ==
|
||||
|
||||
"@edge-runtime/primitives@^1.1.0-beta.7":
|
||||
version "1.1.0-beta.7"
|
||||
resolved "https://registry.yarnpkg.com/@edge-runtime/primitives/-/primitives-1.1.0-beta.7.tgz#0450ee3e5e03a8898ee072c0d0ee01fd2c1ed8f1"
|
||||
integrity sha512-ZwuSMpmrf2mAj/O7EWxKOXrC03YMkU64N+CgvVFOtJGfhydk4Db/392Zama3BjNYAMOr/oY9L7HxfPutAFesKw==
|
||||
|
||||
"@edge-runtime/vm@1.1.0-beta.23", "@edge-runtime/vm@^1.1.0-beta.23":
|
||||
version "1.1.0-beta.23"
|
||||
resolved "https://registry.yarnpkg.com/@edge-runtime/vm/-/vm-1.1.0-beta.23.tgz#b55d9add18cb7bb57acf184f6cd7b6edec782a25"
|
||||
integrity sha512-XBp3rCuX4scJVOo2KconAotL5XGX3zdd8IkfDNr5VVSQ/B6HkiTNuf+EvzSQTpplF+fiyLTpfcP9EbNLibwLTA==
|
||||
"@edge-runtime/vm@1.1.0-beta.32", "@edge-runtime/vm@^1.1.0-beta.32":
|
||||
version "1.1.0-beta.32"
|
||||
resolved "https://registry.yarnpkg.com/@edge-runtime/vm/-/vm-1.1.0-beta.32.tgz#1bc9c77a88343478d50009f30813b9fbf8a0f4ad"
|
||||
integrity sha512-G0SH80am2XjlK6oFI3RoKlg1SBS5ZAeqakYasfNhJEXqM7g7tsoh5jURMQcNxpLvo48XBTgHgAVEMzhAGgDPZg==
|
||||
dependencies:
|
||||
"@edge-runtime/primitives" "^1.1.0-beta.23"
|
||||
"@edge-runtime/primitives" "^1.1.0-beta.32"
|
||||
|
||||
"@edge-runtime/vm@^1.1.0-beta.7":
|
||||
version "1.1.0-beta.7"
|
||||
@@ -3212,27 +3212,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.24.0.tgz#a2e8783a185caa99b5d8961a57dfc9665de16296"
|
||||
integrity sha512-crqItMcIwCkvdXY/V3/TzrHJQx6nbIaRqE1cOopJhgGX6izvNov40SmD//nS5flfEvdK54YGjwVVq+zG6crjOg==
|
||||
|
||||
"@vercel/nft@0.21.0":
|
||||
version "0.21.0"
|
||||
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.21.0.tgz#e0715b1997cd7021a7c7c48b584ef2295fd4b810"
|
||||
integrity sha512-hFCAETfI5cG8l5iAiLhMC2bReC5K7SIybzrxGorv+eGspIbIFsVw7Vg85GovXm/LxA08pIDrAlrhR6GN36XB/Q==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.5"
|
||||
acorn "^8.6.0"
|
||||
async-sema "^3.1.1"
|
||||
bindings "^1.4.0"
|
||||
estree-walker "2.0.2"
|
||||
glob "^7.1.3"
|
||||
graceful-fs "^4.2.9"
|
||||
micromatch "^4.0.2"
|
||||
node-gyp-build "^4.2.2"
|
||||
resolve-from "^5.0.0"
|
||||
rollup-pluginutils "^2.8.2"
|
||||
|
||||
"@vercel/nft@0.22.0":
|
||||
version "0.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.22.0.tgz#586ed4edfd0dabc9bf07525044782198a0b31199"
|
||||
integrity sha512-hB80/093PPiCefN2gVbqv6J93MH+63Zr7uDCwkiS/U4W07DXkLoftbnkBmZoS0Q84LiTSl9DRVSHU4XYCX+sJA==
|
||||
"@vercel/nft@0.22.1":
|
||||
version "0.22.1"
|
||||
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.22.1.tgz#0d91d2a21e3a7f0b23ce1550da9870eac4942828"
|
||||
integrity sha512-lYYZIoxRurqDOSoVIdBicGnpUIpfyaS5qVjdPq+EfI285WqtZK3NK/dyCkiyBul+X2U2OEhRyeMdXPCHGJbohw==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.5"
|
||||
acorn "^8.6.0"
|
||||
@@ -5490,13 +5473,13 @@ ecc-jsbn@~0.1.1:
|
||||
jsbn "~0.1.0"
|
||||
safer-buffer "^2.1.0"
|
||||
|
||||
edge-runtime@1.1.0-beta.23:
|
||||
version "1.1.0-beta.23"
|
||||
resolved "https://registry.yarnpkg.com/edge-runtime/-/edge-runtime-1.1.0-beta.23.tgz#fd4d93f021c622e9b188399fa83e6bd5e445cb5e"
|
||||
integrity sha512-A7dO/Y+4UJnaxFcdz6pepL+0GcvvViWvf201oFQXepgdSxPDKiqxaayCag0eiirQ6OfF+cSTmPD3xrfEoAIjiQ==
|
||||
edge-runtime@1.1.0-beta.32:
|
||||
version "1.1.0-beta.32"
|
||||
resolved "https://registry.yarnpkg.com/edge-runtime/-/edge-runtime-1.1.0-beta.32.tgz#e43fd53c57fdba3c567b3fef50743cba00ff5e49"
|
||||
integrity sha512-fbqqUF3OKynqtWgExhjyxXX2SwbkWuwmjUYhml3Sv8Y/vkrTxyTKrxS0MoxUy5sGPB3BBEtpopn36cQgwlOpAg==
|
||||
dependencies:
|
||||
"@edge-runtime/format" "^1.1.0-beta.23"
|
||||
"@edge-runtime/vm" "^1.1.0-beta.23"
|
||||
"@edge-runtime/format" "^1.1.0-beta.32"
|
||||
"@edge-runtime/vm" "^1.1.0-beta.32"
|
||||
exit-hook "2.2.1"
|
||||
http-status "1.5.2"
|
||||
mri "1.2.0"
|
||||
|
||||
Reference in New Issue
Block a user