mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 12:57:46 +00:00
Compare commits
28 Commits
@vercel/py
...
@vercel/py
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
619ca93421 | ||
|
|
cea2981512 | ||
|
|
1f30e3a4b7 | ||
|
|
20e8fdd049 | ||
|
|
3df8313d69 | ||
|
|
95c9ea92c4 | ||
|
|
7ddebb099d | ||
|
|
6498fd1aab | ||
|
|
9d7d822da3 | ||
|
|
b8110d97d1 | ||
|
|
2d9373b0f1 | ||
|
|
cc7577a648 | ||
|
|
f3f3d7df5b | ||
|
|
0bafea6d51 | ||
|
|
5abb74eddd | ||
|
|
23d7eaccab | ||
|
|
2cb008e8ed | ||
|
|
b5c3610113 | ||
|
|
f23c7fc4fc | ||
|
|
3dc1ad6437 | ||
|
|
4dc0bef62b | ||
|
|
8b3c52b9e8 | ||
|
|
fc74300ad0 | ||
|
|
28f8a38e00 | ||
|
|
c318ce9695 | ||
|
|
5b36eaacff | ||
|
|
c9f7ca23a8 | ||
|
|
57e0db0f65 |
1
.github/workflows/publish.yml
vendored
1
.github/workflows/publish.yml
vendored
@@ -34,6 +34,7 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 14
|
||||
cache: 'yarn'
|
||||
- name: Install
|
||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||
run: yarn install --check-files --frozen-lockfile --network-timeout 1000000
|
||||
|
||||
11
.github/workflows/test-integration-cli.yml
vendored
11
.github/workflows/test-integration-cli.yml
vendored
@@ -25,19 +25,16 @@ jobs:
|
||||
echo "TURBO_REMOTE_ONLY=true" >> $GITHUB_ENV
|
||||
echo "TURBO_TEAM=vercel" >> $GITHUB_ENV
|
||||
echo "TURBO_TOKEN=${{ secrets.TURBO_TOKEN }}" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.13.15'
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 100
|
||||
- run: git --version
|
||||
- run: git fetch origin main --depth=100
|
||||
- run: git fetch origin ${{ github.ref }} --depth=100
|
||||
- run: git diff origin/main...HEAD --name-only
|
||||
cache: 'yarn'
|
||||
- run: yarn install --network-timeout 1000000 --frozen-lockfile
|
||||
- run: yarn run build
|
||||
- run: yarn test-integration-cli
|
||||
|
||||
13
.github/workflows/test-unit.yml
vendored
13
.github/workflows/test-unit.yml
vendored
@@ -28,16 +28,13 @@ jobs:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.13.15'
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 100
|
||||
- run: git --version
|
||||
- run: git fetch origin main --depth=100
|
||||
- run: git fetch origin ${{ github.ref }} --depth=100
|
||||
- run: git diff origin/main...HEAD --name-only
|
||||
fetch-depth: 2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: 'yarn'
|
||||
- run: yarn install --network-timeout 1000000 --frozen-lockfile
|
||||
- run: yarn run build
|
||||
- run: yarn run lint
|
||||
|
||||
7
.github/workflows/test.yml
vendored
7
.github/workflows/test.yml
vendored
@@ -20,8 +20,11 @@ jobs:
|
||||
dplUrl: ${{ steps.waitForTarball.outputs.url }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- run: git --version
|
||||
- run: git fetch origin main
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '1.13.15'
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
|
||||
@@ -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.2",
|
||||
"version": "5.4.3",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
29
packages/build-utils/src/clone-env.ts
Normal file
29
packages/build-utils/src/clone-env.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { Env } from './types';
|
||||
|
||||
const { hasOwnProperty } = Object.prototype;
|
||||
|
||||
/**
|
||||
* Clones zero or more objects into a single new object while ensuring that the
|
||||
* `PATH` environment variable is defined when the `PATH` or `Path` environment
|
||||
* variables are defined.
|
||||
*
|
||||
* @param {Object} [...envs] Objects and/or `process.env` to clone and merge
|
||||
* @returns {Object} The new object
|
||||
*/
|
||||
export function cloneEnv(...envs: (Env | undefined)[]): Env {
|
||||
return envs.reduce((obj: Env, env) => {
|
||||
if (env === undefined || env === null) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
// the system path is called `Path` on Windows and Node.js will
|
||||
// automatically return the system path when accessing `PATH`,
|
||||
// however we lose this proxied value when we destructure and
|
||||
// thus we must explicitly copy it
|
||||
if (hasOwnProperty.call(env, 'PATH') || hasOwnProperty.call(env, 'Path')) {
|
||||
obj.PATH = env.PATH;
|
||||
}
|
||||
|
||||
return Object.assign(obj, env);
|
||||
}, {});
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import { NowBuildError } from '../errors';
|
||||
import { Meta, PackageJson, NodeVersion, Config } from '../types';
|
||||
import { getSupportedNodeVersion, getLatestNodeVersion } from './node-version';
|
||||
import { readConfigFile } from './read-config-file';
|
||||
import { cloneEnv } from '../clone-env';
|
||||
|
||||
// Only allow one `runNpmInstall()` invocation to run concurrently
|
||||
const runNpmInstallSema = new Sema(1);
|
||||
@@ -217,7 +218,7 @@ export function getSpawnOptions(
|
||||
nodeVersion: NodeVersion
|
||||
): SpawnOptions {
|
||||
const opts = {
|
||||
env: { ...process.env },
|
||||
env: cloneEnv(process.env),
|
||||
};
|
||||
|
||||
if (!meta.isDev) {
|
||||
@@ -449,7 +450,7 @@ export async function runNpmInstall(
|
||||
debug(`Installing to ${destPath}`);
|
||||
|
||||
const opts: SpawnOptionsExtended = { cwd: destPath, ...spawnOpts };
|
||||
const env = opts.env ? { ...opts.env } : { ...process.env };
|
||||
const env = cloneEnv(opts.env || process.env);
|
||||
delete env.NODE_ENV;
|
||||
opts.env = getEnvForPackageManager({
|
||||
cliType,
|
||||
@@ -464,6 +465,19 @@ export async function runNpmInstall(
|
||||
commandArgs = args
|
||||
.filter(a => a !== '--prefer-offline')
|
||||
.concat(['install', '--no-audit', '--unsafe-perm']);
|
||||
if (
|
||||
nodeVersion?.major === 16 &&
|
||||
spawnOpts?.env?.VERCEL_NPM_LEGACY_PEER_DEPS === '1' &&
|
||||
spawnOpts?.env?.ENABLE_EXPERIMENTAL_COREPACK !== '1'
|
||||
) {
|
||||
// Starting in npm@8.6.0, if you ran `npm install --legacy-peer-deps`,
|
||||
// and then later ran `npm install`, it would fail. So the only way
|
||||
// to safely upgrade npm from npm@8.5.0 is to set this flag. The docs
|
||||
// say this flag is not recommended so its is behind a feature flag
|
||||
// so we can remove it in node@18, which can introduce breaking changes.
|
||||
// See https://docs.npmjs.com/cli/v8/using-npm/config#legacy-peer-deps
|
||||
commandArgs.push('--legacy-peer-deps');
|
||||
}
|
||||
} else if (cliType === 'pnpm') {
|
||||
// PNPM's install command is similar to NPM's but without the audit nonsense
|
||||
// @see options https://pnpm.io/cli/install
|
||||
@@ -591,10 +605,7 @@ export async function runPackageJsonScript(
|
||||
cliType,
|
||||
lockfileVersion,
|
||||
nodeVersion: undefined,
|
||||
env: {
|
||||
...process.env,
|
||||
...spawnOpts?.env,
|
||||
},
|
||||
env: cloneEnv(process.env, spawnOpts?.env),
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import debug from './debug';
|
||||
import getIgnoreFilter from './get-ignore-filter';
|
||||
import { getPlatformEnv } from './get-platform-env';
|
||||
import { getPrefixedEnvVars } from './get-prefixed-env-vars';
|
||||
import { cloneEnv } from './clone-env';
|
||||
|
||||
export {
|
||||
FileBlob,
|
||||
@@ -84,6 +85,7 @@ export {
|
||||
getLambdaOptionsFromFunction,
|
||||
scanParentDirs,
|
||||
getIgnoreFilter,
|
||||
cloneEnv,
|
||||
};
|
||||
|
||||
export { EdgeFunction } from './edge-function';
|
||||
|
||||
@@ -342,6 +342,7 @@ export interface BuilderV2 {
|
||||
version: 2;
|
||||
build: BuildV2;
|
||||
prepareCache?: PrepareCache;
|
||||
shouldServe?: ShouldServe;
|
||||
}
|
||||
|
||||
export interface BuilderV3 {
|
||||
|
||||
1
packages/build-utils/test/fixtures/20-npm-7/package-lock.json
generated
vendored
1
packages/build-utils/test/fixtures/20-npm-7/package-lock.json
generated
vendored
@@ -5,6 +5,7 @@
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "20-npm-7",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ const skipFixtures: string[] = [
|
||||
'08-zero-config-middleman',
|
||||
'21-npm-workspaces',
|
||||
'23-pnpm-workspaces',
|
||||
'41-nx-monorepo',
|
||||
'42-npm-workspace-with-nx',
|
||||
];
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
|
||||
120
packages/build-utils/test/unit.clone-env.test.ts
vendored
Normal file
120
packages/build-utils/test/unit.clone-env.test.ts
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
import { cloneEnv } from '../src';
|
||||
|
||||
it('should clone env with Path', () => {
|
||||
expect(
|
||||
cloneEnv(
|
||||
new Proxy(
|
||||
{
|
||||
foo: 'bar',
|
||||
Path: 'baz',
|
||||
},
|
||||
{
|
||||
get(target: typeof process.env, prop: string) {
|
||||
if (prop === 'PATH') {
|
||||
return target.PATH ?? target.Path;
|
||||
}
|
||||
return target[prop];
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
).toEqual({
|
||||
foo: 'bar',
|
||||
Path: 'baz',
|
||||
PATH: 'baz',
|
||||
});
|
||||
});
|
||||
|
||||
it('should clone env with PATH', () => {
|
||||
expect(
|
||||
cloneEnv({
|
||||
foo: 'bar',
|
||||
PATH: 'baz',
|
||||
})
|
||||
).toEqual({
|
||||
foo: 'bar',
|
||||
PATH: 'baz',
|
||||
});
|
||||
});
|
||||
|
||||
it('should clone and merge multiple env objects', () => {
|
||||
// note: this also tests the last object doesn't overwrite `PATH` with
|
||||
// `undefined`
|
||||
expect(
|
||||
cloneEnv(
|
||||
{
|
||||
foo: 'bar',
|
||||
},
|
||||
{
|
||||
PATH: 'baz',
|
||||
},
|
||||
{
|
||||
baz: 'wiz',
|
||||
}
|
||||
)
|
||||
).toEqual({
|
||||
foo: 'bar',
|
||||
PATH: 'baz',
|
||||
baz: 'wiz',
|
||||
});
|
||||
});
|
||||
|
||||
it('should clone the actual process.env object', () => {
|
||||
expect(cloneEnv(process.env).PATH).toEqual(process.env.PATH);
|
||||
});
|
||||
|
||||
it('should overwrite PATH with last value', () => {
|
||||
expect(
|
||||
cloneEnv(
|
||||
new Proxy(
|
||||
{
|
||||
Path: 'foo',
|
||||
},
|
||||
{
|
||||
get(target: typeof process.env, prop: string) {
|
||||
if (prop === 'PATH') {
|
||||
return target.PATH ?? target.Path;
|
||||
}
|
||||
return target[prop];
|
||||
},
|
||||
}
|
||||
),
|
||||
{
|
||||
PATH: 'bar',
|
||||
},
|
||||
{
|
||||
PATH: undefined,
|
||||
}
|
||||
)
|
||||
).toEqual({
|
||||
Path: 'foo',
|
||||
PATH: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle process.env at any argument position', () => {
|
||||
expect(
|
||||
cloneEnv(
|
||||
{
|
||||
foo: 'bar',
|
||||
},
|
||||
new Proxy(
|
||||
{
|
||||
Path: 'baz',
|
||||
},
|
||||
{
|
||||
get(target: typeof process.env, prop: string) {
|
||||
if (prop === 'PATH') {
|
||||
return target.PATH ?? target.Path;
|
||||
}
|
||||
return target[prop];
|
||||
},
|
||||
}
|
||||
)
|
||||
)
|
||||
).toEqual({
|
||||
foo: 'bar',
|
||||
Path: 'baz',
|
||||
PATH: 'baz',
|
||||
});
|
||||
});
|
||||
172
packages/build-utils/test/unit.run-npm-install.test.ts
vendored
Normal file
172
packages/build-utils/test/unit.run-npm-install.test.ts
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
const spawnMock = jest.fn();
|
||||
jest.mock('cross-spawn', () => {
|
||||
const spawn = (...args: any) => {
|
||||
spawnMock(...args);
|
||||
const child = {
|
||||
on: (type: string, fn: (code: number) => void) => {
|
||||
if (type === 'close') {
|
||||
return fn(0);
|
||||
}
|
||||
},
|
||||
};
|
||||
return child;
|
||||
};
|
||||
return spawn;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
spawnMock.mockClear();
|
||||
});
|
||||
|
||||
import path from 'path';
|
||||
import { runNpmInstall, cloneEnv } from '../src';
|
||||
import type { Meta } from '../src/types';
|
||||
|
||||
function getTestSpawnOpts(env: Record<string, string>) {
|
||||
return { env: cloneEnv(process.env, env) };
|
||||
}
|
||||
|
||||
function getNodeVersion(major: number) {
|
||||
return { major, range: `${major}.x`, runtime: `nodejs${major}.x` };
|
||||
}
|
||||
|
||||
it('should not include peer dependencies when missing VERCEL_NPM_LEGACY_PEER_DEPS on node16', async () => {
|
||||
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
||||
const meta: Meta = {};
|
||||
const spawnOpts = getTestSpawnOpts({});
|
||||
const nodeVersion = { major: 16 } as any;
|
||||
await runNpmInstall(fixture, [], spawnOpts, meta, nodeVersion);
|
||||
expect(spawnMock.mock.calls.length).toBe(1);
|
||||
const args = spawnMock.mock.calls[0];
|
||||
expect(args[0]).toEqual('npm');
|
||||
expect(args[1]).toEqual(['install', '--no-audit', '--unsafe-perm']);
|
||||
expect(args[2]).toEqual({
|
||||
cwd: fixture,
|
||||
prettyCommand: 'npm install',
|
||||
stdio: 'inherit',
|
||||
env: expect.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
it('should include peer dependencies when VERCEL_NPM_LEGACY_PEER_DEPS=1 on node16', async () => {
|
||||
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
||||
const meta: Meta = {};
|
||||
const spawnOpts = getTestSpawnOpts({ VERCEL_NPM_LEGACY_PEER_DEPS: '1' });
|
||||
const nodeVersion = getNodeVersion(16);
|
||||
await runNpmInstall(fixture, [], spawnOpts, meta, nodeVersion);
|
||||
expect(spawnMock.mock.calls.length).toBe(1);
|
||||
const args = spawnMock.mock.calls[0];
|
||||
expect(args[0]).toEqual('npm');
|
||||
expect(args[1]).toEqual([
|
||||
'install',
|
||||
'--no-audit',
|
||||
'--unsafe-perm',
|
||||
'--legacy-peer-deps',
|
||||
]);
|
||||
expect(args[2]).toEqual({
|
||||
cwd: fixture,
|
||||
prettyCommand: 'npm install',
|
||||
stdio: 'inherit',
|
||||
env: expect.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
it('should not include peer dependencies when VERCEL_NPM_LEGACY_PEER_DEPS=1 on node14', async () => {
|
||||
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
||||
const meta: Meta = {};
|
||||
const spawnOpts = getTestSpawnOpts({ VERCEL_NPM_LEGACY_PEER_DEPS: '1' });
|
||||
const nodeVersion = getNodeVersion(14);
|
||||
await runNpmInstall(fixture, [], spawnOpts, meta, nodeVersion);
|
||||
expect(spawnMock.mock.calls.length).toBe(1);
|
||||
const args = spawnMock.mock.calls[0];
|
||||
expect(args[0]).toEqual('npm');
|
||||
expect(args[1]).toEqual(['install', '--no-audit', '--unsafe-perm']);
|
||||
expect(args[2]).toEqual({
|
||||
cwd: fixture,
|
||||
prettyCommand: 'npm install',
|
||||
stdio: 'inherit',
|
||||
env: expect.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
it('should not include peer dependencies when VERCEL_NPM_LEGACY_PEER_DEPS=1 on node16 with corepack enabled', async () => {
|
||||
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
||||
const meta: Meta = {};
|
||||
const spawnOpts = getTestSpawnOpts({
|
||||
VERCEL_NPM_LEGACY_PEER_DEPS: '1',
|
||||
ENABLE_EXPERIMENTAL_COREPACK: '1',
|
||||
});
|
||||
const nodeVersion = getNodeVersion(16);
|
||||
await runNpmInstall(fixture, [], spawnOpts, meta, nodeVersion);
|
||||
expect(spawnMock.mock.calls.length).toBe(1);
|
||||
const args = spawnMock.mock.calls[0];
|
||||
expect(args[0]).toEqual('npm');
|
||||
expect(args[1]).toEqual(['install', '--no-audit', '--unsafe-perm']);
|
||||
expect(args[2]).toEqual({
|
||||
cwd: fixture,
|
||||
prettyCommand: 'npm install',
|
||||
stdio: 'inherit',
|
||||
env: expect.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
it('should only invoke `runNpmInstall()` once per `package.json` file (serial)', async () => {
|
||||
const meta: Meta = {};
|
||||
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||
const apiDir = path.join(fixture, 'api');
|
||||
|
||||
const run1 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||
expect(run1).toEqual(true);
|
||||
expect(
|
||||
(meta.runNpmInstallSet as Set<string>).has(
|
||||
path.join(fixture, 'package.json')
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
const run2 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||
expect(run2).toEqual(false);
|
||||
|
||||
const run3 = await runNpmInstall(fixture, [], undefined, meta);
|
||||
expect(run3).toEqual(false);
|
||||
|
||||
expect(spawnMock.mock.calls.length).toBe(1);
|
||||
const args = spawnMock.mock.calls[0];
|
||||
expect(args[0]).toEqual('yarn');
|
||||
expect(args[1]).toEqual(['install']);
|
||||
expect(args[2]).toEqual({
|
||||
cwd: apiDir,
|
||||
prettyCommand: 'yarn install',
|
||||
stdio: 'inherit',
|
||||
env: expect.any(Object),
|
||||
});
|
||||
});
|
||||
|
||||
it('should only invoke `runNpmInstall()` once per `package.json` file (parallel)', async () => {
|
||||
const meta: Meta = {};
|
||||
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||
const apiDir = path.join(fixture, 'api');
|
||||
const [run1, run2, run3] = await Promise.all([
|
||||
runNpmInstall(apiDir, [], undefined, meta),
|
||||
runNpmInstall(apiDir, [], undefined, meta),
|
||||
runNpmInstall(fixture, [], undefined, meta),
|
||||
]);
|
||||
expect(run1).toEqual(true);
|
||||
expect(run2).toEqual(false);
|
||||
expect(run3).toEqual(false);
|
||||
expect(
|
||||
(meta.runNpmInstallSet as Set<string>).has(
|
||||
path.join(fixture, 'package.json')
|
||||
)
|
||||
).toEqual(true);
|
||||
|
||||
expect(spawnMock.mock.calls.length).toBe(1);
|
||||
const args = spawnMock.mock.calls[0];
|
||||
expect(args[0]).toEqual('yarn');
|
||||
expect(args[1]).toEqual(['install']);
|
||||
expect(args[2]).toEqual({
|
||||
cwd: apiDir,
|
||||
prettyCommand: 'yarn install',
|
||||
stdio: 'inherit',
|
||||
env: expect.any(Object),
|
||||
});
|
||||
});
|
||||
53
packages/build-utils/test/unit.test.ts
vendored
53
packages/build-utils/test/unit.test.ts
vendored
@@ -1,7 +1,6 @@
|
||||
import ms from 'ms';
|
||||
import path from 'path';
|
||||
import fs, { readlink } from 'fs-extra';
|
||||
import retry from 'async-retry';
|
||||
import { strict as assert, strictEqual } from 'assert';
|
||||
import { createZip } from '../src/lambda';
|
||||
import { getSupportedNodeVersion } from '../src/fs/node-version';
|
||||
@@ -16,7 +15,6 @@ import {
|
||||
runPackageJsonScript,
|
||||
scanParentDirs,
|
||||
FileBlob,
|
||||
Meta,
|
||||
} from '../src';
|
||||
|
||||
jest.setTimeout(10 * 1000);
|
||||
@@ -577,54 +575,3 @@ it('should detect package.json in nested frontend', async () => {
|
||||
// There is no lockfile but this test will pick up vercel/vercel/yarn.lock
|
||||
expect(result.packageJsonPath).toEqual(path.join(fixture, 'package.json'));
|
||||
});
|
||||
|
||||
it('should only invoke `runNpmInstall()` once per `package.json` file (serial)', async () => {
|
||||
const meta: Meta = {};
|
||||
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||
const apiDir = path.join(fixture, 'api');
|
||||
const retryOpts = { maxRetryTime: 1000 };
|
||||
let run1, run2, run3;
|
||||
await retry(async () => {
|
||||
run1 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||
expect(run1).toEqual(true);
|
||||
expect(
|
||||
(meta.runNpmInstallSet as Set<string>).has(
|
||||
path.join(fixture, 'package.json')
|
||||
)
|
||||
).toEqual(true);
|
||||
}, retryOpts);
|
||||
await retry(async () => {
|
||||
run2 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||
expect(run2).toEqual(false);
|
||||
}, retryOpts);
|
||||
await retry(async () => {
|
||||
run3 = await runNpmInstall(fixture, [], undefined, meta);
|
||||
expect(run3).toEqual(false);
|
||||
}, retryOpts);
|
||||
});
|
||||
|
||||
it('should only invoke `runNpmInstall()` once per `package.json` file (parallel)', async () => {
|
||||
const meta: Meta = {};
|
||||
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||
const apiDir = path.join(fixture, 'api');
|
||||
let results: [boolean, boolean, boolean] | undefined;
|
||||
await retry(
|
||||
async () => {
|
||||
results = await Promise.all([
|
||||
runNpmInstall(apiDir, [], undefined, meta),
|
||||
runNpmInstall(apiDir, [], undefined, meta),
|
||||
runNpmInstall(fixture, [], undefined, meta),
|
||||
]);
|
||||
},
|
||||
{ maxRetryTime: 3000 }
|
||||
);
|
||||
const [run1, run2, run3] = results || [];
|
||||
expect(run1).toEqual(true);
|
||||
expect(run2).toEqual(false);
|
||||
expect(run3).toEqual(false);
|
||||
expect(
|
||||
(meta.runNpmInstallSet as Set<string>).has(
|
||||
path.join(fixture, 'package.json')
|
||||
)
|
||||
).toEqual(true);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "28.2.3",
|
||||
"version": "28.3.0",
|
||||
"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.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.22",
|
||||
"@vercel/build-utils": "5.4.3",
|
||||
"@vercel/go": "2.2.6",
|
||||
"@vercel/hydrogen": "0.0.19",
|
||||
"@vercel/next": "3.1.26",
|
||||
"@vercel/node": "2.5.15",
|
||||
"@vercel/python": "3.1.15",
|
||||
"@vercel/redwood": "1.0.24",
|
||||
"@vercel/remix": "1.0.25",
|
||||
"@vercel/ruby": "1.3.32",
|
||||
"@vercel/static-build": "1.0.24",
|
||||
"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.4",
|
||||
"@vercel/frameworks": "1.1.4",
|
||||
"@vercel/fs-detectors": "3.0.0",
|
||||
"@vercel/client": "12.2.5",
|
||||
"@vercel/frameworks": "1.1.6",
|
||||
"@vercel/fs-detectors": "3.3.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';
|
||||
@@ -32,6 +31,7 @@ import {
|
||||
} from '@vercel/routing-utils';
|
||||
import {
|
||||
Builder,
|
||||
cloneEnv,
|
||||
Env,
|
||||
StartDevServerResult,
|
||||
FileFsRef,
|
||||
@@ -62,11 +62,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 +96,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 +131,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 +158,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 +166,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 +178,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 +204,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 +485,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 +688,7 @@ export default class DevServer {
|
||||
this.projectEnvs || [],
|
||||
this.systemEnvValues || [],
|
||||
this.projectSettings?.autoExposeSystemEnvs,
|
||||
new URL(this.address).host
|
||||
this.address.host
|
||||
);
|
||||
|
||||
allEnv = { ...cloudEnv };
|
||||
@@ -842,7 +823,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 +896,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 +913,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 +964,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 +1012,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 +1414,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 +1430,7 @@ export default class DevServer {
|
||||
buildEnv: { ...envConfigs.buildEnv },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (startMiddlewareResult) {
|
||||
const { port, pid } = startMiddlewareResult;
|
||||
@@ -1560,15 +1511,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 +1587,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 +1769,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 +1843,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 +1949,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 +1961,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) {
|
||||
@@ -2256,18 +2223,22 @@ export default class DevServer {
|
||||
|
||||
const port = await getPort();
|
||||
|
||||
const env: Env = {
|
||||
// Because of child process 'pipe' below, isTTY will be false.
|
||||
// Most frameworks use `chalk`/`supports-color` so we enable it anyway.
|
||||
FORCE_COLOR: process.stdout.isTTY ? '1' : '0',
|
||||
// Prevent framework dev servers from automatically opening a web
|
||||
// browser window, since it will not be the port that `vc dev`
|
||||
// is listening on and thus will be missing Vercel features.
|
||||
BROWSER: 'none',
|
||||
...process.env,
|
||||
...this.envConfigs.allEnv,
|
||||
PORT: `${port}`,
|
||||
};
|
||||
const env: Env = cloneEnv(
|
||||
{
|
||||
// Because of child process 'pipe' below, isTTY will be false.
|
||||
// Most frameworks use `chalk`/`supports-color` so we enable it anyway.
|
||||
FORCE_COLOR: process.stdout.isTTY ? '1' : '0',
|
||||
// Prevent framework dev servers from automatically opening a web
|
||||
// browser window, since it will not be the port that `vc dev`
|
||||
// is listening on and thus will be missing Vercel features.
|
||||
BROWSER: 'none',
|
||||
},
|
||||
process.env,
|
||||
this.envConfigs.allEnv,
|
||||
{
|
||||
PORT: `${port}`,
|
||||
}
|
||||
);
|
||||
|
||||
// This is necesary so that the dev command in the Project
|
||||
// will work cross-platform (especially Windows).
|
||||
@@ -2301,7 +2272,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 +2288,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 +2585,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();
|
||||
});
|
||||
|
||||
|
||||
@@ -457,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) => {
|
||||
@@ -477,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) => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -12,6 +12,8 @@ import vercelNodePkg from '@vercel/node/package.json';
|
||||
|
||||
jest.setTimeout(ms('30 seconds'));
|
||||
|
||||
const repoRoot = join(__dirname, '../../../../../..');
|
||||
|
||||
describe('importBuilders()', () => {
|
||||
it('should import built-in Builders', async () => {
|
||||
const specs = new Set(['@vercel/node', '@vercel/next']);
|
||||
@@ -19,6 +21,12 @@ describe('importBuilders()', () => {
|
||||
expect(builders.size).toEqual(2);
|
||||
expect(builders.get('@vercel/node')?.pkg).toMatchObject(vercelNodePkg);
|
||||
expect(builders.get('@vercel/next')?.pkg).toMatchObject(vercelNextPkg);
|
||||
expect(builders.get('@vercel/node')?.pkgPath).toEqual(
|
||||
join(repoRoot, 'packages/node/package.json')
|
||||
);
|
||||
expect(builders.get('@vercel/next')?.pkgPath).toEqual(
|
||||
join(repoRoot, 'packages/next/package.json')
|
||||
);
|
||||
expect(typeof builders.get('@vercel/node')?.builder.build).toEqual(
|
||||
'function'
|
||||
);
|
||||
@@ -27,25 +35,124 @@ describe('importBuilders()', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should import 3rd party Builders', async () => {
|
||||
it('should import built-in Builders using `@latest`', async () => {
|
||||
const specs = new Set(['@vercel/node@latest', '@vercel/next@latest']);
|
||||
const builders = await importBuilders(specs, process.cwd(), client.output);
|
||||
expect(builders.size).toEqual(2);
|
||||
expect(builders.get('@vercel/node@latest')?.pkg).toMatchObject(
|
||||
vercelNodePkg
|
||||
);
|
||||
expect(builders.get('@vercel/next@latest')?.pkg).toMatchObject(
|
||||
vercelNextPkg
|
||||
);
|
||||
expect(builders.get('@vercel/node@latest')?.pkgPath).toEqual(
|
||||
join(repoRoot, 'packages/node/package.json')
|
||||
);
|
||||
expect(builders.get('@vercel/next@latest')?.pkgPath).toEqual(
|
||||
join(repoRoot, 'packages/next/package.json')
|
||||
);
|
||||
expect(typeof builders.get('@vercel/node@latest')?.builder.build).toEqual(
|
||||
'function'
|
||||
);
|
||||
expect(typeof builders.get('@vercel/next@latest')?.builder.build).toEqual(
|
||||
'function'
|
||||
);
|
||||
});
|
||||
|
||||
it('should import built-in Builders using `@canary`', async () => {
|
||||
const specs = new Set(['@vercel/node@canary', '@vercel/next@canary']);
|
||||
const builders = await importBuilders(specs, process.cwd(), client.output);
|
||||
expect(builders.size).toEqual(2);
|
||||
expect(builders.get('@vercel/node@canary')?.pkg).toMatchObject(
|
||||
vercelNodePkg
|
||||
);
|
||||
expect(builders.get('@vercel/next@canary')?.pkg).toMatchObject(
|
||||
vercelNextPkg
|
||||
);
|
||||
expect(builders.get('@vercel/node@canary')?.pkgPath).toEqual(
|
||||
join(repoRoot, 'packages/node/package.json')
|
||||
);
|
||||
expect(builders.get('@vercel/next@canary')?.pkgPath).toEqual(
|
||||
join(repoRoot, 'packages/next/package.json')
|
||||
);
|
||||
expect(typeof builders.get('@vercel/node@canary')?.builder.build).toEqual(
|
||||
'function'
|
||||
);
|
||||
expect(typeof builders.get('@vercel/next@canary')?.builder.build).toEqual(
|
||||
'function'
|
||||
);
|
||||
});
|
||||
|
||||
it('should install and import 1st party Builders with explicit version', 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 spec = '@vercel/node@2.0.0';
|
||||
const specs = new Set([spec]);
|
||||
const builders = await importBuilders(specs, cwd, client.output);
|
||||
expect(builders.size).toEqual(1);
|
||||
expect(builders.get(spec)?.pkg.name).toEqual('@vercel/node');
|
||||
expect(builders.get(spec)?.pkg.version).toEqual('2.0.0');
|
||||
expect(builders.get(spec)?.pkgPath).toEqual(
|
||||
join(cwd, '.vercel/builders/node_modules/@vercel/node/package.json')
|
||||
);
|
||||
expect(typeof builders.get(spec)?.builder.build).toEqual('function');
|
||||
await expect(client.stderr).toOutput(
|
||||
'> Installing Builder: @vercel/node'
|
||||
);
|
||||
} finally {
|
||||
await remove(cwd);
|
||||
}
|
||||
});
|
||||
|
||||
it('should install and 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 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(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 import legacy `@now/build-utils` Builders', async () => {
|
||||
it('should install and 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';
|
||||
@@ -62,6 +169,31 @@ describe('importBuilders()', () => {
|
||||
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'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveBuilders()', () => {
|
||||
|
||||
@@ -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.4",
|
||||
"version": "12.2.5",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://vercel.com",
|
||||
@@ -43,7 +43,7 @@
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/build-utils": "5.4.3",
|
||||
"@vercel/routing-utils": "2.0.2",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/frameworks",
|
||||
"version": "1.1.4",
|
||||
"version": "1.1.6",
|
||||
"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": "3.0.0",
|
||||
"version": "3.3.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.4",
|
||||
"@vercel/frameworks": "1.1.6",
|
||||
"@vercel/routing-utils": "2.0.2",
|
||||
"glob": "8.0.3",
|
||||
"js-yaml": "4.1.0",
|
||||
|
||||
@@ -125,4 +125,15 @@ export abstract class DetectorFilesystem {
|
||||
public chdir = (name: string): DetectorFilesystem => {
|
||||
return this._chdir(name);
|
||||
};
|
||||
|
||||
/**
|
||||
* Writes a file to the filesystem cache.
|
||||
* @param name the name of the file to write
|
||||
* @param content The content of the file
|
||||
*/
|
||||
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,9 @@ export async function getWorkspacePackagePaths({
|
||||
case 'pnpm':
|
||||
results = await getPnpmWorkspacePackagePaths({ fs: workspaceFs });
|
||||
break;
|
||||
case 'nx':
|
||||
results = await getNxWorkspacePackagePaths({ fs: workspaceFs });
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown workspace implementation: ${type}`);
|
||||
}
|
||||
@@ -103,6 +106,17 @@ async function getPackageJsonWorkspacePackagePaths({
|
||||
return getPackagePaths(packages, fs);
|
||||
}
|
||||
|
||||
async function getNxWorkspacePackagePaths({
|
||||
fs,
|
||||
}: GetPackagePathOptions): Promise<string[]> {
|
||||
const nxWorkspaceJsonAsBuffer = await fs.readFile('workspace.json');
|
||||
|
||||
const { projects } = JSON.parse(nxWorkspaceJsonAsBuffer.toString());
|
||||
|
||||
const packages: string[] = Object.values(projects);
|
||||
return getPackagePaths(packages, fs);
|
||||
}
|
||||
|
||||
async function getPnpmWorkspacePackagePaths({
|
||||
fs,
|
||||
}: GetPackagePathOptions): Promise<string[]> {
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface GetWorkspaceOptions {
|
||||
cwd?: string;
|
||||
}
|
||||
|
||||
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm';
|
||||
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm' | 'nx';
|
||||
|
||||
export type Workspace = {
|
||||
type: WorkspaceType;
|
||||
|
||||
@@ -59,6 +59,18 @@ export const workspaceManagers: Array<
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'nx',
|
||||
slug: 'nx',
|
||||
detectors: {
|
||||
every: [
|
||||
{
|
||||
path: 'workspace.json',
|
||||
matchContent: '"projects":\\s*{[^}]',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
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": []
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/41-nx-workspace/apps/app-one/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/41-nx-workspace/apps/app-one/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "b",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/41-nx-workspace/apps/app-two/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/41-nx-workspace/apps/app-two/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "b",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
}
|
||||
7
packages/fs-detectors/test/fixtures/41-nx-workspace/workspace.json
vendored
Normal file
7
packages/fs-detectors/test/fixtures/41-nx-workspace/workspace.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 2,
|
||||
"projects": {
|
||||
"myblog": "apps/app-one",
|
||||
"svelte-app": "apps/app-two"
|
||||
}
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/apps/app-one/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/apps/app-one/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "b",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/apps/app-two/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/apps/app-two/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "b",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
}
|
||||
782
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/package-lock.json
generated
vendored
Normal file
782
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,782 @@
|
||||
{
|
||||
"name": "42-npm-workspace-with-nx",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "1.0.0",
|
||||
"workspaces": [
|
||||
"apps/app-one",
|
||||
"apps/app-two"
|
||||
]
|
||||
},
|
||||
"apps/app-one": {
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.2"
|
||||
}
|
||||
},
|
||||
"apps/app-two": {
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/a": {
|
||||
"resolved": "a",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dependencies": {
|
||||
"color-convert": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/b": {
|
||||
"resolved": "b",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
||||
"dependencies": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui/node_modules/ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui/node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui/node_modules/string-width": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui/node_modules/strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dependencies": {
|
||||
"color-name": "~1.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/cowsay": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/cowsay/-/cowsay-1.5.0.tgz",
|
||||
"integrity": "sha512-8Ipzr54Z8zROr/62C8f0PdhQcDusS05gKTS87xxdji8VbWefWly0k8BwGK7+VqamOrkv3eGsCkPtvlHzrhWsCA==",
|
||||
"dependencies": {
|
||||
"get-stdin": "8.0.0",
|
||||
"string-width": "~2.1.1",
|
||||
"strip-final-newline": "2.0.0",
|
||||
"yargs": "15.4.1"
|
||||
},
|
||||
"bin": {
|
||||
"cowsay": "cli.js",
|
||||
"cowthink": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"node_modules/find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"dependencies": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||
"engines": {
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stdin": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
|
||||
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"dependencies": {
|
||||
"p-locate": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"dependencies": {
|
||||
"p-try": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"dependencies": {
|
||||
"p-limit": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/require-main-filename": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
|
||||
},
|
||||
"node_modules/set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
||||
"dependencies": {
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-final-newline": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
|
||||
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/which-module": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
||||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/string-width": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi/node_modules/strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/y18n": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "15.4.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
||||
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
||||
"dependencies": {
|
||||
"cliui": "^6.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^4.1.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^4.2.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^18.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs-parser": {
|
||||
"version": "18.1.3",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||
"dependencies": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs/node_modules/ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs/node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs/node_modules/string-width": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs/node_modules/strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"a": {
|
||||
"version": "file:a",
|
||||
"requires": {
|
||||
"debug": "^4.3.2"
|
||||
}
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"b": {
|
||||
"version": "file:b",
|
||||
"requires": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
||||
},
|
||||
"cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
||||
"requires": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^6.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"cowsay": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/cowsay/-/cowsay-1.5.0.tgz",
|
||||
"integrity": "sha512-8Ipzr54Z8zROr/62C8f0PdhQcDusS05gKTS87xxdji8VbWefWly0k8BwGK7+VqamOrkv3eGsCkPtvlHzrhWsCA==",
|
||||
"requires": {
|
||||
"get-stdin": "8.0.0",
|
||||
"string-width": "~2.1.1",
|
||||
"strip-final-newline": "2.0.0",
|
||||
"yargs": "15.4.1"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"requires": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
||||
},
|
||||
"get-stdin": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz",
|
||||
"integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"requires": {
|
||||
"p-locate": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"requires": {
|
||||
"p-limit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
||||
"requires": {
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"strip-final-newline": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
|
||||
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="
|
||||
},
|
||||
"which-module": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
||||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||
"requires": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "15.4.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
|
||||
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
|
||||
"requires": {
|
||||
"cliui": "^6.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^4.1.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^4.2.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^18.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz",
|
||||
"integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==",
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "18.1.3",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/package.json
vendored
Normal file
8
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/package.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "42-npm-workspace-with-nx",
|
||||
"version": "1.0.0",
|
||||
"workspaces": [
|
||||
"apps/app-one",
|
||||
"apps/app-two"
|
||||
]
|
||||
}
|
||||
4
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/workspace.json
vendored
Normal file
4
packages/fs-detectors/test/fixtures/42-npm-workspace-with-nx/workspace.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"version": 2,
|
||||
"projects": {}
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/apps/app-one/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/apps/app-one/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "b",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/apps/app-two/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/apps/app-two/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "b",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
}
|
||||
3
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/workspace.json
vendored
Normal file
3
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/workspace.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"version": 2
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/44-nx-json-string/apps/app-one/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/44-nx-json-string/apps/app-one/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "b",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/44-nx-json-string/apps/app-two/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/44-nx-json-string/apps/app-two/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "b",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"cowsay": "^1.5.0"
|
||||
}
|
||||
}
|
||||
4
packages/fs-detectors/test/fixtures/44-nx-json-string/workspace.json
vendored
Normal file
4
packages/fs-detectors/test/fixtures/44-nx-json-string/workspace.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"version": 2,
|
||||
"projects": "hello"
|
||||
}
|
||||
@@ -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}`
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import path from 'path';
|
||||
import frameworkList from '@vercel/frameworks';
|
||||
import workspaceManagers from '../src/workspaces/workspace-managers';
|
||||
import { detectFramework, DetectorFilesystem } from '../src';
|
||||
import { Stat } from '../src/detectors/filesystem';
|
||||
|
||||
@@ -173,6 +174,24 @@ describe('DetectorFilesystem', () => {
|
||||
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');
|
||||
|
||||
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 () => {
|
||||
const nextPackageJson = JSON.stringify({
|
||||
dependencies: {
|
||||
@@ -253,6 +272,28 @@ describe('DetectorFilesystem', () => {
|
||||
expect(await detectFramework({ fs, frameworkList })).toBe(null);
|
||||
});
|
||||
|
||||
it('Detect nx', async () => {
|
||||
const fs = new VirtualFilesystem({
|
||||
'workspace.json': JSON.stringify({
|
||||
projects: { 'app-one': 'apps/app-one' },
|
||||
}),
|
||||
});
|
||||
|
||||
expect(
|
||||
await detectFramework({ fs, frameworkList: workspaceManagers })
|
||||
).toBe('nx');
|
||||
});
|
||||
|
||||
it('Do not detect anything', async () => {
|
||||
const fs = new VirtualFilesystem({
|
||||
'workspace.json': JSON.stringify({ projects: {} }),
|
||||
});
|
||||
|
||||
expect(
|
||||
await detectFramework({ fs, frameworkList: workspaceManagers })
|
||||
).toBe(null);
|
||||
});
|
||||
|
||||
it('Detect Next.js', async () => {
|
||||
const fs = new VirtualFilesystem({
|
||||
'package.json': JSON.stringify({
|
||||
|
||||
@@ -14,6 +14,10 @@ describe.each<[string, string[]]>([
|
||||
['/backend/c', '/backend/d', '/frontend/a', '/frontend/b'],
|
||||
],
|
||||
['22-pnpm', []],
|
||||
['41-nx-workspace', ['/apps/app-one', '/apps/app-two']],
|
||||
['42-npm-workspace-with-nx', ['/apps/app-one', '/apps/app-two']],
|
||||
['43-nx-json-misshaped', []],
|
||||
['44-nx-json-string', []],
|
||||
])('`getWorkspacesPackagePaths()`', (fixturePath, packagePaths) => {
|
||||
const testName =
|
||||
packagePaths.length > 0
|
||||
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
getWriteableDirectory,
|
||||
shouldServe,
|
||||
debug,
|
||||
cloneEnv,
|
||||
} from '@vercel/build-utils';
|
||||
|
||||
const TMP = tmpdir();
|
||||
@@ -694,11 +695,9 @@ Learn more: https://vercel.com/docs/runtimes#official-runtimes/go`
|
||||
`vercel-dev-port-${Math.random().toString(32).substring(2)}`
|
||||
);
|
||||
|
||||
const env: typeof process.env = {
|
||||
...process.env,
|
||||
...meta.env,
|
||||
const env = cloneEnv(process.env, meta.env, {
|
||||
VERCEL_DEV_PORT_FILE: portFile,
|
||||
};
|
||||
});
|
||||
|
||||
const tmpRelative = `.${sep}${entrypointDir}`;
|
||||
const child = spawn('go', ['run', tmpRelative], {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/go",
|
||||
"version": "2.2.5",
|
||||
"version": "2.2.6",
|
||||
"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.2",
|
||||
"@vercel/build-utils": "5.4.3",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"async-retry": "1.3.1",
|
||||
"execa": "^1.0.0",
|
||||
|
||||
10
packages/go/test/fixtures/25-square-brackets-with-go-mod/api/[hello].go
vendored
Normal file
10
packages/go/test/fixtures/25-square-brackets-with-go-mod/api/[hello].go
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func Handler(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "hello:RANDOMNESS_PLACEHOLDER")
|
||||
}
|
||||
10
packages/go/test/fixtures/25-square-brackets-with-go-mod/api/sub/[hi].go
vendored
Normal file
10
packages/go/test/fixtures/25-square-brackets-with-go-mod/api/sub/[hi].go
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func Handler(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "hi:RANDOMNESS_PLACEHOLDER")
|
||||
}
|
||||
3
packages/go/test/fixtures/25-square-brackets-with-go-mod/go.mod
vendored
Normal file
3
packages/go/test/fixtures/25-square-brackets-with-go-mod/go.mod
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
module github.com/vercel/vercel/packages/go/test/fixtures/21-square-brackets-with-go-mod
|
||||
|
||||
go 1.16
|
||||
0
packages/go/test/fixtures/25-square-brackets-with-go-mod/go.sum
vendored
Normal file
0
packages/go/test/fixtures/25-square-brackets-with-go-mod/go.sum
vendored
Normal file
9
packages/go/test/fixtures/25-square-brackets-with-go-mod/probes.json
vendored
Normal file
9
packages/go/test/fixtures/25-square-brackets-with-go-mod/probes.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"probes": [
|
||||
{
|
||||
"path": "/api/a",
|
||||
"mustContain": "hello:RANDOMNESS_PLACEHOLDER"
|
||||
},
|
||||
{ "path": "/api/sub/b", "mustContain": "hi:RANDOMNESS_PLACEHOLDER" }
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/hydrogen",
|
||||
"version": "0.0.18",
|
||||
"version": "0.0.19",
|
||||
"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.2",
|
||||
"@vercel/build-utils": "5.4.3",
|
||||
"typescript": "4.6.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/next",
|
||||
"version": "3.1.25",
|
||||
"version": "3.1.26",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
|
||||
@@ -8,7 +8,7 @@
|
||||
"build": "node build.js",
|
||||
"build-dev": "node build.js --dev",
|
||||
"test": "jest --env node --verbose --bail --runInBand",
|
||||
"test-unit": "yarn test test/build.test.ts test/unit/",
|
||||
"test-unit": "yarn test test/unit/",
|
||||
"test-next-local": "jest --env node --verbose --bail --forceExit --testTimeout=360000 test/integration/*.test.js test/integration/*.test.ts",
|
||||
"test-next-local:middleware": "jest --env node --verbose --bail --useStderr --testTimeout=360000 test/integration/middleware.test.ts",
|
||||
"test-integration-once": "rm test/builder-info.json; jest --env node --verbose --runInBand --bail test/fixtures/**/*.test.js"
|
||||
@@ -44,7 +44,7 @@
|
||||
"@types/semver": "6.0.0",
|
||||
"@types/text-table": "0.2.1",
|
||||
"@types/webpack-sources": "3.2.0",
|
||||
"@vercel/build-utils": "5.4.2",
|
||||
"@vercel/build-utils": "5.4.3",
|
||||
"@vercel/nft": "0.22.1",
|
||||
"@vercel/routing-utils": "2.0.2",
|
||||
"async-sema": "3.0.1",
|
||||
|
||||
@@ -675,7 +675,7 @@ export const build: BuildV2 = async ({
|
||||
}
|
||||
}
|
||||
|
||||
let dynamicPrefix = path.join('/', entryDirectory);
|
||||
let dynamicPrefix = path.posix.join('/', entryDirectory);
|
||||
dynamicPrefix = dynamicPrefix === '/' ? '' : dynamicPrefix;
|
||||
|
||||
if (imagesManifest) {
|
||||
@@ -824,7 +824,7 @@ export const build: BuildV2 = async ({
|
||||
|
||||
// Make sure to 404 for the /404 path itself
|
||||
{
|
||||
src: path.join('/', entryDirectory, '404/?'),
|
||||
src: path.posix.join('/', entryDirectory, '404/?'),
|
||||
status: 404,
|
||||
continue: true,
|
||||
},
|
||||
@@ -838,7 +838,7 @@ export const build: BuildV2 = async ({
|
||||
...(routesManifest?.basePath
|
||||
? [
|
||||
{
|
||||
src: path.join('/', entryDirectory, '_next/image/?'),
|
||||
src: path.posix.join('/', entryDirectory, '_next/image/?'),
|
||||
dest: '/_next/image',
|
||||
check: true,
|
||||
},
|
||||
@@ -848,12 +848,12 @@ export const build: BuildV2 = async ({
|
||||
// No-op _next/data rewrite to trigger handle: 'rewrites' and then 404
|
||||
// if no match to prevent rewriting _next/data unexpectedly
|
||||
{
|
||||
src: path.join('/', entryDirectory, '_next/data/(.*)'),
|
||||
dest: path.join('/', entryDirectory, '_next/data/$1'),
|
||||
src: path.posix.join('/', entryDirectory, '_next/data/(.*)'),
|
||||
dest: path.posix.join('/', entryDirectory, '_next/data/$1'),
|
||||
check: true,
|
||||
},
|
||||
{
|
||||
src: path.join('/', entryDirectory, '_next/data/(.*)'),
|
||||
src: path.posix.join('/', entryDirectory, '_next/data/(.*)'),
|
||||
status: 404,
|
||||
},
|
||||
|
||||
@@ -867,14 +867,14 @@ export const build: BuildV2 = async ({
|
||||
|
||||
...fallbackRewrites,
|
||||
|
||||
{ src: path.join('/', entryDirectory, '.*'), status: 404 },
|
||||
{ src: path.posix.join('/', entryDirectory, '.*'), status: 404 },
|
||||
|
||||
// We need to make sure to 404 for /_next after handle: miss since
|
||||
// handle: miss is called before rewrites and to prevent rewriting
|
||||
// /_next
|
||||
{ handle: 'miss' },
|
||||
{
|
||||
src: path.join(
|
||||
src: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|image|media)/.+'
|
||||
@@ -894,7 +894,7 @@ export const build: BuildV2 = async ({
|
||||
{
|
||||
// This ensures we only match known emitted-by-Next.js files and not
|
||||
// user-emitted files which may be missing a hash in their filename.
|
||||
src: path.join(
|
||||
src: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
`_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|image|media|${escapedBuildId})/.+`
|
||||
@@ -909,15 +909,15 @@ export const build: BuildV2 = async ({
|
||||
},
|
||||
|
||||
// error handling
|
||||
...(output[path.join('./', entryDirectory, '404')] ||
|
||||
output[path.join('./', entryDirectory, '404/index')]
|
||||
...(output[path.posix.join('./', entryDirectory, '404')] ||
|
||||
output[path.posix.join('./', entryDirectory, '404/index')]
|
||||
? [
|
||||
{ handle: 'error' } as RouteWithHandle,
|
||||
|
||||
{
|
||||
status: 404,
|
||||
src: path.join(entryDirectory, '.*'),
|
||||
dest: path.join('/', entryDirectory, '404'),
|
||||
src: path.posix.join(entryDirectory, '.*'),
|
||||
dest: path.posix.join('/', entryDirectory, '404'),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
@@ -1063,7 +1063,7 @@ export const build: BuildV2 = async ({
|
||||
}
|
||||
|
||||
debug(`Creating serverless function for page: "${page}"...`);
|
||||
lambdas[path.join(entryDirectory, pathname)] = new NodejsLambda({
|
||||
lambdas[path.posix.join(entryDirectory, pathname)] = new NodejsLambda({
|
||||
files: {
|
||||
...nextFiles,
|
||||
...pageFiles,
|
||||
@@ -1114,30 +1114,32 @@ export const build: BuildV2 = async ({
|
||||
prerenderManifest,
|
||||
routesManifest
|
||||
);
|
||||
hasStatic500 = !!staticPages[path.join(entryDirectory, '500')];
|
||||
hasStatic500 = !!staticPages[path.posix.join(entryDirectory, '500')];
|
||||
|
||||
// this can be either 404.html in latest versions
|
||||
// or _errors/404.html versions while this was experimental
|
||||
static404Page =
|
||||
staticPages[path.join(entryDirectory, '404')] && hasPages404
|
||||
? path.join(entryDirectory, '404')
|
||||
: staticPages[path.join(entryDirectory, '_errors/404')]
|
||||
? path.join(entryDirectory, '_errors/404')
|
||||
staticPages[path.posix.join(entryDirectory, '404')] && hasPages404
|
||||
? path.posix.join(entryDirectory, '404')
|
||||
: staticPages[path.posix.join(entryDirectory, '_errors/404')]
|
||||
? path.posix.join(entryDirectory, '_errors/404')
|
||||
: undefined;
|
||||
|
||||
const { i18n } = routesManifest || {};
|
||||
|
||||
if (!static404Page && i18n) {
|
||||
static404Page = staticPages[
|
||||
path.join(entryDirectory, i18n.defaultLocale, '404')
|
||||
path.posix.join(entryDirectory, i18n.defaultLocale, '404')
|
||||
]
|
||||
? path.join(entryDirectory, i18n.defaultLocale, '404')
|
||||
? path.posix.join(entryDirectory, i18n.defaultLocale, '404')
|
||||
: undefined;
|
||||
}
|
||||
|
||||
if (!hasStatic500 && i18n) {
|
||||
hasStatic500 =
|
||||
!!staticPages[path.join(entryDirectory, i18n.defaultLocale, '500')];
|
||||
!!staticPages[
|
||||
path.posix.join(entryDirectory, i18n.defaultLocale, '500')
|
||||
];
|
||||
}
|
||||
|
||||
if (routesManifest) {
|
||||
@@ -1171,7 +1173,7 @@ export const build: BuildV2 = async ({
|
||||
src: (
|
||||
dataRoute.namedDataRouteRegex || dataRoute.dataRouteRegex
|
||||
).replace(/^\^/, `^${appMountPrefixNoTrailingSlash}`),
|
||||
dest: path.join(
|
||||
dest: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
// make sure to route SSG data route to the data prerender
|
||||
|
||||
@@ -169,7 +169,7 @@ export async function serverBuild({
|
||||
CORRECTED_MANIFESTS_VERSION
|
||||
);
|
||||
|
||||
let hasStatic500 = !!staticPages[path.join(entryDirectory, '500')];
|
||||
let hasStatic500 = !!staticPages[path.posix.join(entryDirectory, '500')];
|
||||
|
||||
if (lambdaPageKeys.length === 0) {
|
||||
throw new NowBuildError({
|
||||
@@ -187,23 +187,23 @@ export async function serverBuild({
|
||||
const hasPages404 = routesManifest.pages404;
|
||||
|
||||
let static404Page =
|
||||
staticPages[path.join(entryDirectory, '404')] && hasPages404
|
||||
? path.join(entryDirectory, '404')
|
||||
: staticPages[path.join(entryDirectory, '_errors/404')]
|
||||
? path.join(entryDirectory, '_errors/404')
|
||||
staticPages[path.posix.join(entryDirectory, '404')] && hasPages404
|
||||
? path.posix.join(entryDirectory, '404')
|
||||
: staticPages[path.posix.join(entryDirectory, '_errors/404')]
|
||||
? path.posix.join(entryDirectory, '_errors/404')
|
||||
: undefined;
|
||||
|
||||
if (!static404Page && i18n) {
|
||||
static404Page = staticPages[
|
||||
path.join(entryDirectory, i18n.defaultLocale, '404')
|
||||
path.posix.join(entryDirectory, i18n.defaultLocale, '404')
|
||||
]
|
||||
? path.join(entryDirectory, i18n.defaultLocale, '404')
|
||||
? path.posix.join(entryDirectory, i18n.defaultLocale, '404')
|
||||
: undefined;
|
||||
}
|
||||
|
||||
if (!hasStatic500 && i18n) {
|
||||
hasStatic500 =
|
||||
!!staticPages[path.join(entryDirectory, i18n.defaultLocale, '500')];
|
||||
!!staticPages[path.posix.join(entryDirectory, i18n.defaultLocale, '500')];
|
||||
}
|
||||
|
||||
const lstatSema = new Sema(25);
|
||||
@@ -377,7 +377,7 @@ export async function serverBuild({
|
||||
if (i18n) {
|
||||
for (const locale of i18n.locales) {
|
||||
const static404File =
|
||||
staticPages[path.join(entryDirectory, locale, '/404')] ||
|
||||
staticPages[path.posix.join(entryDirectory, locale, '/404')] ||
|
||||
new FileFsRef({
|
||||
fsPath: path.join(pagesDir, locale, '/404.html'),
|
||||
});
|
||||
@@ -520,14 +520,14 @@ export async function serverBuild({
|
||||
|
||||
if (
|
||||
entryDirectory !== '.' &&
|
||||
path.join('/', entryDirectory) !== routesManifest.basePath
|
||||
path.posix.join('/', entryDirectory) !== routesManifest.basePath
|
||||
) {
|
||||
// we normalize the entryDirectory in the request URL since
|
||||
// Next.js isn't aware of it and it isn't included in the
|
||||
// x-matched-path header
|
||||
launcher = launcher.replace(
|
||||
'// entryDirectory handler',
|
||||
`req.url = req.url.replace(/^${path
|
||||
`req.url = req.url.replace(/^${path.posix
|
||||
.join('/', entryDirectory)
|
||||
.replace(/\//g, '\\/')}/, '')`
|
||||
);
|
||||
@@ -848,7 +848,7 @@ export async function serverBuild({
|
||||
}
|
||||
|
||||
const outputName = normalizeIndexOutput(
|
||||
path.join(entryDirectory, pageNoExt),
|
||||
path.posix.join(entryDirectory, pageNoExt),
|
||||
true
|
||||
);
|
||||
|
||||
@@ -863,7 +863,7 @@ export async function serverBuild({
|
||||
for (const locale of i18n.locales) {
|
||||
lambdas[
|
||||
normalizeIndexOutput(
|
||||
path.join(
|
||||
path.posix.join(
|
||||
entryDirectory,
|
||||
locale,
|
||||
pageNoExt === 'index' ? '' : pageNoExt
|
||||
@@ -918,7 +918,7 @@ export async function serverBuild({
|
||||
route = normalizeLocalePath(route, routesManifest.i18n.locales).pathname;
|
||||
}
|
||||
delete lambdas[
|
||||
path.join('.', entryDirectory, route === '/' ? 'index' : route)
|
||||
path.posix.join('.', entryDirectory, route === '/' ? 'index' : route)
|
||||
];
|
||||
});
|
||||
|
||||
@@ -968,7 +968,7 @@ export async function serverBuild({
|
||||
// routes since only the status is being modified and we don't want
|
||||
// to exceed the routes limit
|
||||
const starterRouteSrc = `^${
|
||||
entryDirectory !== '.' ? path.join('/', entryDirectory, '()') : '()'
|
||||
entryDirectory !== '.' ? path.posix.join('/', entryDirectory, '()') : '()'
|
||||
}`;
|
||||
let currentRouteSrc = starterRouteSrc;
|
||||
|
||||
@@ -1019,14 +1019,14 @@ export async function serverBuild({
|
||||
? [
|
||||
// strip _next/data prefix for resolving
|
||||
{
|
||||
src: `^${path.join(
|
||||
src: `^${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/_next/data/',
|
||||
escapedBuildId,
|
||||
'/(.*).json'
|
||||
)}`,
|
||||
dest: `${path.join(
|
||||
dest: `${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/$1',
|
||||
@@ -1044,14 +1044,18 @@ export async function serverBuild({
|
||||
// normalize "/index" from "/_next/data/index.json" to -> just "/"
|
||||
// as matches a rewrite sources will expect just "/"
|
||||
{
|
||||
src: path.join('^/', entryDirectory, '/index(?:/)?'),
|
||||
src: path.posix.join('^/', entryDirectory, '/index(?:/)?'),
|
||||
has: [
|
||||
{
|
||||
type: 'header',
|
||||
key: 'x-nextjs-data',
|
||||
},
|
||||
],
|
||||
dest: path.join('/', entryDirectory, trailingSlash ? '/' : ''),
|
||||
dest: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
trailingSlash ? '/' : ''
|
||||
),
|
||||
...(isOverride ? { override: true } : {}),
|
||||
continue: true,
|
||||
},
|
||||
@@ -1063,14 +1067,19 @@ export async function serverBuild({
|
||||
return isNextDataServerResolving
|
||||
? [
|
||||
{
|
||||
src: path.join('^/', entryDirectory, trailingSlash ? '/' : '', '$'),
|
||||
src: path.posix.join(
|
||||
'^/',
|
||||
entryDirectory,
|
||||
trailingSlash ? '/' : '',
|
||||
'$'
|
||||
),
|
||||
has: [
|
||||
{
|
||||
type: 'header',
|
||||
key: 'x-nextjs-data',
|
||||
},
|
||||
],
|
||||
dest: `${path.join(
|
||||
dest: `${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/_next/data/',
|
||||
@@ -1081,7 +1090,7 @@ export async function serverBuild({
|
||||
...(isOverride ? { override: true } : {}),
|
||||
},
|
||||
{
|
||||
src: path.join(
|
||||
src: path.posix.join(
|
||||
'^/',
|
||||
entryDirectory,
|
||||
'((?!_next/)(?:.*[^/]|.*))/?$'
|
||||
@@ -1092,7 +1101,7 @@ export async function serverBuild({
|
||||
key: 'x-nextjs-data',
|
||||
},
|
||||
],
|
||||
dest: `${path.join(
|
||||
dest: `${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/_next/data/',
|
||||
@@ -1176,7 +1185,7 @@ export async function serverBuild({
|
||||
// Handle auto-adding current default locale to path based on
|
||||
// $wildcard
|
||||
{
|
||||
src: `^${path.join(
|
||||
src: `^${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/'
|
||||
@@ -1186,7 +1195,9 @@ export async function serverBuild({
|
||||
// we aren't able to ensure trailing slash mode here
|
||||
// so ensure this comes after the trailing slash redirect
|
||||
dest: `${
|
||||
entryDirectory !== '.' ? path.join('/', entryDirectory) : ''
|
||||
entryDirectory !== '.'
|
||||
? path.posix.join('/', entryDirectory)
|
||||
: ''
|
||||
}$wildcard/$1`,
|
||||
continue: true,
|
||||
},
|
||||
@@ -1197,7 +1208,10 @@ export async function serverBuild({
|
||||
i18n.localeDetection !== false
|
||||
? [
|
||||
{
|
||||
src: `^${path.join('/', entryDirectory)}/?(?:${i18n.locales
|
||||
src: `^${path.posix.join(
|
||||
'/',
|
||||
entryDirectory
|
||||
)}/?(?:${i18n.locales
|
||||
.map(locale => escapeStringRegexp(locale))
|
||||
.join('|')})?/?$`,
|
||||
locale: {
|
||||
@@ -1251,8 +1265,12 @@ export async function serverBuild({
|
||||
: []),
|
||||
|
||||
{
|
||||
src: `^${path.join('/', entryDirectory)}$`,
|
||||
dest: `${path.join('/', entryDirectory, i18n.defaultLocale)}`,
|
||||
src: `^${path.posix.join('/', entryDirectory)}$`,
|
||||
dest: `${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
i18n.defaultLocale
|
||||
)}`,
|
||||
continue: true,
|
||||
},
|
||||
|
||||
@@ -1262,14 +1280,18 @@ export async function serverBuild({
|
||||
// e.g. for /de/posts/[slug] x-now-route-matches would have
|
||||
// 1=posts%2Fpost-1
|
||||
{
|
||||
src: `^${path.join(
|
||||
src: `^${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/'
|
||||
)}(?!(?:_next/.*|${i18n.locales
|
||||
.map(locale => escapeStringRegexp(locale))
|
||||
.join('|')})(?:/.*|$))(.*)$`,
|
||||
dest: `${path.join('/', entryDirectory, i18n.defaultLocale)}/$1`,
|
||||
dest: `${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
i18n.defaultLocale
|
||||
)}/$1`,
|
||||
continue: true,
|
||||
},
|
||||
]
|
||||
@@ -1293,7 +1315,11 @@ export async function serverBuild({
|
||||
...(i18n
|
||||
? [
|
||||
{
|
||||
src: `${path.join('/', entryDirectory, '/')}(?:${i18n.locales
|
||||
src: `${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/'
|
||||
)}(?:${i18n.locales
|
||||
.map(locale => escapeStringRegexp(locale))
|
||||
.join('|')})?[/]?404/?`,
|
||||
status: 404,
|
||||
@@ -1302,7 +1328,7 @@ export async function serverBuild({
|
||||
]
|
||||
: [
|
||||
{
|
||||
src: path.join('/', entryDirectory, '404/?'),
|
||||
src: path.posix.join('/', entryDirectory, '404/?'),
|
||||
status: 404,
|
||||
continue: true,
|
||||
},
|
||||
@@ -1314,7 +1340,11 @@ export async function serverBuild({
|
||||
: i18n
|
||||
? [
|
||||
{
|
||||
src: `${path.join('/', entryDirectory, '/')}(?:${i18n.locales
|
||||
src: `${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/'
|
||||
)}(?:${i18n.locales
|
||||
.map(locale => escapeStringRegexp(locale))
|
||||
.join('|')})?[/]?500`,
|
||||
status: 500,
|
||||
@@ -1323,7 +1353,7 @@ export async function serverBuild({
|
||||
]
|
||||
: [
|
||||
{
|
||||
src: path.join('/', entryDirectory, '500'),
|
||||
src: path.posix.join('/', entryDirectory, '500'),
|
||||
status: 500,
|
||||
continue: true,
|
||||
},
|
||||
@@ -1346,7 +1376,7 @@ export async function serverBuild({
|
||||
...(routesManifest?.basePath
|
||||
? [
|
||||
{
|
||||
src: path.join('/', entryDirectory, '_next/image/?'),
|
||||
src: path.posix.join('/', entryDirectory, '_next/image/?'),
|
||||
dest: '/_next/image',
|
||||
check: true,
|
||||
},
|
||||
@@ -1361,8 +1391,8 @@ export async function serverBuild({
|
||||
// No-op _next/data rewrite to trigger handle: 'rewrites' and then 404
|
||||
// if no match to prevent rewriting _next/data unexpectedly
|
||||
{
|
||||
src: path.join('/', entryDirectory, '_next/data/(.*)'),
|
||||
dest: path.join('/', entryDirectory, '_next/data/$1'),
|
||||
src: path.posix.join('/', entryDirectory, '_next/data/(.*)'),
|
||||
dest: path.posix.join('/', entryDirectory, '_next/data/$1'),
|
||||
check: true,
|
||||
},
|
||||
]
|
||||
@@ -1378,13 +1408,13 @@ export async function serverBuild({
|
||||
|
||||
...fallbackRewrites,
|
||||
|
||||
{ src: path.join('/', entryDirectory, '.*'), status: 404 },
|
||||
{ src: path.posix.join('/', entryDirectory, '.*'), status: 404 },
|
||||
|
||||
// We need to make sure to 404 for /_next after handle: miss since
|
||||
// handle: miss is called before rewrites and to prevent rewriting /_next
|
||||
{ handle: 'miss' },
|
||||
{
|
||||
src: path.join(
|
||||
src: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|image|media)/.+'
|
||||
@@ -1399,10 +1429,10 @@ export async function serverBuild({
|
||||
...(i18n
|
||||
? [
|
||||
{
|
||||
src: `^${path.join('/', entryDirectory)}/?(?:${i18n.locales
|
||||
src: `^${path.posix.join('/', entryDirectory)}/?(?:${i18n.locales
|
||||
.map(locale => escapeStringRegexp(locale))
|
||||
.join('|')})/(.*)`,
|
||||
dest: `${path.join('/', entryDirectory, '/')}$1`,
|
||||
dest: `${path.posix.join('/', entryDirectory, '/')}$1`,
|
||||
check: true,
|
||||
},
|
||||
]
|
||||
@@ -1474,8 +1504,8 @@ export async function serverBuild({
|
||||
// ensure we 404 for non-existent _next/data routes before
|
||||
// trying page dynamic routes
|
||||
{
|
||||
src: path.join('/', entryDirectory, '_next/data/(.*)'),
|
||||
dest: path.join('/', entryDirectory, '404'),
|
||||
src: path.posix.join('/', entryDirectory, '_next/data/(.*)'),
|
||||
dest: path.posix.join('/', entryDirectory, '404'),
|
||||
status: 404,
|
||||
},
|
||||
]
|
||||
@@ -1488,7 +1518,7 @@ export async function serverBuild({
|
||||
...(isNextDataServerResolving
|
||||
? [
|
||||
{
|
||||
src: `^${path.join(
|
||||
src: `^${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/_next/data/',
|
||||
@@ -1504,7 +1534,7 @@ export async function serverBuild({
|
||||
// add a catch-all data route so we don't 404 when getting
|
||||
// middleware effects
|
||||
{
|
||||
src: `^${path.join(
|
||||
src: `^${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/_next/data/',
|
||||
@@ -1522,7 +1552,7 @@ export async function serverBuild({
|
||||
{
|
||||
// This ensures we only match known emitted-by-Next.js files and not
|
||||
// user-emitted files which may be missing a hash in their filename.
|
||||
src: path.join(
|
||||
src: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
`_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|image|media|${escapedBuildId})/.+`
|
||||
@@ -1539,7 +1569,7 @@ export async function serverBuild({
|
||||
// TODO: remove below workaround when `/` is allowed to be output
|
||||
// different than `/index`
|
||||
{
|
||||
src: path.join('/', entryDirectory, '/index'),
|
||||
src: path.posix.join('/', entryDirectory, '/index'),
|
||||
headers: {
|
||||
'x-matched-path': '/',
|
||||
},
|
||||
@@ -1547,7 +1577,7 @@ export async function serverBuild({
|
||||
important: true,
|
||||
},
|
||||
{
|
||||
src: path.join('/', entryDirectory, `/((?!index$).*)`),
|
||||
src: path.posix.join('/', entryDirectory, `/((?!index$).*)`),
|
||||
headers: {
|
||||
'x-matched-path': '/$1',
|
||||
},
|
||||
@@ -1562,20 +1592,20 @@ export async function serverBuild({
|
||||
...(i18n && (static404Page || hasIsr404Page || lambdaPages['404.js'])
|
||||
? [
|
||||
{
|
||||
src: `${path.join(
|
||||
src: `${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/'
|
||||
)}(?<nextLocale>${i18n.locales
|
||||
.map(locale => escapeStringRegexp(locale))
|
||||
.join('|')})(/.*|$)`,
|
||||
dest: path.join('/', entryDirectory, '/$nextLocale/404'),
|
||||
dest: path.posix.join('/', entryDirectory, '/$nextLocale/404'),
|
||||
status: 404,
|
||||
caseSensitive: true,
|
||||
},
|
||||
{
|
||||
src: path.join('/', entryDirectory, '.*'),
|
||||
dest: path.join(
|
||||
src: path.posix.join('/', entryDirectory, '.*'),
|
||||
dest: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
`/${i18n.defaultLocale}/404`
|
||||
@@ -1585,13 +1615,13 @@ export async function serverBuild({
|
||||
]
|
||||
: [
|
||||
{
|
||||
src: path.join('/', entryDirectory, '.*'),
|
||||
dest: path.join(
|
||||
src: path.posix.join('/', entryDirectory, '.*'),
|
||||
dest: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
static404Page ||
|
||||
hasIsr404Page ||
|
||||
lambdas[path.join(entryDirectory, '404')]
|
||||
lambdas[path.posix.join(entryDirectory, '404')]
|
||||
? '/404'
|
||||
: '/_error'
|
||||
),
|
||||
@@ -1603,20 +1633,20 @@ export async function serverBuild({
|
||||
...(i18n && (hasStatic500 || hasIsr500Page || lambdaPages['500.js'])
|
||||
? [
|
||||
{
|
||||
src: `${path.join(
|
||||
src: `${path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
'/'
|
||||
)}(?<nextLocale>${i18n.locales
|
||||
.map(locale => escapeStringRegexp(locale))
|
||||
.join('|')})(/.*|$)`,
|
||||
dest: path.join('/', entryDirectory, '/$nextLocale/500'),
|
||||
dest: path.posix.join('/', entryDirectory, '/$nextLocale/500'),
|
||||
status: 500,
|
||||
caseSensitive: true,
|
||||
},
|
||||
{
|
||||
src: path.join('/', entryDirectory, '.*'),
|
||||
dest: path.join(
|
||||
src: path.posix.join('/', entryDirectory, '.*'),
|
||||
dest: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
`/${i18n.defaultLocale}/500`
|
||||
@@ -1626,13 +1656,13 @@ export async function serverBuild({
|
||||
]
|
||||
: [
|
||||
{
|
||||
src: path.join('/', entryDirectory, '.*'),
|
||||
dest: path.join(
|
||||
src: path.posix.join('/', entryDirectory, '.*'),
|
||||
dest: path.posix.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
hasStatic500 ||
|
||||
hasIsr500Page ||
|
||||
lambdas[path.join(entryDirectory, '500')]
|
||||
lambdas[path.posix.join(entryDirectory, '500')]
|
||||
? '/500'
|
||||
: '/_error'
|
||||
),
|
||||
|
||||
@@ -290,7 +290,7 @@ export async function getDynamicRoutes(
|
||||
.map(({ page, regex }: { page: string; regex: string }) => {
|
||||
return {
|
||||
src: regex,
|
||||
dest: !isDev ? path.join('/', entryDirectory, page) : page,
|
||||
dest: !isDev ? path.posix.join('/', entryDirectory, page) : page,
|
||||
check: true,
|
||||
status:
|
||||
canUsePreviewMode && omittedRoutes?.has(page) ? 404 : undefined,
|
||||
@@ -315,7 +315,9 @@ export async function getDynamicRoutes(
|
||||
const { page, namedRegex, regex, routeKeys } = params;
|
||||
const route: RouteWithSrc = {
|
||||
src: namedRegex || regex,
|
||||
dest: `${!isDev ? path.join('/', entryDirectory, page) : page}${
|
||||
dest: `${
|
||||
!isDev ? path.posix.join('/', entryDirectory, page) : page
|
||||
}${
|
||||
routeKeys
|
||||
? `?${Object.keys(routeKeys)
|
||||
.map(key => `${routeKeys[key]}=$${key}`)
|
||||
@@ -410,7 +412,7 @@ export async function getDynamicRoutes(
|
||||
pageMatchers.forEach(pageMatcher => {
|
||||
// in `vercel dev` we don't need to prefix the destination
|
||||
const dest = !isDev
|
||||
? path.join('/', entryDirectory, pageMatcher.pageName)
|
||||
? path.posix.join('/', entryDirectory, pageMatcher.pageName)
|
||||
: pageMatcher.pageName;
|
||||
|
||||
if (pageMatcher && pageMatcher.matcher) {
|
||||
@@ -465,8 +467,8 @@ export function localizeDynamicRoutes(
|
||||
// ensure destination has locale prefix to match prerender output
|
||||
// path so that the prerender object is used
|
||||
route.dest = route.dest!.replace(
|
||||
`${path.join('/', entryDirectory, '/')}`,
|
||||
`${path.join('/', entryDirectory, '$nextLocale', '/')}`
|
||||
`${path.posix.join('/', entryDirectory, '/')}`,
|
||||
`${path.posix.join('/', entryDirectory, '$nextLocale', '/')}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -575,7 +577,7 @@ export function filterStaticPages(
|
||||
return;
|
||||
}
|
||||
|
||||
const staticRoute = path.join(entryDirectory, pathname);
|
||||
const staticRoute = path.posix.join(entryDirectory, pathname);
|
||||
|
||||
staticPages[staticRoute] = staticPageFiles[page];
|
||||
staticPages[staticRoute].contentType = htmlContentType;
|
||||
@@ -1616,11 +1618,11 @@ export const onPrerenderRouteInitial = (
|
||||
// if the 404 page used getStaticProps we need to update static404Page
|
||||
// since it wasn't populated from the staticPages group
|
||||
if (routeNoLocale === '/404') {
|
||||
static404Page = path.join(entryDirectory, routeKey);
|
||||
static404Page = path.posix.join(entryDirectory, routeKey);
|
||||
}
|
||||
|
||||
if (routeNoLocale === '/500') {
|
||||
static500Page = path.join(entryDirectory, routeKey);
|
||||
static500Page = path.posix.join(entryDirectory, routeKey);
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -1851,7 +1853,10 @@ export const onPrerenderRoute =
|
||||
'/',
|
||||
srcRoute == null
|
||||
? outputPathPageOrig
|
||||
: path.join(entryDirectory, srcRoute === '/' ? '/index' : srcRoute)
|
||||
: path.posix.join(
|
||||
entryDirectory,
|
||||
srcRoute === '/' ? '/index' : srcRoute
|
||||
)
|
||||
),
|
||||
isServerMode
|
||||
);
|
||||
@@ -2066,17 +2071,17 @@ export async function getStaticFiles(
|
||||
const publicDirectoryFiles: Record<string, FileFsRef> = {};
|
||||
|
||||
for (const file of Object.keys(nextStaticFiles)) {
|
||||
staticFiles[path.join(entryDirectory, `_next/static/${file}`)] =
|
||||
staticFiles[path.posix.join(entryDirectory, `_next/static/${file}`)] =
|
||||
nextStaticFiles[file];
|
||||
}
|
||||
|
||||
for (const file of Object.keys(staticFolderFiles)) {
|
||||
staticDirectoryFiles[path.join(entryDirectory, 'static', file)] =
|
||||
staticDirectoryFiles[path.posix.join(entryDirectory, 'static', file)] =
|
||||
staticFolderFiles[file];
|
||||
}
|
||||
|
||||
for (const file of Object.keys(publicFolderFiles)) {
|
||||
publicDirectoryFiles[path.join(entryDirectory, file)] =
|
||||
publicDirectoryFiles[path.posix.join(entryDirectory, file)] =
|
||||
publicFolderFiles[file];
|
||||
}
|
||||
|
||||
|
||||
10
packages/next/test/fixtures/00-app-dir/app/(newroot)/layout.js
vendored
Normal file
10
packages/next/test/fixtures/00-app-dir/app/(newroot)/layout.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
export default function Root({ children }) {
|
||||
return (
|
||||
<html className="this-is-another-document-html">
|
||||
<head>
|
||||
<title>{`hello world`}</title>
|
||||
</head>
|
||||
<body className="this-is-another-document-body">{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
export async function getServerSideProps() {
|
||||
return {
|
||||
props: {
|
||||
world: 'world',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default function Root({ children, world }) {
|
||||
return (
|
||||
<html className="this-is-another-document-html">
|
||||
<head>
|
||||
<title>{`hello ${world}`}</title>
|
||||
</head>
|
||||
<body className="this-is-another-document-body">{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
'client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
import style from './style.module.css';
|
||||
@@ -1,3 +1,5 @@
|
||||
'client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
import styles from './style.module.css';
|
||||
@@ -1,15 +1,7 @@
|
||||
export async function getServerSideProps({ params }) {
|
||||
return {
|
||||
props: {
|
||||
id: params.id,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default function DeploymentsPage(props) {
|
||||
return (
|
||||
<>
|
||||
<p>hello from app/dashboard/deployments/[id]. ID is: {props.id}</p>
|
||||
<p>hello from app/dashboard/deployments/[id]. ID is: {props.params.id}</p>
|
||||
</>
|
||||
);
|
||||
}
|
||||
8
packages/next/test/fixtures/00-app-dir/app/dashboard/deployments/layout.js
vendored
Normal file
8
packages/next/test/fixtures/00-app-dir/app/dashboard/deployments/layout.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export default function DeploymentsLayout({ message, children }) {
|
||||
return (
|
||||
<>
|
||||
<h2>Deployments hello</h2>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
export function getServerSideProps() {
|
||||
return {
|
||||
props: {
|
||||
message: 'hello',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default function DeploymentsLayout({ message, children }) {
|
||||
return (
|
||||
<>
|
||||
<h2>Deployments {message}</h2>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
'client';
|
||||
|
||||
export default function LazyComponent() {
|
||||
return (
|
||||
<>
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ClientComponent } from './test.client.js';
|
||||
import { ClientComponent } from './test.js';
|
||||
|
||||
export default function DashboardIndexPage() {
|
||||
return (
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user