mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 12:57:46 +00:00
Compare commits
71 Commits
@vercel/fs
...
@vercel/py
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8814fc1515 | ||
|
|
0d044b4eac | ||
|
|
f6bd1aa8c0 | ||
|
|
8cd84ec066 | ||
|
|
a8df231e4c | ||
|
|
f674842bed | ||
|
|
bf5cfa9a41 | ||
|
|
12121b7a71 | ||
|
|
baa56aed2c | ||
|
|
6f767367e4 | ||
|
|
0e4124f94c | ||
|
|
30503d0a3f | ||
|
|
6c9164f67d | ||
|
|
906b7a8f2c | ||
|
|
43499b13d8 | ||
|
|
7d6e56670f | ||
|
|
dba337f148 | ||
|
|
a825bc9540 | ||
|
|
f5486a8297 | ||
|
|
225e0a4de3 | ||
|
|
0ecfdc1325 | ||
|
|
628409d233 | ||
|
|
51d968314f | ||
|
|
b4e2cbc6e5 | ||
|
|
7323beea8e | ||
|
|
e4bb311144 | ||
|
|
288546659d | ||
|
|
822224e212 | ||
|
|
6b23950b65 | ||
|
|
1558f21e49 | ||
|
|
a6aee8b904 | ||
|
|
27f4034bdc | ||
|
|
e43b968fbe | ||
|
|
48eb720556 | ||
|
|
30e4d74db6 | ||
|
|
75840896ee | ||
|
|
9657bda86d | ||
|
|
4536029d42 | ||
|
|
a35654d047 | ||
|
|
f6a01a1af3 | ||
|
|
c2bca954e0 | ||
|
|
21701c3c3d | ||
|
|
7f4723b3f8 | ||
|
|
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 |
7
.github/workflows/publish.yml
vendored
7
.github/workflows/publish.yml
vendored
@@ -7,6 +7,11 @@ on:
|
||||
tags:
|
||||
- '!*'
|
||||
|
||||
env:
|
||||
TURBO_REMOTE_ONLY: 'true'
|
||||
TURBO_TEAM: 'vercel'
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Publish
|
||||
@@ -32,8 +37,10 @@ jobs:
|
||||
- name: Setup Node
|
||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||
uses: actions/setup-node@v3
|
||||
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
|
||||
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
|
||||
|
||||
27
.github/workflows/test-integration-cli.yml
vendored
27
.github/workflows/test-integration-cli.yml
vendored
@@ -8,6 +8,11 @@ on:
|
||||
- '!*'
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
TURBO_REMOTE_ONLY: 'true'
|
||||
TURBO_TEAM: 'vercel'
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: CLI
|
||||
@@ -19,28 +24,20 @@ jobs:
|
||||
node: [14]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Conditionally set remote env
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
run: |
|
||||
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
|
||||
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
|
||||
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
|
||||
env:
|
||||
VERCEL_TEAM_TOKEN: ${{ secrets.VERCEL_TEAM_TOKEN }}
|
||||
VERCEL_REGISTRATION_URL: ${{ secrets.VERCEL_REGISTRATION_URL }}
|
||||
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
|
||||
VERCEL_TEST_REGISTRATION_URL: ${{ secrets.VERCEL_TEST_REGISTRATION_URL }}
|
||||
|
||||
25
.github/workflows/test-unit.yml
vendored
25
.github/workflows/test-unit.yml
vendored
@@ -8,6 +8,11 @@ on:
|
||||
- '!*'
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
TURBO_REMOTE_ONLY: 'true'
|
||||
TURBO_TEAM: 'vercel'
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Unit
|
||||
@@ -19,25 +24,17 @@ jobs:
|
||||
node: [14]
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Conditionally set remote env
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
run: |
|
||||
echo "TURBO_REMOTE_ONLY=true" >> $GITHUB_ENV
|
||||
echo "TURBO_TEAM=vercel" >> $GITHUB_ENV
|
||||
echo "TURBO_TOKEN=${{ secrets.TURBO_TOKEN }}" >> $GITHUB_ENV
|
||||
- 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
|
||||
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
cache: 'yarn'
|
||||
- run: yarn install --network-timeout 1000000 --frozen-lockfile
|
||||
- run: yarn run build
|
||||
- run: yarn run lint
|
||||
|
||||
22
.github/workflows/test.yml
vendored
22
.github/workflows/test.yml
vendored
@@ -10,6 +10,9 @@ on:
|
||||
|
||||
env:
|
||||
NODE_VERSION: '14'
|
||||
TURBO_REMOTE_ONLY: 'true'
|
||||
TURBO_TEAM: 'vercel'
|
||||
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
@@ -20,9 +23,13 @@ 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
|
||||
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'yarn'
|
||||
@@ -52,12 +59,6 @@ jobs:
|
||||
matrix:
|
||||
include: ${{ fromJson(needs.setup.outputs['tests']) }}
|
||||
steps:
|
||||
- name: Conditionally set remote env
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
run: |
|
||||
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
|
||||
@@ -65,6 +66,7 @@ jobs:
|
||||
with:
|
||||
go-version: '1.13.15'
|
||||
- uses: actions/setup-node@v3
|
||||
timeout-minutes: 5 # See https://github.com/actions/cache/issues/810
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: 'yarn'
|
||||
@@ -84,8 +86,8 @@ jobs:
|
||||
shell: bash
|
||||
env:
|
||||
VERCEL_CLI_VERSION: ${{ needs.setup.outputs.dplUrl }}/tarballs/vercel.tgz
|
||||
VERCEL_TEAM_TOKEN: ${{ secrets.VERCEL_TEAM_TOKEN }}
|
||||
VERCEL_REGISTRATION_URL: ${{ secrets.VERCEL_REGISTRATION_URL }}
|
||||
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
|
||||
VERCEL_TEST_REGISTRATION_URL: ${{ secrets.VERCEL_TEST_REGISTRATION_URL }}
|
||||
FORCE_COLOR: '1'
|
||||
|
||||
conclusion:
|
||||
|
||||
@@ -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.1",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "8.22.0",
|
||||
"eslint-config-next": "12.2.5"
|
||||
"eslint": "8.23.1",
|
||||
"eslint-config-next": "12.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.19.1.tgz#f0cbbe7edda7c4109cd253bb1dee99aba4594ad9"
|
||||
integrity sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==
|
||||
dependencies:
|
||||
core-js-pure "^3.20.2"
|
||||
core-js-pure "^3.25.1"
|
||||
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.2":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356"
|
||||
integrity sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==
|
||||
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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.1.tgz#18266bd92de3b4aa4037b1927aa59e6f11879260"
|
||||
integrity sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.1.tgz#b821f27b0f175954d8d18e5d323fce040ecc79a6"
|
||||
integrity sha512-sw+lTf6r6P0j+g/n9y4qdWWI2syPqZx+uc0+B/fRENqfR3KpSid6MIKqc9gNwGhJASazEQ5b3w8h4cAET213jw==
|
||||
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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz#b15ce8ad376102a3b8c0f3c017dde050a22bb1a3"
|
||||
integrity sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz#85d205f568a790a137cb3c3f720d961a2436ac9c"
|
||||
integrity sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz#b105457d6760a7916b27e46c97cb1a40547114ae"
|
||||
integrity sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz#6947b39082271378896b095b6696a7791c6e32b1"
|
||||
integrity sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz#2b6c36a4d84aae8b0ea0e0da9bafc696ae27085a"
|
||||
integrity sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz#6e421c44285cfedac1f4631d5de330dd60b86298"
|
||||
integrity sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz#8863f08a81f422f910af126159d2cbb9552ef717"
|
||||
integrity sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz#0038f07cf0b259d70ae0c80890d826dfc775d9f3"
|
||||
integrity sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz#c66468f5e8181ffb096c537f0dbfb589baa6a9c1"
|
||||
integrity sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz#c6269f3e96ac0395bc722ad97ce410ea5101d305"
|
||||
integrity sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz#83c639ee969cee36ce247c3abd1d9df97b5ecade"
|
||||
integrity sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz#52995748b92aa8ad053440301bc2c0d9fbcf27c2"
|
||||
integrity sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA==
|
||||
|
||||
"@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.1":
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz#27d71a95247a9eaee03d47adee7e3bd594514136"
|
||||
integrity sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
@@ -150,14 +155,14 @@
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@rushstack/eslint-patch@^1.1.3":
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz#0c8b74c50f29ee44f423f7416829c0bf8bb5eb27"
|
||||
integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz#8be36a1f66f3265389e90b5f9c9962146758f728"
|
||||
integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==
|
||||
|
||||
"@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.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.38.0.tgz#5a59a1ff41a7b43aacd1bb2db54f6bf1c02b2ff8"
|
||||
integrity sha512-/F63giJGLDr0ms1Cr8utDAxP2SPiglaD6V+pCOcG35P2jCqdfR7uuEhz1GIC3oy4hkUF8xA1XSXmd9hOh/a5EA==
|
||||
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.38.0"
|
||||
"@typescript-eslint/types" "5.38.0"
|
||||
"@typescript-eslint/typescript-estree" "5.38.0"
|
||||
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.38.0":
|
||||
version "5.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz#8f0927024b6b24e28671352c93b393a810ab4553"
|
||||
integrity sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.34.0"
|
||||
"@typescript-eslint/visitor-keys" "5.34.0"
|
||||
"@typescript-eslint/types" "5.38.0"
|
||||
"@typescript-eslint/visitor-keys" "5.38.0"
|
||||
|
||||
"@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.38.0":
|
||||
version "5.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.38.0.tgz#8cd15825e4874354e31800dcac321d07548b8a5f"
|
||||
integrity sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==
|
||||
|
||||
"@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.38.0":
|
||||
version "5.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz#89f86b2279815c6fb7f57d68cf9b813f0dc25d98"
|
||||
integrity sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.34.0"
|
||||
"@typescript-eslint/visitor-keys" "5.34.0"
|
||||
"@typescript-eslint/types" "5.38.0"
|
||||
"@typescript-eslint/visitor-keys" "5.38.0"
|
||||
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.38.0":
|
||||
version "5.38.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz#60591ca3bf78aa12b25002c0993d067c00887e34"
|
||||
integrity sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "5.34.0"
|
||||
"@typescript-eslint/types" "5.38.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
acorn-jsx@^5.3.2:
|
||||
@@ -339,10 +344,10 @@ callsites@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||
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==
|
||||
caniuse-lite@^1.0.30001406:
|
||||
version "1.0.30001406"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001406.tgz#d0146e7919635479f873b4507517b627f66ab269"
|
||||
integrity sha512-bWTlaXUy/rq0BBtYShc/jArYfBPjEV95euvZ8JVtO43oQExEN/WquoqpufFjNu4kSpi5cy5kMbNvzztWDfv1Jg==
|
||||
|
||||
chalk@^4.0.0:
|
||||
version "4.1.2"
|
||||
@@ -369,10 +374,10 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
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==
|
||||
core-js-pure@^3.25.1:
|
||||
version "3.25.2"
|
||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.2.tgz#44a4fd873bdd4fecf6ca11512bcefedbe87e744a"
|
||||
integrity sha512-ItD7YpW1cUB4jaqFLZXe1AXkyqIxz6GqPnsDV4uF4hVcWh/WAGIqSqw5p0/WdsILM0Xht9s3Koyw05R3K6RtiA==
|
||||
|
||||
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,19 +503,19 @@ 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.1:
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.3.1.tgz#5d4eb0b7903cea81fd0d5106601d3afb0a453ff4"
|
||||
integrity sha512-EN/xwKPU6jz1G0Qi6Bd/BqMnHLyRAL0VsaQaWA7F3KkjAgZHi4f1uL1JKGWNxdQpHTW/sdGONBd0bzxUka/DJg==
|
||||
dependencies:
|
||||
"@next/eslint-plugin-next" "12.2.5"
|
||||
"@next/eslint-plugin-next" "12.3.1"
|
||||
"@rushstack/eslint-patch" "^1.1.3"
|
||||
"@typescript-eslint/parser" "^5.21.0"
|
||||
eslint-import-resolver-node "^0.3.6"
|
||||
eslint-import-resolver-typescript "^2.7.1"
|
||||
eslint-plugin-import "^2.26.0"
|
||||
eslint-plugin-jsx-a11y "^6.5.1"
|
||||
eslint-plugin-react "^7.29.4"
|
||||
eslint-plugin-react "^7.31.7"
|
||||
eslint-plugin-react-hooks "^4.5.0"
|
||||
|
||||
eslint-import-resolver-node@^0.3.6:
|
||||
@@ -582,10 +587,10 @@ eslint-plugin-react-hooks@^4.5.0:
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
|
||||
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==
|
||||
eslint-plugin-react@^7.31.7:
|
||||
version "7.31.8"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz#3a4f80c10be1bcbc8197be9e8b641b2a3ef219bf"
|
||||
integrity sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==
|
||||
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.1:
|
||||
version "8.23.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.1.tgz#cfd7b3f7fdd07db8d16b4ac0516a29c8d8dca5dc"
|
||||
integrity sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==
|
||||
dependencies:
|
||||
"@eslint/eslintrc" "^1.3.0"
|
||||
"@eslint/eslintrc" "^1.3.2"
|
||||
"@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,13 +650,12 @@ 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"
|
||||
file-entry-cache "^6.0.1"
|
||||
find-up "^5.0.0"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
glob-parent "^6.0.1"
|
||||
globals "^13.15.0"
|
||||
globby "^11.1.0"
|
||||
@@ -659,6 +664,7 @@ eslint@8.22.0:
|
||||
import-fresh "^3.0.0"
|
||||
imurmurhash "^0.1.4"
|
||||
is-glob "^4.0.0"
|
||||
js-sdsl "^4.1.4"
|
||||
js-yaml "^4.1.0"
|
||||
json-stable-stringify-without-jsonify "^1.0.1"
|
||||
levn "^0.4.1"
|
||||
@@ -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"
|
||||
@@ -711,9 +716,9 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
||||
fast-glob@^3.2.9:
|
||||
version "3.2.11"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
|
||||
integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
|
||||
version "3.2.12"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
|
||||
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "^2.0.2"
|
||||
"@nodelib/fs.walk" "^1.2.3"
|
||||
@@ -793,20 +798,15 @@ function.prototype.name@^1.1.5:
|
||||
es-abstract "^1.19.0"
|
||||
functions-have-names "^1.2.2"
|
||||
|
||||
functional-red-black-tree@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
|
||||
integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==
|
||||
|
||||
functions-have-names@^1.2.2:
|
||||
version "1.2.3"
|
||||
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:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598"
|
||||
integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==
|
||||
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.2:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385"
|
||||
integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
has "^1.0.3"
|
||||
@@ -974,9 +974,9 @@ is-boolean-object@^1.1.0:
|
||||
has-tostringtag "^1.0.0"
|
||||
|
||||
is-callable@^1.1.4, is-callable@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
|
||||
integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
|
||||
version "1.2.6"
|
||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.6.tgz#fd6170b0b8c7e2cc73de342ef8284a2202023c44"
|
||||
integrity sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==
|
||||
|
||||
is-core-module@^2.8.1, is-core-module@^2.9.0:
|
||||
version "2.10.0"
|
||||
@@ -1062,6 +1062,11 @@ isexe@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
||||
|
||||
js-sdsl@^4.1.4:
|
||||
version "4.1.4"
|
||||
resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.4.tgz#78793c90f80e8430b7d8dc94515b6c77d98a26a6"
|
||||
integrity sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==
|
||||
|
||||
"js-tokens@^3.0.0 || ^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
@@ -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.1:
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-12.3.1.tgz#127b825ad2207faf869b33393ec8c75fe61e50f1"
|
||||
integrity sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==
|
||||
dependencies:
|
||||
"@next/env" "12.2.5"
|
||||
"@swc/helpers" "0.4.3"
|
||||
caniuse-lite "^1.0.30001332"
|
||||
"@next/env" "12.3.1"
|
||||
"@swc/helpers" "0.4.11"
|
||||
caniuse-lite "^1.0.30001406"
|
||||
postcss "8.4.14"
|
||||
styled-jsx "5.0.4"
|
||||
styled-jsx "5.0.7"
|
||||
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.1"
|
||||
"@next/swc-android-arm64" "12.3.1"
|
||||
"@next/swc-darwin-arm64" "12.3.1"
|
||||
"@next/swc-darwin-x64" "12.3.1"
|
||||
"@next/swc-freebsd-x64" "12.3.1"
|
||||
"@next/swc-linux-arm-gnueabihf" "12.3.1"
|
||||
"@next/swc-linux-arm64-gnu" "12.3.1"
|
||||
"@next/swc-linux-arm64-musl" "12.3.1"
|
||||
"@next/swc-linux-x64-gnu" "12.3.1"
|
||||
"@next/swc-linux-x64-musl" "12.3.1"
|
||||
"@next/swc-win32-arm64-msvc" "12.3.1"
|
||||
"@next/swc-win32-ia32-msvc" "12.3.1"
|
||||
"@next/swc-win32-x64-msvc" "12.3.1"
|
||||
|
||||
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.7:
|
||||
version "5.0.7"
|
||||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.7.tgz#be44afc53771b983769ac654d355ca8d019dff48"
|
||||
integrity sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==
|
||||
|
||||
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"
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"prettier": "2.6.2",
|
||||
"ts-eager": "2.0.2",
|
||||
"ts-jest": "28.0.5",
|
||||
"turbo": "1.3.2-canary.1"
|
||||
"turbo": "1.4.7"
|
||||
},
|
||||
"scripts": {
|
||||
"lerna": "lerna",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/build-utils",
|
||||
"version": "5.4.2",
|
||||
"version": "5.5.3",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
34
packages/build-utils/src/clone-env.ts
Normal file
34
packages/build-utils/src/clone-env.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// mixin the env first
|
||||
obj = Object.assign(obj, env);
|
||||
|
||||
if (hasOwnProperty.call(env, 'Path')) {
|
||||
// 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, but we must also remove the
|
||||
// `Path` property since we can't have both a `PATH` and `Path`
|
||||
obj.PATH = obj.Path;
|
||||
delete obj.Path;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
@@ -38,6 +38,9 @@ export class EdgeFunction {
|
||||
*/
|
||||
assets?: { name: string; path: string }[];
|
||||
|
||||
/** The regions where the edge function will be executed on */
|
||||
regions?: 'auto' | string[] | 'all' | 'default';
|
||||
|
||||
constructor(params: Omit<EdgeFunction, 'type'>) {
|
||||
this.type = 'EdgeFunction';
|
||||
this.name = params.name;
|
||||
@@ -46,5 +49,6 @@ export class EdgeFunction {
|
||||
this.files = params.files;
|
||||
this.envVarsInUse = params.envVarsInUse;
|
||||
this.assets = params.assets;
|
||||
this.regions = params.regions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,14 +61,14 @@ export function getPrettyError(obj: {
|
||||
}
|
||||
|
||||
return new NowBuildError({
|
||||
code: 'DEV_VALIDATE_CONFIG',
|
||||
code: 'INVALID_VERCEL_CONFIG',
|
||||
message: message,
|
||||
link: prop ? `${docsUrl}#project/${prop.toLowerCase()}` : docsUrl,
|
||||
action: 'View Documentation',
|
||||
});
|
||||
} catch (e) {
|
||||
return new NowBuildError({
|
||||
code: 'DEV_VALIDATE_CONFIG',
|
||||
code: 'INVALID_VERCEL_CONFIG',
|
||||
message: `Failed to validate configuration.`,
|
||||
link: docsUrl,
|
||||
action: 'View Documentation',
|
||||
|
||||
@@ -10,7 +10,7 @@ const allOptions = [
|
||||
major: 12,
|
||||
range: '12.x',
|
||||
runtime: 'nodejs12.x',
|
||||
discontinueDate: new Date('2022-10-01'),
|
||||
discontinueDate: new Date('2022-10-03'),
|
||||
},
|
||||
{
|
||||
major: 10,
|
||||
|
||||
@@ -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,
|
||||
@@ -458,12 +459,30 @@ export async function runNpmInstall(
|
||||
env,
|
||||
});
|
||||
let commandArgs: string[];
|
||||
const isPotentiallyBrokenNpm =
|
||||
cliType === 'npm' &&
|
||||
(nodeVersion?.major === 16 ||
|
||||
opts.env.PATH?.includes('/node16/bin-npm7')) &&
|
||||
!args.includes('--legacy-peer-deps') &&
|
||||
spawnOpts?.env?.ENABLE_EXPERIMENTAL_COREPACK !== '1';
|
||||
|
||||
if (cliType === 'npm') {
|
||||
opts.prettyCommand = 'npm install';
|
||||
commandArgs = args
|
||||
.filter(a => a !== '--prefer-offline')
|
||||
.concat(['install', '--no-audit', '--unsafe-perm']);
|
||||
if (
|
||||
isPotentiallyBrokenNpm &&
|
||||
spawnOpts?.env?.VERCEL_NPM_LEGACY_PEER_DEPS === '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
|
||||
@@ -480,7 +499,26 @@ export async function runNpmInstall(
|
||||
commandArgs.push('--production');
|
||||
}
|
||||
|
||||
await spawnAsync(cliType, commandArgs, opts);
|
||||
try {
|
||||
await spawnAsync(cliType, commandArgs, opts);
|
||||
} catch (_) {
|
||||
const potentialErrorPath = path.join(
|
||||
process.env.HOME || '/',
|
||||
'.npm',
|
||||
'eresolve-report.txt'
|
||||
);
|
||||
if (
|
||||
isPotentiallyBrokenNpm &&
|
||||
!commandArgs.includes('--legacy-peer-deps') &&
|
||||
fs.existsSync(potentialErrorPath)
|
||||
) {
|
||||
console.warn(
|
||||
'Warning: Retrying "Install Command" with `--legacy-peer-deps` which may accept a potentially broken dependency and slow install time.'
|
||||
);
|
||||
commandArgs.push('--legacy-peer-deps');
|
||||
await spawnAsync(cliType, commandArgs, opts);
|
||||
}
|
||||
}
|
||||
debug(`Install complete [${Date.now() - installTime}ms]`);
|
||||
return true;
|
||||
} finally {
|
||||
@@ -591,10 +629,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 {
|
||||
|
||||
2
packages/build-utils/test/fixtures/14-npm-6-legacy-peer-deps/.gitignore
vendored
Normal file
2
packages/build-utils/test/fixtures/14-npm-6-legacy-peer-deps/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
.vercel
|
||||
64
packages/build-utils/test/fixtures/14-npm-6-legacy-peer-deps/package-lock.json
generated
vendored
Normal file
64
packages/build-utils/test/fixtures/14-npm-6-legacy-peer-deps/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.8.0.tgz",
|
||||
"integrity": "sha512-g+nikW2D48kqgWSPwNo0NH9tIGG3DsQFlrtrQ1kj6W77z5ahyIHG0w8kPpz4Sdj6gyLnz0lEd/xsjOoGge2MYQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"scheduler": "^0.13.0"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"scheduler": {
|
||||
"version": "0.13.6",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz",
|
||||
"integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"swr": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/swr/-/swr-1.3.0.tgz",
|
||||
"integrity": "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
11
packages/build-utils/test/fixtures/14-npm-6-legacy-peer-deps/package.json
vendored
Normal file
11
packages/build-utils/test/fixtures/14-npm-6-legacy-peer-deps/package.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "mkdir -p public && echo 'legacy peer deps' > public/index.txt"
|
||||
},
|
||||
"packageManager": "npm@6.14.17",
|
||||
"dependencies": {
|
||||
"swr": "1.3.0",
|
||||
"react": "16.8.0"
|
||||
}
|
||||
}
|
||||
3
packages/build-utils/test/fixtures/14-npm-6-legacy-peer-deps/probes.json
vendored
Normal file
3
packages/build-utils/test/fixtures/14-npm-6-legacy-peer-deps/probes.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"probes": [{ "path": "/", "mustContain": "legacy peer deps" }]
|
||||
}
|
||||
2
packages/build-utils/test/fixtures/15-npm-8-legacy-peer-deps/.gitignore
vendored
Normal file
2
packages/build-utils/test/fixtures/15-npm-8-legacy-peer-deps/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
.vercel
|
||||
143
packages/build-utils/test/fixtures/15-npm-8-legacy-peer-deps/package-lock.json
generated
vendored
Normal file
143
packages/build-utils/test/fixtures/15-npm-8-legacy-peer-deps/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
{
|
||||
"name": "15-npm-8-legacy-peer-deps",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"react": "16.8.0",
|
||||
"swr": "1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dependencies": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "16.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.8.0.tgz",
|
||||
"integrity": "sha512-g+nikW2D48kqgWSPwNo0NH9tIGG3DsQFlrtrQ1kj6W77z5ahyIHG0w8kPpz4Sdj6gyLnz0lEd/xsjOoGge2MYQ==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"scheduler": "^0.13.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.13.6",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz",
|
||||
"integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/swr": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/swr/-/swr-1.3.0.tgz",
|
||||
"integrity": "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.11.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"react": {
|
||||
"version": "16.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.8.0.tgz",
|
||||
"integrity": "sha512-g+nikW2D48kqgWSPwNo0NH9tIGG3DsQFlrtrQ1kj6W77z5ahyIHG0w8kPpz4Sdj6gyLnz0lEd/xsjOoGge2MYQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"scheduler": "^0.13.0"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"scheduler": {
|
||||
"version": "0.13.6",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz",
|
||||
"integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==",
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"swr": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/swr/-/swr-1.3.0.tgz",
|
||||
"integrity": "sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
11
packages/build-utils/test/fixtures/15-npm-8-legacy-peer-deps/package.json
vendored
Normal file
11
packages/build-utils/test/fixtures/15-npm-8-legacy-peer-deps/package.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "mkdir -p public && echo 'legacy peer deps' > public/index.txt"
|
||||
},
|
||||
"packageManager": "npm@8.6.0",
|
||||
"dependencies": {
|
||||
"swr": "1.3.0",
|
||||
"react": "16.8.0"
|
||||
}
|
||||
}
|
||||
3
packages/build-utils/test/fixtures/15-npm-8-legacy-peer-deps/probes.json
vendored
Normal file
3
packages/build-utils/test/fixtures/15-npm-8-legacy-peer-deps/probes.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"probes": [{ "path": "/", "mustContain": "legacy peer deps" }]
|
||||
}
|
||||
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
|
||||
|
||||
117
packages/build-utils/test/unit.clone-env.test.ts
vendored
Normal file
117
packages/build-utils/test/unit.clone-env.test.ts
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
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',
|
||||
});
|
||||
});
|
||||
|
||||
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: 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',
|
||||
});
|
||||
});
|
||||
197
packages/build-utils/test/unit.run-npm-install.test.ts
vendored
Normal file
197
packages/build-utils/test/unit.run-npm-install.test.ts
vendored
Normal file
@@ -0,0 +1,197 @@
|
||||
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 = 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 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 include peer dependencies when VERCEL_NPM_LEGACY_PEER_DEPS=1 on node14 and npm7+', 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',
|
||||
'--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 and npm6', async () => {
|
||||
const fixture = path.join(__dirname, 'fixtures', '14-npm-6-legacy-peer-deps');
|
||||
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),
|
||||
});
|
||||
});
|
||||
67
packages/build-utils/test/unit.test.ts
vendored
67
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);
|
||||
@@ -436,8 +434,8 @@ it('should warn for deprecated versions, soon to be discontinued', async () => {
|
||||
expect(warningMessages).toStrictEqual([
|
||||
'Error: Node.js version 10.x has reached End-of-Life. Deployments created on or after 2021-04-20 will fail to build. Please set "engines": { "node": "16.x" } in your `package.json` file to use Node.js 16.',
|
||||
'Error: Node.js version 10.x has reached End-of-Life. Deployments created on or after 2021-04-20 will fail to build. Please set Node.js Version to 16.x in your Project Settings to use Node.js 16.',
|
||||
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-01 will fail to build. Please set "engines": { "node": "16.x" } in your `package.json` file to use Node.js 16.',
|
||||
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-01 will fail to build. Please set Node.js Version to 16.x in your Project Settings to use Node.js 16.',
|
||||
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set "engines": { "node": "16.x" } in your `package.json` file to use Node.js 16.',
|
||||
'Error: Node.js version 12.x has reached End-of-Life. Deployments created on or after 2022-10-03 will fail to build. Please set Node.js Version to 16.x in your Project Settings to use Node.js 16.',
|
||||
]);
|
||||
|
||||
global.Date.now = realDateNow;
|
||||
@@ -578,53 +576,16 @@ it('should detect package.json in nested frontend', async () => {
|
||||
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);
|
||||
it('should retry npm install when peer deps invalid and npm@8 on node@16', async () => {
|
||||
const nodeMajor = Number(process.versions.node.split('.')[0]);
|
||||
if (nodeMajor !== 16) {
|
||||
console.log(`Skipping test on node@${nodeMajor}`);
|
||||
return;
|
||||
}
|
||||
const fixture = path.join(__dirname, 'fixtures', '15-npm-8-legacy-peer-deps');
|
||||
const nodeVersion = { major: nodeMajor } as any;
|
||||
await runNpmInstall(fixture, [], {}, {}, nodeVersion);
|
||||
expect(warningMessages).toStrictEqual([
|
||||
'Warning: Retrying "Install Command" with `--legacy-peer-deps` which may accept a potentially broken dependency and slow install time.',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vercel",
|
||||
"version": "28.2.3",
|
||||
"version": "28.4.5",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Vercel",
|
||||
@@ -41,16 +41,16 @@
|
||||
"node": ">= 14"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vercel/build-utils": "5.4.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.5.3",
|
||||
"@vercel/go": "2.2.11",
|
||||
"@vercel/hydrogen": "0.0.24",
|
||||
"@vercel/next": "3.2.1",
|
||||
"@vercel/node": "2.5.21",
|
||||
"@vercel/python": "3.1.20",
|
||||
"@vercel/redwood": "1.0.29",
|
||||
"@vercel/remix": "1.0.30",
|
||||
"@vercel/ruby": "1.3.37",
|
||||
"@vercel/static-build": "1.0.29",
|
||||
"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.10",
|
||||
"@vercel/frameworks": "1.1.6",
|
||||
"@vercel/fs-detectors": "3.4.1",
|
||||
"@vercel/fun": "1.0.4",
|
||||
"@vercel/ncc": "0.24.0",
|
||||
"@zeit/source-map-support": "0.6.2",
|
||||
|
||||
@@ -2,7 +2,6 @@ import open from 'open';
|
||||
import boxen from 'boxen';
|
||||
import execa from 'execa';
|
||||
import plural from 'pluralize';
|
||||
import inquirer from 'inquirer';
|
||||
import { resolve } from 'path';
|
||||
import chalk, { Chalk } from 'chalk';
|
||||
import { URLSearchParams, parse } from 'url';
|
||||
@@ -150,7 +149,9 @@ export default async function main(client: Client): Promise<number> {
|
||||
|
||||
if (badDeployment) {
|
||||
if (badDeployment instanceof Error) {
|
||||
badDeployment.message += ` "${bad}"`;
|
||||
badDeployment.message += ` when requesting bad deployment "${normalizeURL(
|
||||
bad
|
||||
)}"`;
|
||||
output.prettyError(badDeployment);
|
||||
return 1;
|
||||
}
|
||||
@@ -165,7 +166,9 @@ export default async function main(client: Client): Promise<number> {
|
||||
|
||||
if (goodDeployment) {
|
||||
if (goodDeployment instanceof Error) {
|
||||
goodDeployment.message += ` "${good}"`;
|
||||
goodDeployment.message += ` when requesting good deployment "${normalizeURL(
|
||||
good
|
||||
)}"`;
|
||||
output.prettyError(goodDeployment);
|
||||
return 1;
|
||||
}
|
||||
@@ -226,7 +229,8 @@ export default async function main(client: Client): Promise<number> {
|
||||
// If we have the "good" deployment in this chunk, then we're done
|
||||
for (let i = 0; i < newDeployments.length; i++) {
|
||||
if (newDeployments[i].url === good) {
|
||||
newDeployments = newDeployments.slice(0, i + 1);
|
||||
// grab all deployments up until the good one
|
||||
newDeployments = newDeployments.slice(0, i);
|
||||
next = undefined;
|
||||
break;
|
||||
}
|
||||
@@ -316,7 +320,7 @@ export default async function main(client: Client): Promise<number> {
|
||||
if (openEnabled) {
|
||||
await open(testUrl);
|
||||
}
|
||||
const answer = await inquirer.prompt({
|
||||
const answer = await client.prompt({
|
||||
type: 'expand',
|
||||
name: 'action',
|
||||
message: 'Select an action:',
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
MergeRoutesProps,
|
||||
Route,
|
||||
} from '@vercel/routing-utils';
|
||||
import { fileNameSymbol } from '@vercel/client';
|
||||
import type { VercelConfig } from '@vercel/client';
|
||||
|
||||
import pull from './pull';
|
||||
@@ -54,6 +55,7 @@ import { importBuilders } from '../util/build/import-builders';
|
||||
import { initCorepack, cleanupCorepack } from '../util/build/corepack';
|
||||
import { sortBuilders } from '../util/build/sort-builders';
|
||||
import { toEnumerableError } from '../util/error';
|
||||
import { validateConfig } from '../util/validate-config';
|
||||
|
||||
type BuildResult = BuildResultV2 | BuildResultV3;
|
||||
|
||||
@@ -232,7 +234,8 @@ export default async function main(client: Client): Promise<number> {
|
||||
process.env.VERCEL = '1';
|
||||
process.env.NOW_BUILDER = '1';
|
||||
|
||||
return await doBuild(client, project, buildsJson, cwd, outputDir);
|
||||
await doBuild(client, project, buildsJson, cwd, outputDir);
|
||||
return 0;
|
||||
} catch (err: any) {
|
||||
output.prettyError(err);
|
||||
|
||||
@@ -265,23 +268,36 @@ async function doBuild(
|
||||
buildsJson: BuildsManifest,
|
||||
cwd: string,
|
||||
outputDir: string
|
||||
): Promise<number> {
|
||||
): Promise<void> {
|
||||
const { output } = client;
|
||||
const workPath = join(cwd, project.settings.rootDirectory || '.');
|
||||
|
||||
// Load `package.json` and `vercel.json` files
|
||||
const [pkg, vercelConfig] = await Promise.all([
|
||||
const [pkg, vercelConfig, nowConfig] = await Promise.all([
|
||||
readJSONFile<PackageJson>(join(workPath, 'package.json')),
|
||||
readJSONFile<VercelConfig>(join(workPath, 'vercel.json')).then(
|
||||
config => config || readJSONFile<VercelConfig>(join(workPath, 'now.json'))
|
||||
),
|
||||
readJSONFile<VercelConfig>(join(workPath, 'vercel.json')),
|
||||
readJSONFile<VercelConfig>(join(workPath, 'now.json')),
|
||||
]);
|
||||
|
||||
if (pkg instanceof CantParseJSONFile) throw pkg;
|
||||
if (vercelConfig instanceof CantParseJSONFile) throw vercelConfig;
|
||||
if (nowConfig instanceof CantParseJSONFile) throw nowConfig;
|
||||
|
||||
if (vercelConfig) {
|
||||
vercelConfig[fileNameSymbol] = 'vercel.json';
|
||||
} else if (nowConfig) {
|
||||
nowConfig[fileNameSymbol] = 'now.json';
|
||||
}
|
||||
|
||||
const localConfig = vercelConfig || nowConfig || {};
|
||||
const validateError = validateConfig(localConfig);
|
||||
|
||||
if (validateError) {
|
||||
throw validateError;
|
||||
}
|
||||
|
||||
const projectSettings = {
|
||||
...project.settings,
|
||||
...pickOverrides(vercelConfig || {}),
|
||||
...pickOverrides(localConfig),
|
||||
};
|
||||
|
||||
// Get a list of source files
|
||||
@@ -289,12 +305,12 @@ async function doBuild(
|
||||
normalizePath(relative(workPath, f))
|
||||
);
|
||||
|
||||
const routesResult = getTransformedRoutes(vercelConfig || {});
|
||||
const routesResult = getTransformedRoutes(localConfig);
|
||||
if (routesResult.error) {
|
||||
throw routesResult.error;
|
||||
}
|
||||
|
||||
if (vercelConfig?.builds && vercelConfig.functions) {
|
||||
if (localConfig.builds && localConfig.functions) {
|
||||
throw new NowBuildError({
|
||||
code: 'bad_request',
|
||||
message:
|
||||
@@ -303,7 +319,7 @@ async function doBuild(
|
||||
});
|
||||
}
|
||||
|
||||
let builds = vercelConfig?.builds || [];
|
||||
let builds = localConfig.builds || [];
|
||||
let zeroConfigRoutes: Route[] = [];
|
||||
let isZeroConfig = false;
|
||||
|
||||
@@ -318,7 +334,7 @@ async function doBuild(
|
||||
|
||||
// Detect the Vercel Builders that will need to be invoked
|
||||
const detectedBuilders = await detectBuilders(files, pkg, {
|
||||
...vercelConfig,
|
||||
...localConfig,
|
||||
projectSettings,
|
||||
ignoreBuildScript: true,
|
||||
featHandleMiss: true,
|
||||
@@ -395,13 +411,10 @@ async function doBuild(
|
||||
})
|
||||
);
|
||||
buildsJson.builds = Array.from(buildsJsonBuilds.values());
|
||||
const buildsJsonPath = join(outputDir, 'builds.json');
|
||||
const writeBuildsJsonPromise = fs.writeJSON(buildsJsonPath, buildsJson, {
|
||||
await fs.writeJSON(join(outputDir, 'builds.json'), buildsJson, {
|
||||
spaces: 2,
|
||||
});
|
||||
|
||||
ops.push(writeBuildsJsonPromise);
|
||||
|
||||
// The `meta` config property is re-used for each Builder
|
||||
// invocation so that Builders can share state between
|
||||
// subsequent entrypoint builds.
|
||||
@@ -466,7 +479,7 @@ async function doBuild(
|
||||
build,
|
||||
builder,
|
||||
builderPkg,
|
||||
vercelConfig
|
||||
localConfig
|
||||
).then(
|
||||
override => {
|
||||
if (override) overrides.push(override);
|
||||
@@ -475,26 +488,11 @@ async function doBuild(
|
||||
)
|
||||
);
|
||||
} catch (err: any) {
|
||||
output.prettyError(err);
|
||||
|
||||
const writeConfigJsonPromise = fs.writeJSON(
|
||||
join(outputDir, 'config.json'),
|
||||
{ version: 3 },
|
||||
{ spaces: 2 }
|
||||
);
|
||||
|
||||
await Promise.all([writeBuildsJsonPromise, writeConfigJsonPromise]);
|
||||
|
||||
const buildJsonBuild = buildsJsonBuilds.get(build);
|
||||
if (buildJsonBuild) {
|
||||
buildJsonBuild.error = toEnumerableError(err);
|
||||
|
||||
await fs.writeJSON(buildsJsonPath, buildsJson, {
|
||||
spaces: 2,
|
||||
});
|
||||
}
|
||||
|
||||
return 1;
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,7 +553,7 @@ async function doBuild(
|
||||
builds: builderRoutes,
|
||||
});
|
||||
|
||||
const mergedImages = mergeImages(buildResults.values());
|
||||
const mergedImages = mergeImages(localConfig.images, buildResults.values());
|
||||
const mergedWildcard = mergeWildcard(buildResults.values());
|
||||
const mergedOverrides: Record<string, PathOverride> =
|
||||
overrides.length > 0 ? Object.assign({}, ...overrides) : undefined;
|
||||
@@ -581,8 +579,6 @@ async function doBuild(
|
||||
emoji('success')
|
||||
)}\n`
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function expandBuild(files: string[], build: Builder): Builder[] {
|
||||
@@ -624,9 +620,9 @@ function expandBuild(files: string[], build: Builder): Builder[] {
|
||||
}
|
||||
|
||||
function mergeImages(
|
||||
images: BuildResultV2Typical['images'],
|
||||
buildResults: Iterable<BuildResult>
|
||||
): BuildResultV2Typical['images'] {
|
||||
let images: BuildResultV2Typical['images'] = undefined;
|
||||
for (const result of buildResults) {
|
||||
if ('images' in result && result.images) {
|
||||
images = Object.assign({}, images, result.images);
|
||||
|
||||
@@ -522,7 +522,12 @@ export default async (client: Client): Promise<number> => {
|
||||
quiet,
|
||||
wantsPublic: argv['--public'] || localConfig.public,
|
||||
type: null,
|
||||
nowConfig: localConfig,
|
||||
nowConfig: {
|
||||
...localConfig,
|
||||
// `images` is allowed in "vercel.json" and processed
|
||||
// by `vc build`, but don't send it to the API endpoint
|
||||
images: undefined,
|
||||
},
|
||||
regions,
|
||||
meta,
|
||||
gitMetadata,
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -23,6 +23,7 @@ import type {
|
||||
} from '../types';
|
||||
import { sharedPromise } from './promise';
|
||||
import { APIError } from './errors-ts';
|
||||
import { normalizeError } from './is-error';
|
||||
|
||||
const isSAMLError = (v: any): v is SAMLError => {
|
||||
return v && v.saml;
|
||||
@@ -146,10 +147,15 @@ export default class Client extends EventEmitter implements Stdio {
|
||||
const error = await responseError(res);
|
||||
|
||||
if (isSAMLError(error)) {
|
||||
// A SAML error means the token is expired, or is not
|
||||
// designated for the requested team, so the user needs
|
||||
// to re-authenticate
|
||||
await this.reauthenticate(error);
|
||||
try {
|
||||
// A SAML error means the token is expired, or is not
|
||||
// designated for the requested team, so the user needs
|
||||
// to re-authenticate
|
||||
await this.reauthenticate(error);
|
||||
} catch (reauthError) {
|
||||
// there's no sense in retrying
|
||||
return bail(normalizeError(reauthError));
|
||||
}
|
||||
} else if (res.status >= 400 && res.status < 500) {
|
||||
// Any other 4xx should bail without retrying
|
||||
return bail(error);
|
||||
@@ -186,7 +192,7 @@ export default class Client extends EventEmitter implements Stdio {
|
||||
`Failed to re-authenticate for ${bold(error.scope)} scope`
|
||||
);
|
||||
}
|
||||
process.exit(1);
|
||||
throw error;
|
||||
}
|
||||
|
||||
this.authConfig.token = result.token;
|
||||
|
||||
@@ -78,16 +78,23 @@ function getLastCommit(directory: string): Promise<git.Commit> {
|
||||
|
||||
export function isDirty(directory: string, output: Output): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
exec('git status -s', { cwd: directory }, function (err, stdout, stderr) {
|
||||
let debugMessage = `Failed to determine if Git repo has been modified:`;
|
||||
if (err || stderr) {
|
||||
if (err) debugMessage += `\n${err}`;
|
||||
if (stderr) debugMessage += `\n${stderr.trim()}`;
|
||||
output.debug(debugMessage);
|
||||
return resolve(false);
|
||||
// note: we specify the `--no-optional-locks` git flag so that `git status`
|
||||
// does not perform any "optional" operations such as optimizing the index
|
||||
// in the background: https://git-scm.com/docs/git-status#_background_refresh
|
||||
exec(
|
||||
'git --no-optional-locks status -s',
|
||||
{ cwd: directory },
|
||||
function (err, stdout, stderr) {
|
||||
let debugMessage = `Failed to determine if Git repo has been modified:`;
|
||||
if (err || stderr) {
|
||||
if (err) debugMessage += `\n${err}`;
|
||||
if (stderr) debugMessage += `\n${stderr.trim()}`;
|
||||
output.debug(debugMessage);
|
||||
return resolve(false);
|
||||
}
|
||||
resolve(stdout.trim().length > 0);
|
||||
}
|
||||
resolve(stdout.trim().length > 0);
|
||||
});
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
@@ -57,16 +57,11 @@ import { MissingDotenvVarsError } from '../errors-ts';
|
||||
import cliPkg from '../pkg';
|
||||
import { getVercelDirectory } from '../projects/link';
|
||||
import { staticFiles as getFiles } from '../get-files';
|
||||
import { validateConfig } from './validate';
|
||||
import { validateConfig } from '../validate-config';
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,16 @@ export async function writeProjectSettings(
|
||||
project: Project,
|
||||
org: Org
|
||||
) {
|
||||
let analyticsId: string | undefined;
|
||||
if (
|
||||
project.analytics?.id &&
|
||||
(!project.analytics.disabledAt ||
|
||||
(project.analytics.enabledAt &&
|
||||
project.analytics.enabledAt > project.analytics.disabledAt))
|
||||
) {
|
||||
analyticsId = project.analytics.id;
|
||||
}
|
||||
|
||||
const projectLinkAndSettings: ProjectLinkAndSettings = {
|
||||
projectId: project.id,
|
||||
orgId: org.id,
|
||||
@@ -41,7 +51,7 @@ export async function writeProjectSettings(
|
||||
rootDirectory: project.rootDirectory,
|
||||
directoryListing: project.directoryListing,
|
||||
nodeVersion: project.nodeVersion,
|
||||
analyticsId: project.analytics?.id,
|
||||
analyticsId,
|
||||
},
|
||||
};
|
||||
const path = join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT);
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
rewritesSchema,
|
||||
trailingSlashSchema,
|
||||
} from '@vercel/routing-utils';
|
||||
import { VercelConfig } from './types';
|
||||
import { VercelConfig } from './dev/types';
|
||||
import {
|
||||
functionsSchema,
|
||||
buildsSchema,
|
||||
@@ -16,6 +16,83 @@ import {
|
||||
} from '@vercel/build-utils';
|
||||
import { fileNameSymbol } from '@vercel/client';
|
||||
|
||||
const imagesSchema = {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['sizes'],
|
||||
properties: {
|
||||
contentSecurityPolicy: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 256,
|
||||
},
|
||||
dangerouslyAllowSVG: {
|
||||
type: 'boolean',
|
||||
},
|
||||
domains: {
|
||||
type: 'array',
|
||||
minItems: 0,
|
||||
maxItems: 50,
|
||||
items: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 256,
|
||||
},
|
||||
},
|
||||
formats: {
|
||||
type: 'array',
|
||||
minItems: 1,
|
||||
maxItems: 4,
|
||||
items: {
|
||||
enum: ['image/avif', 'image/webp', 'image/jpeg', 'image/png'],
|
||||
},
|
||||
},
|
||||
minimumCacheTTL: {
|
||||
type: 'integer',
|
||||
minimum: 1,
|
||||
maximum: 315360000,
|
||||
},
|
||||
remotePatterns: {
|
||||
type: 'array',
|
||||
minItems: 0,
|
||||
maxItems: 50,
|
||||
items: {
|
||||
type: 'object',
|
||||
additionalProperties: false,
|
||||
required: ['hostname'],
|
||||
properties: {
|
||||
protocol: {
|
||||
enum: ['http', 'https'],
|
||||
},
|
||||
hostname: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 256,
|
||||
},
|
||||
port: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 5,
|
||||
},
|
||||
pathname: {
|
||||
type: 'string',
|
||||
minLength: 1,
|
||||
maxLength: 256,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sizes: {
|
||||
type: 'array',
|
||||
minItems: 1,
|
||||
maxItems: 50,
|
||||
items: {
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const vercelConfigSchema = {
|
||||
type: 'object',
|
||||
// These are not all possibilities because `vc dev`
|
||||
@@ -30,6 +107,7 @@ const vercelConfigSchema = {
|
||||
rewrites: rewritesSchema,
|
||||
trailingSlash: trailingSlashSchema,
|
||||
functions: functionsSchema,
|
||||
images: imagesSchema,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import generateUUID from '../vendor/generate-uuid';
|
||||
|
||||
export const config = {
|
||||
runtime: 'experimental-edge',
|
||||
};
|
||||
|
||||
export default async function edge(request, event) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
randomString: generateUUID(),
|
||||
})
|
||||
);
|
||||
}
|
||||
6
packages/cli/test/dev/fixtures/edge-function/vendor/generate-uuid/index-browser.js
vendored
Normal file
6
packages/cli/test/dev/fixtures/edge-function/vendor/generate-uuid/index-browser.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
// This uses the `crypto` globaly,
|
||||
// which will work fine in a browser or Edge Runtime environment
|
||||
|
||||
export default function generateUUID(message) {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
8
packages/cli/test/dev/fixtures/edge-function/vendor/generate-uuid/index-node.js
vendored
Normal file
8
packages/cli/test/dev/fixtures/edge-function/vendor/generate-uuid/index-node.js
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import crypto from 'crypto';
|
||||
|
||||
// this uses a core Node library,
|
||||
// which will fail to execute in a browser or Edge Runtime context
|
||||
|
||||
export default function say(message) {
|
||||
return crypto.generateUUID();
|
||||
}
|
||||
6
packages/cli/test/dev/fixtures/edge-function/vendor/generate-uuid/package.json
vendored
Normal file
6
packages/cli/test/dev/fixtures/edge-function/vendor/generate-uuid/package.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "generate-uuid",
|
||||
"private": true,
|
||||
"main": "index-node.js",
|
||||
"browser": "index-browser.js"
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -85,6 +86,7 @@ test(
|
||||
testFixtureStdio('edge-function', async (testPath: any) => {
|
||||
await testPath(500, '/api/edge-500-response');
|
||||
await testPath(200, '/api/edge-success');
|
||||
await testPath(200, '/api/edge-import-browser');
|
||||
})
|
||||
);
|
||||
|
||||
@@ -723,12 +725,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) => {
|
||||
|
||||
7
packages/cli/test/fixtures/unit/commands/build/images/.vercel/project.json
vendored
Normal file
7
packages/cli/test/fixtures/unit/commands/build/images/.vercel/project.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"orgId": ".",
|
||||
"projectId": ".",
|
||||
"settings": {
|
||||
"framework": null
|
||||
}
|
||||
}
|
||||
1
packages/cli/test/fixtures/unit/commands/build/images/index.html
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/build/images/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<h1>Vercel</h1>
|
||||
8
packages/cli/test/fixtures/unit/commands/build/images/vercel.json
vendored
Normal file
8
packages/cli/test/fixtures/unit/commands/build/images/vercel.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"images": {
|
||||
"sizes": [256, 384, 600, 1000],
|
||||
"domains": [],
|
||||
"minimumCacheTTL": 60,
|
||||
"formats": ["image/avif", "image/webp"]
|
||||
}
|
||||
}
|
||||
7
packages/cli/test/fixtures/unit/commands/build/invalid-rewrites/.vercel/project.json
vendored
Normal file
7
packages/cli/test/fixtures/unit/commands/build/invalid-rewrites/.vercel/project.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"orgId": ".",
|
||||
"projectId": ".",
|
||||
"settings": {
|
||||
"framework": null
|
||||
}
|
||||
}
|
||||
1
packages/cli/test/fixtures/unit/commands/build/invalid-rewrites/index.html
vendored
Normal file
1
packages/cli/test/fixtures/unit/commands/build/invalid-rewrites/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<h1>Vercel</h1>
|
||||
16
packages/cli/test/fixtures/unit/commands/build/invalid-rewrites/vercel.json
vendored
Normal file
16
packages/cli/test/fixtures/unit/commands/build/invalid-rewrites/vercel.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"rewrites": [
|
||||
{
|
||||
"source": "/one",
|
||||
"destination": "/api/one"
|
||||
},
|
||||
{
|
||||
"source": "/two",
|
||||
"destination": "/api/two"
|
||||
},
|
||||
{
|
||||
"src": "/three",
|
||||
"dest": "/api/three"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,20 +3,26 @@ import chance from 'chance';
|
||||
import { Deployment } from '@vercel/client';
|
||||
import { client } from './client';
|
||||
import { Build, User } from '../../src/types';
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
let deployments = new Map<string, Deployment>();
|
||||
let deploymentBuilds = new Map<Deployment, Build[]>();
|
||||
let alreadySetupDeplomentEndpoints = false;
|
||||
|
||||
type State = Deployment['readyState'];
|
||||
|
||||
export function useDeployment({
|
||||
creator,
|
||||
state = 'READY',
|
||||
createdAt,
|
||||
}: {
|
||||
creator: Pick<User, 'id' | 'email' | 'name' | 'username'>;
|
||||
state?: State;
|
||||
createdAt?: number;
|
||||
}) {
|
||||
const createdAt = Date.now();
|
||||
setupDeploymentEndpoints();
|
||||
|
||||
createdAt = createdAt || Date.now();
|
||||
const url = new URL(chance().url());
|
||||
const name = chance().name();
|
||||
const id = `dpl_${chance().guid()}`;
|
||||
@@ -69,7 +75,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: {
|
||||
@@ -99,6 +105,15 @@ export function useDeploymentMissingProjectSettings() {
|
||||
beforeEach(() => {
|
||||
deployments = new Map();
|
||||
deploymentBuilds = new Map();
|
||||
alreadySetupDeplomentEndpoints = false;
|
||||
});
|
||||
|
||||
function setupDeploymentEndpoints() {
|
||||
if (alreadySetupDeplomentEndpoints) {
|
||||
return;
|
||||
}
|
||||
|
||||
alreadySetupDeplomentEndpoints = true;
|
||||
|
||||
client.scenario.get('/:version/deployments/:id', (req, res) => {
|
||||
const { id } = req.params;
|
||||
@@ -136,8 +151,21 @@ beforeEach(() => {
|
||||
res.json({ builds });
|
||||
});
|
||||
|
||||
client.scenario.get('/:version/now/deployments', (req, res) => {
|
||||
const deploymentsList = Array.from(deployments.values());
|
||||
res.json({ deployments: deploymentsList });
|
||||
});
|
||||
});
|
||||
function handleGetDeployments(req: Request, res: Response) {
|
||||
const currentDeployments = Array.from(deployments.values()).sort(
|
||||
(a: Deployment, b: Deployment) => {
|
||||
// sort in reverse chronological order
|
||||
return b.createdAt - a.createdAt;
|
||||
}
|
||||
);
|
||||
|
||||
res.json({
|
||||
pagination: {
|
||||
count: currentDeployments.length,
|
||||
},
|
||||
deployments: currentDeployments,
|
||||
});
|
||||
}
|
||||
client.scenario.get('/:version/now/deployments', handleGetDeployments);
|
||||
client.scenario.get('/:version/deployments', handleGetDeployments);
|
||||
}
|
||||
|
||||
55
packages/cli/test/unit/commands/bisect.test.ts
Normal file
55
packages/cli/test/unit/commands/bisect.test.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { client } from '../../mocks/client';
|
||||
import { useUser } from '../../mocks/user';
|
||||
import bisect from '../../../src/commands/bisect';
|
||||
import { useDeployment } from '../../mocks/deployment';
|
||||
|
||||
describe('bisect', () => {
|
||||
it('should find the bad deployment', async () => {
|
||||
const user = useUser();
|
||||
|
||||
const now = Date.now();
|
||||
const deployment1 = useDeployment({ creator: user, createdAt: now });
|
||||
const deployment2 = useDeployment({
|
||||
creator: user,
|
||||
createdAt: now + 10000,
|
||||
});
|
||||
const deployment3 = useDeployment({
|
||||
creator: user,
|
||||
createdAt: now + 20000,
|
||||
});
|
||||
|
||||
// also create an extra deployment before the known good deployment
|
||||
// to make sure the bisect pool doesn't include it
|
||||
useDeployment({
|
||||
creator: user,
|
||||
createdAt: now - 30000,
|
||||
});
|
||||
|
||||
const bisectPromise = bisect(client);
|
||||
|
||||
await expect(client.stderr).toOutput('Specify a URL where the bug occurs:');
|
||||
client.stdin.write(`https://${deployment3.url}\n`);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
'Specify a URL where the bug does not occur:'
|
||||
);
|
||||
client.stdin.write(`https://${deployment1.url}\n`);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
'Specify the URL subpath where the bug occurs:'
|
||||
);
|
||||
client.stdin.write('/docs\n');
|
||||
|
||||
await expect(client.stderr).toOutput('Bisecting');
|
||||
await expect(client.stderr).toOutput(
|
||||
`Deployment URL: https://${deployment2.url}`
|
||||
);
|
||||
client.stdin.write('b\n');
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`The first bad deployment is: https://${deployment2.url}`
|
||||
);
|
||||
|
||||
await expect(bisectPromise).resolves.toEqual(0);
|
||||
});
|
||||
});
|
||||
@@ -750,11 +750,22 @@ describe('build', () => {
|
||||
const errorBuilds = builds.builds.filter((b: any) => 'error' in b);
|
||||
expect(errorBuilds).toHaveLength(1);
|
||||
|
||||
expect(errorBuilds[0].error.name).toEqual('Error');
|
||||
expect(errorBuilds[0].error.message).toMatch(`TS1005`);
|
||||
expect(errorBuilds[0].error.message).toMatch(`',' expected.`);
|
||||
expect(errorBuilds[0].error.hideStackTrace).toEqual(true);
|
||||
expect(errorBuilds[0].error.code).toEqual('NODE_TYPESCRIPT_ERROR');
|
||||
expect(errorBuilds[0].error).toEqual({
|
||||
name: 'Error',
|
||||
message: expect.stringContaining('TS1005'),
|
||||
stack: expect.stringContaining('api/typescript.ts'),
|
||||
hideStackTrace: true,
|
||||
code: 'NODE_TYPESCRIPT_ERROR',
|
||||
});
|
||||
|
||||
// top level "error" also contains the same error
|
||||
expect(builds.error).toEqual({
|
||||
name: 'Error',
|
||||
message: expect.stringContaining('TS1005'),
|
||||
stack: expect.stringContaining('api/typescript.ts'),
|
||||
hideStackTrace: true,
|
||||
code: 'NODE_TYPESCRIPT_ERROR',
|
||||
});
|
||||
|
||||
// `config.json` contains `version`
|
||||
const configJson = await fs.readJSON(join(output, 'config.json'));
|
||||
@@ -895,6 +906,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 {
|
||||
@@ -915,6 +932,62 @@ describe('build', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should apply "images" configuration from `vercel.json`', async () => {
|
||||
const cwd = fixture('images');
|
||||
const output = join(cwd, '.vercel/output');
|
||||
try {
|
||||
process.chdir(cwd);
|
||||
const exitCode = await build(client);
|
||||
expect(exitCode).toEqual(0);
|
||||
|
||||
// `config.json` includes "images" from `vercel.json`
|
||||
const configJson = await fs.readJSON(join(output, 'config.json'));
|
||||
expect(configJson).toMatchObject({
|
||||
images: {
|
||||
sizes: [256, 384, 600, 1000],
|
||||
domains: [],
|
||||
minimumCacheTTL: 60,
|
||||
formats: ['image/avif', 'image/webp'],
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
process.chdir(originalCwd);
|
||||
delete process.env.__VERCEL_BUILD_RUNNING;
|
||||
}
|
||||
});
|
||||
|
||||
it('should fail with invalid "rewrites" configuration from `vercel.json`', async () => {
|
||||
const cwd = fixture('invalid-rewrites');
|
||||
const output = join(cwd, '.vercel/output');
|
||||
try {
|
||||
process.chdir(cwd);
|
||||
const exitCode = await build(client);
|
||||
expect(exitCode).toEqual(1);
|
||||
await expect(client.stderr).toOutput(
|
||||
'Error: Invalid vercel.json - `rewrites[2]` should NOT have additional property `src`. Did you mean `source`?' +
|
||||
'\n' +
|
||||
'View Documentation: https://vercel.com/docs/configuration#project/rewrites'
|
||||
);
|
||||
const builds = await fs.readJSON(join(output, 'builds.json'));
|
||||
expect(builds.builds).toBeUndefined();
|
||||
expect(builds.error).toEqual({
|
||||
name: 'Error',
|
||||
message:
|
||||
'Invalid vercel.json - `rewrites[2]` should NOT have additional property `src`. Did you mean `source`?',
|
||||
stack: expect.stringContaining('at validateConfig'),
|
||||
hideStackTrace: true,
|
||||
code: 'INVALID_VERCEL_CONFIG',
|
||||
link: 'https://vercel.com/docs/configuration#project/rewrites',
|
||||
action: 'View Documentation',
|
||||
});
|
||||
const configJson = await fs.readJSON(join(output, 'config.json'));
|
||||
expect(configJson.version).toBe(3);
|
||||
} finally {
|
||||
process.chdir(originalCwd);
|
||||
delete process.env.__VERCEL_BUILD_RUNNING;
|
||||
}
|
||||
});
|
||||
|
||||
describe('should find packages with different main/module/browser keys', function () {
|
||||
let output: string;
|
||||
|
||||
|
||||
@@ -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,4 +1,4 @@
|
||||
import { validateConfig } from '../../../../src/util/dev/validate';
|
||||
import { validateConfig } from '../../../../src/util/validate-config';
|
||||
|
||||
describe('validateConfig', () => {
|
||||
it('should not error with empty config', async () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@vercel/client",
|
||||
"version": "12.2.4",
|
||||
"version": "12.2.10",
|
||||
"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.5.3",
|
||||
"@vercel/routing-utils": "2.0.2",
|
||||
"@zeit/fetch": "5.2.0",
|
||||
"async-retry": "1.2.3",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type {
|
||||
Builder,
|
||||
BuilderFunctions,
|
||||
Images,
|
||||
ProjectSettings,
|
||||
} from '@vercel/build-utils';
|
||||
import type { Header, Route, Redirect, Rewrite } from '@vercel/routing-utils';
|
||||
@@ -152,6 +153,7 @@ export interface VercelConfig {
|
||||
installCommand?: string | null;
|
||||
framework?: string | null;
|
||||
outputDirectory?: string | null;
|
||||
images?: Images;
|
||||
}
|
||||
|
||||
export interface GitMetadata {
|
||||
|
||||
@@ -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.4.1",
|
||||
"description": "Vercel filesystem detectors",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
@@ -19,10 +19,11 @@
|
||||
"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",
|
||||
"json5": "2.2.1",
|
||||
"minimatch": "3.0.4",
|
||||
"semver": "6.1.1"
|
||||
},
|
||||
|
||||
@@ -89,33 +89,34 @@ export abstract class DetectorFilesystem {
|
||||
if (!p) {
|
||||
p = this._readdir(dirPath);
|
||||
this.readdirCache.set(dirPath, p);
|
||||
}
|
||||
|
||||
const directoryContent = await p;
|
||||
const directoryFiles = new Set<string>();
|
||||
const directoryContent = await p;
|
||||
const directoryFiles = new Set<string>();
|
||||
|
||||
for (const file of directoryContent) {
|
||||
if (file.type === 'file') {
|
||||
// we know this file exists, mark it as so on the filesystem
|
||||
this.fileCache.set(file.path, Promise.resolve(true));
|
||||
this.pathCache.set(file.path, Promise.resolve(true));
|
||||
directoryFiles.add(file.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (options?.potentialFiles) {
|
||||
// calculate the set of paths that truly do not exist
|
||||
const filesThatDoNotExist = options.potentialFiles.filter(
|
||||
path => !directoryFiles.has(path)
|
||||
);
|
||||
for (const filePath of filesThatDoNotExist) {
|
||||
const fullFilePath =
|
||||
dirPath === '/' ? filePath : posixPath.join(dirPath, filePath);
|
||||
// we know this file does not exist, mark it as so on the filesystem
|
||||
this.fileCache.set(fullFilePath, Promise.resolve(false));
|
||||
this.pathCache.set(fullFilePath, Promise.resolve(false));
|
||||
}
|
||||
for (const file of directoryContent) {
|
||||
if (file.type === 'file') {
|
||||
// we know this file exists, mark it as so on the filesystem
|
||||
this.fileCache.set(file.path, Promise.resolve(true));
|
||||
this.pathCache.set(file.path, Promise.resolve(true));
|
||||
directoryFiles.add(file.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (options?.potentialFiles) {
|
||||
// calculate the set of paths that truly do not exist
|
||||
const filesThatDoNotExist = options.potentialFiles.filter(
|
||||
path => !directoryFiles.has(path)
|
||||
);
|
||||
for (const filePath of filesThatDoNotExist) {
|
||||
const fullFilePath =
|
||||
dirPath === '/' ? filePath : posixPath.join(dirPath, filePath);
|
||||
// we know this file does not exist, mark it as so on the filesystem
|
||||
this.fileCache.set(fullFilePath, Promise.resolve(false));
|
||||
this.pathCache.set(fullFilePath, Promise.resolve(false));
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
@@ -125,4 +126,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;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import _path from 'path';
|
||||
import yaml from 'js-yaml';
|
||||
import glob from 'glob';
|
||||
import json5 from 'json5';
|
||||
import { DetectorFilesystem } from '../detectors/filesystem';
|
||||
import { Workspace } from './get-workspaces';
|
||||
import { getGlobFs } from './get-glob-fs';
|
||||
@@ -33,6 +34,12 @@ export async function getWorkspacePackagePaths({
|
||||
case 'pnpm':
|
||||
results = await getPnpmWorkspacePackagePaths({ fs: workspaceFs });
|
||||
break;
|
||||
case 'nx':
|
||||
results = await getNxWorkspacePackagePaths({ fs: workspaceFs });
|
||||
break;
|
||||
case 'rush':
|
||||
results = await getRushWorkspacePackagePaths({ fs: workspaceFs });
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown workspace implementation: ${type}`);
|
||||
}
|
||||
@@ -55,6 +62,14 @@ type PnpmWorkspaces = {
|
||||
packages?: string[];
|
||||
};
|
||||
|
||||
type RushWorkspaces = {
|
||||
projects: [
|
||||
{
|
||||
projectFolder: string;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
const isWin = process.platform === 'win32';
|
||||
const normalizePath = (p: string) => (isWin ? p.replace(/\\/g, '/') : p);
|
||||
|
||||
@@ -103,6 +118,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[]> {
|
||||
@@ -113,3 +139,23 @@ async function getPnpmWorkspacePackagePaths({
|
||||
|
||||
return getPackagePaths(packages, fs);
|
||||
}
|
||||
|
||||
async function getRushWorkspacePackagePaths({
|
||||
fs,
|
||||
}: GetPackagePathOptions): Promise<string[]> {
|
||||
const rushWorkspaceAsBuffer = await fs.readFile('rush.json');
|
||||
|
||||
const { projects = [] } = json5.parse(
|
||||
rushWorkspaceAsBuffer.toString()
|
||||
) as RushWorkspaces;
|
||||
|
||||
if (Array.isArray(projects)) {
|
||||
const packages = projects
|
||||
.filter(proj => proj.projectFolder)
|
||||
.map(project => project.projectFolder);
|
||||
|
||||
return getPackagePaths(packages, fs);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface GetWorkspaceOptions {
|
||||
cwd?: string;
|
||||
}
|
||||
|
||||
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm';
|
||||
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm' | 'nx' | 'rush';
|
||||
|
||||
export type Workspace = {
|
||||
type: WorkspaceType;
|
||||
|
||||
@@ -59,6 +59,29 @@ export const workspaceManagers: Array<
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'nx',
|
||||
slug: 'nx',
|
||||
detectors: {
|
||||
every: [
|
||||
{
|
||||
path: 'workspace.json',
|
||||
matchContent: '"projects":\\s*{[^}]',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'rush',
|
||||
slug: 'rush',
|
||||
detectors: {
|
||||
every: [
|
||||
{
|
||||
path: 'rush.json',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
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"]
|
||||
}
|
||||
}
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/40-rush-monorepo/apps/my-app/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/40-rush-monorepo/apps/my-app/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "my-app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.2"
|
||||
}
|
||||
}
|
||||
15
packages/fs-detectors/test/fixtures/40-rush-monorepo/apps/my-second-app/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/40-rush-monorepo/apps/my-second-app/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "my-second-app",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.2"
|
||||
}
|
||||
}
|
||||
36
packages/fs-detectors/test/fixtures/40-rush-monorepo/rush.json
vendored
Normal file
36
packages/fs-detectors/test/fixtures/40-rush-monorepo/rush.json
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"$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": []
|
||||
},
|
||||
// comment
|
||||
"variants": [],
|
||||
"projects": [
|
||||
{
|
||||
"packageName": "my-app",
|
||||
"projectFolder": "apps/my-app"
|
||||
},
|
||||
{
|
||||
"packageName": "my-second-app",
|
||||
"projectFolder": "apps/my-second-app"
|
||||
}
|
||||
]
|
||||
}
|
||||
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": "app-one",
|
||||
"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": "app-two",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
27
packages/fs-detectors/test/fixtures/41-rush-monorepo-empty/rush.json
vendored
Normal file
27
packages/fs-detectors/test/fixtures/41-rush-monorepo-empty/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/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": "app-one",
|
||||
"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": "app-two",
|
||||
"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": {}
|
||||
}
|
||||
29
packages/fs-detectors/test/fixtures/42-rush-json-invalid/rush.json
vendored
Normal file
29
packages/fs-detectors/test/fixtures/42-rush-json-invalid/rush.json
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$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": {},
|
||||
/*
|
||||
this is a comment
|
||||
*/
|
||||
"repository": {},
|
||||
"eventHooks": {
|
||||
"preRushInstall": [],
|
||||
|
||||
"postRushInstall": [],
|
||||
"preRushBuild": [],
|
||||
|
||||
"postRushBuild": []
|
||||
},
|
||||
"variants": [],
|
||||
"projects": "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": "app-one",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user