mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-11 12:57:46 +00:00
Compare commits
63 Commits
@vercel/py
...
@vercel/bu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
d5537500d8 | ||
|
|
4b1736b2f2 | ||
|
|
9da1c6fa66 | ||
|
|
a6c320846e | ||
|
|
4973814978 | ||
|
|
f1289ff263 | ||
|
|
3ff93279cd | ||
|
|
58f9d649a8 | ||
|
|
cadc082ad1 |
8
.github/workflows/publish.yml
vendored
8
.github/workflows/publish.yml
vendored
@@ -7,6 +7,11 @@ on:
|
|||||||
tags:
|
tags:
|
||||||
- '!*'
|
- '!*'
|
||||||
|
|
||||||
|
env:
|
||||||
|
TURBO_REMOTE_ONLY: 'true'
|
||||||
|
TURBO_TEAM: 'vercel'
|
||||||
|
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
name: Publish
|
name: Publish
|
||||||
@@ -32,8 +37,11 @@ jobs:
|
|||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
|
env:
|
||||||
|
SEGMENT_DOWNLOAD_TIMEOUT_MIN: 5 # https://github.com/actions/cache/issues/810
|
||||||
with:
|
with:
|
||||||
node-version: 14
|
node-version: 14
|
||||||
|
cache: 'yarn'
|
||||||
- name: Install
|
- name: Install
|
||||||
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
if: ${{ steps.check-release.outputs.IS_RELEASE == 'true' }}
|
||||||
run: yarn install --check-files --frozen-lockfile --network-timeout 1000000
|
run: yarn install --check-files --frozen-lockfile --network-timeout 1000000
|
||||||
|
|||||||
28
.github/workflows/test-integration-cli.yml
vendored
28
.github/workflows/test-integration-cli.yml
vendored
@@ -8,6 +8,11 @@ on:
|
|||||||
- '!*'
|
- '!*'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
TURBO_REMOTE_ONLY: 'true'
|
||||||
|
TURBO_TEAM: 'vercel'
|
||||||
|
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: CLI
|
name: CLI
|
||||||
@@ -19,28 +24,21 @@ jobs:
|
|||||||
node: [14]
|
node: [14]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- name: Conditionally set remote env
|
- uses: actions/checkout@v3
|
||||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
with:
|
||||||
run: |
|
fetch-depth: 2
|
||||||
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
|
- uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.13.15'
|
go-version: '1.13.15'
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
|
env:
|
||||||
|
SEGMENT_DOWNLOAD_TIMEOUT_MIN: 5 # https://github.com/actions/cache/issues/810
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
- uses: actions/checkout@v3
|
cache: 'yarn'
|
||||||
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
|
|
||||||
- run: yarn install --network-timeout 1000000 --frozen-lockfile
|
- run: yarn install --network-timeout 1000000 --frozen-lockfile
|
||||||
- run: yarn run build
|
- run: yarn run build
|
||||||
- run: yarn test-integration-cli
|
- run: yarn test-integration-cli
|
||||||
env:
|
env:
|
||||||
VERCEL_TEAM_TOKEN: ${{ secrets.VERCEL_TEAM_TOKEN }}
|
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
|
||||||
VERCEL_REGISTRATION_URL: ${{ secrets.VERCEL_REGISTRATION_URL }}
|
VERCEL_TEST_REGISTRATION_URL: ${{ secrets.VERCEL_TEST_REGISTRATION_URL }}
|
||||||
|
|||||||
26
.github/workflows/test-unit.yml
vendored
26
.github/workflows/test-unit.yml
vendored
@@ -8,6 +8,11 @@ on:
|
|||||||
- '!*'
|
- '!*'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
TURBO_REMOTE_ONLY: 'true'
|
||||||
|
TURBO_TEAM: 'vercel'
|
||||||
|
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: Unit
|
name: Unit
|
||||||
@@ -19,25 +24,18 @@ jobs:
|
|||||||
node: [14]
|
node: [14]
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
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
|
- uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: '1.13.15'
|
go-version: '1.13.15'
|
||||||
- uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node }}
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 100
|
fetch-depth: 2
|
||||||
- run: git --version
|
- uses: actions/setup-node@v3
|
||||||
- run: git fetch origin main --depth=100
|
env:
|
||||||
- run: git fetch origin ${{ github.ref }} --depth=100
|
SEGMENT_DOWNLOAD_TIMEOUT_MIN: 5 # https://github.com/actions/cache/issues/810
|
||||||
- run: git diff origin/main...HEAD --name-only
|
with:
|
||||||
|
node-version: ${{ matrix.node }}
|
||||||
|
cache: 'yarn'
|
||||||
- run: yarn install --network-timeout 1000000 --frozen-lockfile
|
- run: yarn install --network-timeout 1000000 --frozen-lockfile
|
||||||
- run: yarn run build
|
- run: yarn run build
|
||||||
- run: yarn run lint
|
- run: yarn run lint
|
||||||
|
|||||||
24
.github/workflows/test.yml
vendored
24
.github/workflows/test.yml
vendored
@@ -10,6 +10,9 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
NODE_VERSION: '14'
|
NODE_VERSION: '14'
|
||||||
|
TURBO_REMOTE_ONLY: 'true'
|
||||||
|
TURBO_TEAM: 'vercel'
|
||||||
|
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
@@ -20,9 +23,14 @@ jobs:
|
|||||||
dplUrl: ${{ steps.waitForTarball.outputs.url }}
|
dplUrl: ${{ steps.waitForTarball.outputs.url }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: git --version
|
with:
|
||||||
- run: git fetch origin main
|
fetch-depth: 2
|
||||||
|
- uses: actions/setup-go@v3
|
||||||
|
with:
|
||||||
|
go-version: '1.13.15'
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
|
env:
|
||||||
|
SEGMENT_DOWNLOAD_TIMEOUT_MIN: 5 # https://github.com/actions/cache/issues/810
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
@@ -52,12 +60,6 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
include: ${{ fromJson(needs.setup.outputs['tests']) }}
|
include: ${{ fromJson(needs.setup.outputs['tests']) }}
|
||||||
steps:
|
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
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
@@ -65,6 +67,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
go-version: '1.13.15'
|
go-version: '1.13.15'
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
|
env:
|
||||||
|
SEGMENT_DOWNLOAD_TIMEOUT_MIN: 5 # https://github.com/actions/cache/issues/810
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.NODE_VERSION }}
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
@@ -84,8 +88,8 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
VERCEL_CLI_VERSION: ${{ needs.setup.outputs.dplUrl }}/tarballs/vercel.tgz
|
VERCEL_CLI_VERSION: ${{ needs.setup.outputs.dplUrl }}/tarballs/vercel.tgz
|
||||||
VERCEL_TEAM_TOKEN: ${{ secrets.VERCEL_TEAM_TOKEN }}
|
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
|
||||||
VERCEL_REGISTRATION_URL: ${{ secrets.VERCEL_REGISTRATION_URL }}
|
VERCEL_TEST_REGISTRATION_URL: ${{ secrets.VERCEL_TEST_REGISTRATION_URL }}
|
||||||
FORCE_COLOR: '1'
|
FORCE_COLOR: '1'
|
||||||
|
|
||||||
conclusion:
|
conclusion:
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import fs from 'fs/promises';
|
import fs from 'fs/promises';
|
||||||
import { join, dirname } from 'path';
|
import { join, dirname } from 'path';
|
||||||
import execa from 'execa';
|
|
||||||
import { getExampleList } from '../examples/example-list';
|
import { getExampleList } from '../examples/example-list';
|
||||||
import { mapOldToNew } from '../examples/map-old-to-new';
|
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.rm(pubDir, { recursive: true, force: true });
|
||||||
await fs.mkdir(pubDir);
|
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 examples = await getExampleList();
|
||||||
const pathListAll = join(pubDir, 'list-all.json');
|
const pathListAll = join(pubDir, 'list-all.json');
|
||||||
await fs.writeFile(pathListAll, JSON.stringify(examples));
|
await fs.writeFile(pathListAll, JSON.stringify(examples));
|
||||||
@@ -41,10 +46,6 @@ async function main() {
|
|||||||
JSON.stringify([...existingExamples, ...oldExamples])
|
JSON.stringify([...existingExamples, ...oldExamples])
|
||||||
);
|
);
|
||||||
|
|
||||||
const { stdout: sha } = await execa('git', ['rev-parse', '--short', 'HEAD'], {
|
|
||||||
cwd: repoRoot,
|
|
||||||
});
|
|
||||||
|
|
||||||
const tarballsDir = join(pubDir, 'tarballs');
|
const tarballsDir = join(pubDir, 'tarballs');
|
||||||
const packagesDir = join(repoRoot, 'packages');
|
const packagesDir = join(repoRoot, 'packages');
|
||||||
const packages = await fs.readdir(packagesDir);
|
const packages = await fs.readdir(packagesDir);
|
||||||
@@ -55,12 +56,21 @@ async function main() {
|
|||||||
'utf-8'
|
'utf-8'
|
||||||
);
|
);
|
||||||
const packageJson = JSON.parse(packageJsonRaw);
|
const packageJson = JSON.parse(packageJsonRaw);
|
||||||
const tarballName = `${packageJson.name
|
const files = await fs.readdir(fullDir);
|
||||||
.replace('@', '')
|
const tarballName = files.find(f => /^vercel-.+\.tgz$/.test(f));
|
||||||
.replace('/', '-')}-v${packageJson.version}-${sha.trim()}.tgz`;
|
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`);
|
const destTarballPath = join(tarballsDir, `${packageJson.name}.tgz`);
|
||||||
await fs.mkdir(dirname(destTarballPath), { recursive: true });
|
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.');
|
console.log('Completed building static frontend.');
|
||||||
|
|||||||
@@ -16,10 +16,6 @@ const frameworks = (_frameworks as Framework[])
|
|||||||
defaultRoutes: undefined,
|
defaultRoutes: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (framework.logo) {
|
|
||||||
framework.logo = `https://assets.vercel.com/zeit-inc/image/fetch/${framework.logo}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return framework;
|
return framework;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,12 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"next": "12.2.5",
|
"next": "12.3.1",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
"react-dom": "18.2.0"
|
"react-dom": "18.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "8.22.0",
|
"eslint": "8.23.1",
|
||||||
"eslint-config-next": "12.2.5"
|
"eslint-config-next": "12.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,28 +3,28 @@
|
|||||||
|
|
||||||
|
|
||||||
"@babel/runtime-corejs3@^7.10.2":
|
"@babel/runtime-corejs3@^7.10.2":
|
||||||
version "7.18.9"
|
version "7.19.1"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.9.tgz#7bacecd1cb2dd694eacd32a91fcf7021c20770ae"
|
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.19.1.tgz#f0cbbe7edda7c4109cd253bb1dee99aba4594ad9"
|
||||||
integrity sha512-qZEWeccZCrHA2Au4/X05QW5CMdm4VjUDCrGq5gf1ZDcM4hRqreKrtwAn7yci9zfgAS9apvnsFXiGBHBAxZdK9A==
|
integrity sha512-j2vJGnkopRzH+ykJ8h68wrHnEUmtK//E723jjixiAl/PPf6FhqY/vYRcMVlNydRKQjQsTsYEjpx+DZMIvnGk/g==
|
||||||
dependencies:
|
dependencies:
|
||||||
core-js-pure "^3.20.2"
|
core-js-pure "^3.25.1"
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/runtime@^7.10.2", "@babel/runtime@^7.18.9":
|
"@babel/runtime@^7.10.2", "@babel/runtime@^7.18.9":
|
||||||
version "7.18.9"
|
version "7.19.0"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259"
|
||||||
integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
|
integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA==
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@eslint/eslintrc@^1.3.0":
|
"@eslint/eslintrc@^1.3.2":
|
||||||
version "1.3.0"
|
version "1.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
|
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356"
|
||||||
integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==
|
integrity sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^6.12.4"
|
ajv "^6.12.4"
|
||||||
debug "^4.3.2"
|
debug "^4.3.2"
|
||||||
espree "^9.3.2"
|
espree "^9.4.0"
|
||||||
globals "^13.15.0"
|
globals "^13.15.0"
|
||||||
ignore "^5.2.0"
|
ignore "^5.2.0"
|
||||||
import-fresh "^3.2.1"
|
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"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d"
|
||||||
integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==
|
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":
|
"@humanwhocodes/object-schema@^1.2.1":
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
|
||||||
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
|
||||||
|
|
||||||
"@next/env@12.2.5":
|
"@next/env@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.5.tgz#d908c57b35262b94db3e431e869b72ac3e1ad3e3"
|
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.1.tgz#18266bd92de3b4aa4037b1927aa59e6f11879260"
|
||||||
integrity sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw==
|
integrity sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg==
|
||||||
|
|
||||||
"@next/eslint-plugin-next@12.2.5":
|
"@next/eslint-plugin-next@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.5.tgz#4f3acccd2ed4f9300fbf9fd480cc8a0b261889a8"
|
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.3.1.tgz#b821f27b0f175954d8d18e5d323fce040ecc79a6"
|
||||||
integrity sha512-VBjVbmqEzGiOTBq4+wpeVXt/KgknnGB6ahvC/AxiIGnN93/RCSyXhFRI4uSfftM2Ba3w7ZO7076bfKasZsA0fw==
|
integrity sha512-sw+lTf6r6P0j+g/n9y4qdWWI2syPqZx+uc0+B/fRENqfR3KpSid6MIKqc9gNwGhJASazEQ5b3w8h4cAET213jw==
|
||||||
dependencies:
|
dependencies:
|
||||||
glob "7.1.7"
|
glob "7.1.7"
|
||||||
|
|
||||||
"@next/swc-android-arm-eabi@12.2.5":
|
"@next/swc-android-arm-eabi@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.5.tgz#903a5479ab4c2705d9c08d080907475f7bacf94d"
|
resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz#b15ce8ad376102a3b8c0f3c017dde050a22bb1a3"
|
||||||
integrity sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA==
|
integrity sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ==
|
||||||
|
|
||||||
"@next/swc-android-arm64@12.2.5":
|
"@next/swc-android-arm64@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.5.tgz#2f9a98ec4166c7860510963b31bda1f57a77c792"
|
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz#85d205f568a790a137cb3c3f720d961a2436ac9c"
|
||||||
integrity sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg==
|
integrity sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q==
|
||||||
|
|
||||||
"@next/swc-darwin-arm64@12.2.5":
|
"@next/swc-darwin-arm64@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz#31b1c3c659d54be546120c488a1e1bad21c24a1d"
|
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz#b105457d6760a7916b27e46c97cb1a40547114ae"
|
||||||
integrity sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg==
|
integrity sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg==
|
||||||
|
|
||||||
"@next/swc-darwin-x64@12.2.5":
|
"@next/swc-darwin-x64@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.5.tgz#2e44dd82b2b7fef88238d1bc4d3bead5884cedfd"
|
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz#6947b39082271378896b095b6696a7791c6e32b1"
|
||||||
integrity sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A==
|
integrity sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA==
|
||||||
|
|
||||||
"@next/swc-freebsd-x64@12.2.5":
|
"@next/swc-freebsd-x64@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.5.tgz#e24e75d8c2581bfebc75e4f08f6ddbd116ce9dbd"
|
resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz#2b6c36a4d84aae8b0ea0e0da9bafc696ae27085a"
|
||||||
integrity sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw==
|
integrity sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q==
|
||||||
|
|
||||||
"@next/swc-linux-arm-gnueabihf@12.2.5":
|
"@next/swc-linux-arm-gnueabihf@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.5.tgz#46d8c514d834d2b5f67086013f0bd5e3081e10b9"
|
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz#6e421c44285cfedac1f4631d5de330dd60b86298"
|
||||||
integrity sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg==
|
integrity sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w==
|
||||||
|
|
||||||
"@next/swc-linux-arm64-gnu@12.2.5":
|
"@next/swc-linux-arm64-gnu@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.5.tgz#91f725ac217d3a1f4f9f53b553615ba582fd3d9f"
|
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz#8863f08a81f422f910af126159d2cbb9552ef717"
|
||||||
integrity sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ==
|
integrity sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ==
|
||||||
|
|
||||||
"@next/swc-linux-arm64-musl@12.2.5":
|
"@next/swc-linux-arm64-musl@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.5.tgz#e627e8c867920995810250303cd9b8e963598383"
|
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz#0038f07cf0b259d70ae0c80890d826dfc775d9f3"
|
||||||
integrity sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg==
|
integrity sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg==
|
||||||
|
|
||||||
"@next/swc-linux-x64-gnu@12.2.5":
|
"@next/swc-linux-x64-gnu@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.5.tgz#83a5e224fbc4d119ef2e0f29d0d79c40cc43887e"
|
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz#c66468f5e8181ffb096c537f0dbfb589baa6a9c1"
|
||||||
integrity sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw==
|
integrity sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA==
|
||||||
|
|
||||||
"@next/swc-linux-x64-musl@12.2.5":
|
"@next/swc-linux-x64-musl@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.5.tgz#be700d48471baac1ec2e9539396625584a317e95"
|
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz#c6269f3e96ac0395bc722ad97ce410ea5101d305"
|
||||||
integrity sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g==
|
integrity sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg==
|
||||||
|
|
||||||
"@next/swc-win32-arm64-msvc@12.2.5":
|
"@next/swc-win32-arm64-msvc@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.5.tgz#a93e958133ad3310373fda33a79aa10af2a0aa97"
|
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz#83c639ee969cee36ce247c3abd1d9df97b5ecade"
|
||||||
integrity sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw==
|
integrity sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw==
|
||||||
|
|
||||||
"@next/swc-win32-ia32-msvc@12.2.5":
|
"@next/swc-win32-ia32-msvc@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.5.tgz#4f5f7ba0a98ff89a883625d4af0125baed8b2e19"
|
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz#52995748b92aa8ad053440301bc2c0d9fbcf27c2"
|
||||||
integrity sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw==
|
integrity sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA==
|
||||||
|
|
||||||
"@next/swc-win32-x64-msvc@12.2.5":
|
"@next/swc-win32-x64-msvc@12.3.1":
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz#20fed129b04a0d3f632c6d0de135345bb623b1e4"
|
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz#27d71a95247a9eaee03d47adee7e3bd594514136"
|
||||||
integrity sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q==
|
integrity sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA==
|
||||||
|
|
||||||
"@nodelib/fs.scandir@2.1.5":
|
"@nodelib/fs.scandir@2.1.5":
|
||||||
version "2.1.5"
|
version "2.1.5"
|
||||||
@@ -150,14 +155,14 @@
|
|||||||
fastq "^1.6.0"
|
fastq "^1.6.0"
|
||||||
|
|
||||||
"@rushstack/eslint-patch@^1.1.3":
|
"@rushstack/eslint-patch@^1.1.3":
|
||||||
version "1.1.4"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz#0c8b74c50f29ee44f423f7416829c0bf8bb5eb27"
|
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz#8be36a1f66f3265389e90b5f9c9962146758f728"
|
||||||
integrity sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==
|
integrity sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==
|
||||||
|
|
||||||
"@swc/helpers@0.4.3":
|
"@swc/helpers@0.4.11":
|
||||||
version "0.4.3"
|
version "0.4.11"
|
||||||
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.3.tgz#16593dfc248c53b699d4b5026040f88ddb497012"
|
resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.11.tgz#db23a376761b3d31c26502122f349a21b592c8de"
|
||||||
integrity sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==
|
integrity sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw==
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.4.0"
|
tslib "^2.4.0"
|
||||||
|
|
||||||
@@ -167,47 +172,47 @@
|
|||||||
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
|
||||||
|
|
||||||
"@typescript-eslint/parser@^5.21.0":
|
"@typescript-eslint/parser@^5.21.0":
|
||||||
version "5.34.0"
|
version "5.38.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.34.0.tgz#ca710858ea85dbfd30c9b416a335dc49e82dbc07"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.38.0.tgz#5a59a1ff41a7b43aacd1bb2db54f6bf1c02b2ff8"
|
||||||
integrity sha512-SZ3NEnK4usd2CXkoV3jPa/vo1mWX1fqRyIVUQZR4As1vyp4fneknBNJj+OFtV8WAVgGf+rOHMSqQbs2Qn3nFZQ==
|
integrity sha512-/F63giJGLDr0ms1Cr8utDAxP2SPiglaD6V+pCOcG35P2jCqdfR7uuEhz1GIC3oy4hkUF8xA1XSXmd9hOh/a5EA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/scope-manager" "5.34.0"
|
"@typescript-eslint/scope-manager" "5.38.0"
|
||||||
"@typescript-eslint/types" "5.34.0"
|
"@typescript-eslint/types" "5.38.0"
|
||||||
"@typescript-eslint/typescript-estree" "5.34.0"
|
"@typescript-eslint/typescript-estree" "5.38.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
|
|
||||||
"@typescript-eslint/scope-manager@5.34.0":
|
"@typescript-eslint/scope-manager@5.38.0":
|
||||||
version "5.34.0"
|
version "5.38.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.34.0.tgz#14efd13dc57602937e25f188fd911f118781e527"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz#8f0927024b6b24e28671352c93b393a810ab4553"
|
||||||
integrity sha512-HNvASMQlah5RsBW6L6c7IJ0vsm+8Sope/wu5sEAf7joJYWNb1LDbJipzmdhdUOnfrDFE6LR1j57x1EYVxrY4ow==
|
integrity sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "5.34.0"
|
"@typescript-eslint/types" "5.38.0"
|
||||||
"@typescript-eslint/visitor-keys" "5.34.0"
|
"@typescript-eslint/visitor-keys" "5.38.0"
|
||||||
|
|
||||||
"@typescript-eslint/types@5.34.0":
|
"@typescript-eslint/types@5.38.0":
|
||||||
version "5.34.0"
|
version "5.38.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.34.0.tgz#217bf08049e9e7b86694d982e88a2c1566330c78"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.38.0.tgz#8cd15825e4874354e31800dcac321d07548b8a5f"
|
||||||
integrity sha512-49fm3xbbUPuzBIOcy2CDpYWqy/X7VBkxVN+DC21e0zIm3+61Z0NZi6J9mqPmSW1BDVk9FIOvuCFyUPjXz93sjA==
|
integrity sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree@5.34.0":
|
"@typescript-eslint/typescript-estree@5.38.0":
|
||||||
version "5.34.0"
|
version "5.38.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.34.0.tgz#ba7b83f4bf8ccbabf074bbf1baca7a58de3ccb9a"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz#89f86b2279815c6fb7f57d68cf9b813f0dc25d98"
|
||||||
integrity sha512-mXHAqapJJDVzxauEkfJI96j3D10sd567LlqroyCeJaHnu42sDbjxotGb3XFtGPYKPD9IyLjhsoULML1oI3M86A==
|
integrity sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "5.34.0"
|
"@typescript-eslint/types" "5.38.0"
|
||||||
"@typescript-eslint/visitor-keys" "5.34.0"
|
"@typescript-eslint/visitor-keys" "5.38.0"
|
||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
globby "^11.1.0"
|
globby "^11.1.0"
|
||||||
is-glob "^4.0.3"
|
is-glob "^4.0.3"
|
||||||
semver "^7.3.7"
|
semver "^7.3.7"
|
||||||
tsutils "^3.21.0"
|
tsutils "^3.21.0"
|
||||||
|
|
||||||
"@typescript-eslint/visitor-keys@5.34.0":
|
"@typescript-eslint/visitor-keys@5.38.0":
|
||||||
version "5.34.0"
|
version "5.38.0"
|
||||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.34.0.tgz#d0fb3e31033e82ddd5de048371ad39eb342b2d40"
|
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz#60591ca3bf78aa12b25002c0993d067c00887e34"
|
||||||
integrity sha512-O1moYjOSrab0a2fUvFpsJe0QHtvTC+cR+ovYpgKrAVXzqQyc74mv76TgY6z+aEtjQE2vgZux3CQVtGryqdcOAw==
|
integrity sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "5.34.0"
|
"@typescript-eslint/types" "5.38.0"
|
||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
|
|
||||||
acorn-jsx@^5.3.2:
|
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"
|
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001332:
|
caniuse-lite@^1.0.30001406:
|
||||||
version "1.0.30001382"
|
version "1.0.30001406"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001382.tgz#4d37f0d0b6fffb826c8e5e1c0f4bf8ce592db949"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001406.tgz#d0146e7919635479f873b4507517b627f66ab269"
|
||||||
integrity sha512-2rtJwDmSZ716Pxm1wCtbPvHtbDWAreTPxXbkc5RkKglow3Ig/4GNGazDI9/BVnXbG/wnv6r3B5FEbkfg9OcTGg==
|
integrity sha512-bWTlaXUy/rq0BBtYShc/jArYfBPjEV95euvZ8JVtO43oQExEN/WquoqpufFjNu4kSpi5cy5kMbNvzztWDfv1Jg==
|
||||||
|
|
||||||
chalk@^4.0.0:
|
chalk@^4.0.0:
|
||||||
version "4.1.2"
|
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"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||||
|
|
||||||
core-js-pure@^3.20.2:
|
core-js-pure@^3.25.1:
|
||||||
version "3.24.1"
|
version "3.25.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.24.1.tgz#8839dde5da545521bf282feb7dc6d0b425f39fd3"
|
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.25.2.tgz#44a4fd873bdd4fecf6ca11512bcefedbe87e744a"
|
||||||
integrity sha512-r1nJk41QLLPyozHUUPmILCEMtMw24NG4oWK6RbsDdjzQgg9ZvrUsPBj1MnG0wXXp1DCDU6j+wUvEmBSrtRbLXg==
|
integrity sha512-ItD7YpW1cUB4jaqFLZXe1AXkyqIxz6GqPnsDV4uF4hVcWh/WAGIqSqw5p0/WdsILM0Xht9s3Koyw05R3K6RtiA==
|
||||||
|
|
||||||
cross-spawn@^7.0.2:
|
cross-spawn@^7.0.2:
|
||||||
version "7.0.3"
|
version "7.0.3"
|
||||||
@@ -449,15 +454,15 @@ emoji-regex@^9.2.2:
|
|||||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
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:
|
es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5:
|
||||||
version "1.20.1"
|
version "1.20.2"
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.2.tgz#8495a07bc56d342a3b8ea3ab01bd986700c2ccb3"
|
||||||
integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
|
integrity sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind "^1.0.2"
|
call-bind "^1.0.2"
|
||||||
es-to-primitive "^1.2.1"
|
es-to-primitive "^1.2.1"
|
||||||
function-bind "^1.1.1"
|
function-bind "^1.1.1"
|
||||||
function.prototype.name "^1.1.5"
|
function.prototype.name "^1.1.5"
|
||||||
get-intrinsic "^1.1.1"
|
get-intrinsic "^1.1.2"
|
||||||
get-symbol-description "^1.0.0"
|
get-symbol-description "^1.0.0"
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
has-property-descriptors "^1.0.0"
|
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-shared-array-buffer "^1.0.2"
|
||||||
is-string "^1.0.7"
|
is-string "^1.0.7"
|
||||||
is-weakref "^1.0.2"
|
is-weakref "^1.0.2"
|
||||||
object-inspect "^1.12.0"
|
object-inspect "^1.12.2"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
object.assign "^4.1.2"
|
object.assign "^4.1.4"
|
||||||
regexp.prototype.flags "^1.4.3"
|
regexp.prototype.flags "^1.4.3"
|
||||||
string.prototype.trimend "^1.0.5"
|
string.prototype.trimend "^1.0.5"
|
||||||
string.prototype.trimstart "^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"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||||
|
|
||||||
eslint-config-next@12.2.5:
|
eslint-config-next@12.3.1:
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.2.5.tgz#76ce83f18cc02f6f42ed407a127f83db54fabd3c"
|
resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.3.1.tgz#5d4eb0b7903cea81fd0d5106601d3afb0a453ff4"
|
||||||
integrity sha512-SOowilkqPzW6DxKp3a3SYlrfPi5Ajs9MIzp9gVfUDxxH9QFM5ElkR1hX5m/iICJuvCbWgQqFBiA3mCMozluniw==
|
integrity sha512-EN/xwKPU6jz1G0Qi6Bd/BqMnHLyRAL0VsaQaWA7F3KkjAgZHi4f1uL1JKGWNxdQpHTW/sdGONBd0bzxUka/DJg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@next/eslint-plugin-next" "12.2.5"
|
"@next/eslint-plugin-next" "12.3.1"
|
||||||
"@rushstack/eslint-patch" "^1.1.3"
|
"@rushstack/eslint-patch" "^1.1.3"
|
||||||
"@typescript-eslint/parser" "^5.21.0"
|
"@typescript-eslint/parser" "^5.21.0"
|
||||||
eslint-import-resolver-node "^0.3.6"
|
eslint-import-resolver-node "^0.3.6"
|
||||||
eslint-import-resolver-typescript "^2.7.1"
|
eslint-import-resolver-typescript "^2.7.1"
|
||||||
eslint-plugin-import "^2.26.0"
|
eslint-plugin-import "^2.26.0"
|
||||||
eslint-plugin-jsx-a11y "^6.5.1"
|
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-plugin-react-hooks "^4.5.0"
|
||||||
|
|
||||||
eslint-import-resolver-node@^0.3.6:
|
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"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
|
||||||
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
|
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
|
||||||
|
|
||||||
eslint-plugin-react@^7.29.4:
|
eslint-plugin-react@^7.31.7:
|
||||||
version "7.30.1"
|
version "7.31.8"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.31.8.tgz#3a4f80c10be1bcbc8197be9e8b641b2a3ef219bf"
|
||||||
integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==
|
integrity sha512-5lBTZmgQmARLLSYiwI71tiGVTLUuqXantZM6vlSY39OaDSV0M7+32K5DnLkmFrwTe+Ksz0ffuLUC91RUviVZfw==
|
||||||
dependencies:
|
dependencies:
|
||||||
array-includes "^3.1.5"
|
array-includes "^3.1.5"
|
||||||
array.prototype.flatmap "^1.3.0"
|
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"
|
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
|
||||||
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
|
||||||
|
|
||||||
eslint@8.22.0:
|
eslint@8.23.1:
|
||||||
version "8.22.0"
|
version "8.23.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.22.0.tgz#78fcb044196dfa7eef30a9d65944f6f980402c48"
|
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.1.tgz#cfd7b3f7fdd07db8d16b4ac0516a29c8d8dca5dc"
|
||||||
integrity sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==
|
integrity sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint/eslintrc" "^1.3.0"
|
"@eslint/eslintrc" "^1.3.2"
|
||||||
"@humanwhocodes/config-array" "^0.10.4"
|
"@humanwhocodes/config-array" "^0.10.4"
|
||||||
"@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
|
"@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
|
||||||
|
"@humanwhocodes/module-importer" "^1.0.1"
|
||||||
ajv "^6.10.0"
|
ajv "^6.10.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
cross-spawn "^7.0.2"
|
cross-spawn "^7.0.2"
|
||||||
@@ -644,13 +650,12 @@ eslint@8.22.0:
|
|||||||
eslint-scope "^7.1.1"
|
eslint-scope "^7.1.1"
|
||||||
eslint-utils "^3.0.0"
|
eslint-utils "^3.0.0"
|
||||||
eslint-visitor-keys "^3.3.0"
|
eslint-visitor-keys "^3.3.0"
|
||||||
espree "^9.3.3"
|
espree "^9.4.0"
|
||||||
esquery "^1.4.0"
|
esquery "^1.4.0"
|
||||||
esutils "^2.0.2"
|
esutils "^2.0.2"
|
||||||
fast-deep-equal "^3.1.3"
|
fast-deep-equal "^3.1.3"
|
||||||
file-entry-cache "^6.0.1"
|
file-entry-cache "^6.0.1"
|
||||||
find-up "^5.0.0"
|
find-up "^5.0.0"
|
||||||
functional-red-black-tree "^1.0.1"
|
|
||||||
glob-parent "^6.0.1"
|
glob-parent "^6.0.1"
|
||||||
globals "^13.15.0"
|
globals "^13.15.0"
|
||||||
globby "^11.1.0"
|
globby "^11.1.0"
|
||||||
@@ -659,6 +664,7 @@ eslint@8.22.0:
|
|||||||
import-fresh "^3.0.0"
|
import-fresh "^3.0.0"
|
||||||
imurmurhash "^0.1.4"
|
imurmurhash "^0.1.4"
|
||||||
is-glob "^4.0.0"
|
is-glob "^4.0.0"
|
||||||
|
js-sdsl "^4.1.4"
|
||||||
js-yaml "^4.1.0"
|
js-yaml "^4.1.0"
|
||||||
json-stable-stringify-without-jsonify "^1.0.1"
|
json-stable-stringify-without-jsonify "^1.0.1"
|
||||||
levn "^0.4.1"
|
levn "^0.4.1"
|
||||||
@@ -670,12 +676,11 @@ eslint@8.22.0:
|
|||||||
strip-ansi "^6.0.1"
|
strip-ansi "^6.0.1"
|
||||||
strip-json-comments "^3.1.0"
|
strip-json-comments "^3.1.0"
|
||||||
text-table "^0.2.0"
|
text-table "^0.2.0"
|
||||||
v8-compile-cache "^2.0.3"
|
|
||||||
|
|
||||||
espree@^9.3.2, espree@^9.3.3:
|
espree@^9.4.0:
|
||||||
version "9.3.3"
|
version "9.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.3.tgz#2dd37c4162bb05f433ad3c1a52ddf8a49dc08e9d"
|
resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a"
|
||||||
integrity sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==
|
integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn "^8.8.0"
|
acorn "^8.8.0"
|
||||||
acorn-jsx "^5.3.2"
|
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==
|
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||||
|
|
||||||
fast-glob@^3.2.9:
|
fast-glob@^3.2.9:
|
||||||
version "3.2.11"
|
version "3.2.12"
|
||||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
|
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
|
||||||
integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
|
integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@nodelib/fs.stat" "^2.0.2"
|
"@nodelib/fs.stat" "^2.0.2"
|
||||||
"@nodelib/fs.walk" "^1.2.3"
|
"@nodelib/fs.walk" "^1.2.3"
|
||||||
@@ -793,20 +798,15 @@ function.prototype.name@^1.1.5:
|
|||||||
es-abstract "^1.19.0"
|
es-abstract "^1.19.0"
|
||||||
functions-have-names "^1.2.2"
|
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:
|
functions-have-names@^1.2.2:
|
||||||
version "1.2.3"
|
version "1.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
|
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
|
||||||
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
|
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
|
||||||
|
|
||||||
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
|
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598"
|
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385"
|
||||||
integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==
|
integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
|
||||||
dependencies:
|
dependencies:
|
||||||
function-bind "^1.1.1"
|
function-bind "^1.1.1"
|
||||||
has "^1.0.3"
|
has "^1.0.3"
|
||||||
@@ -974,9 +974,9 @@ is-boolean-object@^1.1.0:
|
|||||||
has-tostringtag "^1.0.0"
|
has-tostringtag "^1.0.0"
|
||||||
|
|
||||||
is-callable@^1.1.4, is-callable@^1.2.4:
|
is-callable@^1.1.4, is-callable@^1.2.4:
|
||||||
version "1.2.4"
|
version "1.2.6"
|
||||||
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
|
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.6.tgz#fd6170b0b8c7e2cc73de342ef8284a2202023c44"
|
||||||
integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
|
integrity sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==
|
||||||
|
|
||||||
is-core-module@^2.8.1, is-core-module@^2.9.0:
|
is-core-module@^2.8.1, is-core-module@^2.9.0:
|
||||||
version "2.10.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"
|
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
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":
|
"js-tokens@^3.0.0 || ^4.0.0":
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
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"
|
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||||
|
|
||||||
next@12.2.5:
|
next@12.3.1:
|
||||||
version "12.2.5"
|
version "12.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717"
|
resolved "https://registry.yarnpkg.com/next/-/next-12.3.1.tgz#127b825ad2207faf869b33393ec8c75fe61e50f1"
|
||||||
integrity sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA==
|
integrity sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@next/env" "12.2.5"
|
"@next/env" "12.3.1"
|
||||||
"@swc/helpers" "0.4.3"
|
"@swc/helpers" "0.4.11"
|
||||||
caniuse-lite "^1.0.30001332"
|
caniuse-lite "^1.0.30001406"
|
||||||
postcss "8.4.14"
|
postcss "8.4.14"
|
||||||
styled-jsx "5.0.4"
|
styled-jsx "5.0.7"
|
||||||
use-sync-external-store "1.2.0"
|
use-sync-external-store "1.2.0"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@next/swc-android-arm-eabi" "12.2.5"
|
"@next/swc-android-arm-eabi" "12.3.1"
|
||||||
"@next/swc-android-arm64" "12.2.5"
|
"@next/swc-android-arm64" "12.3.1"
|
||||||
"@next/swc-darwin-arm64" "12.2.5"
|
"@next/swc-darwin-arm64" "12.3.1"
|
||||||
"@next/swc-darwin-x64" "12.2.5"
|
"@next/swc-darwin-x64" "12.3.1"
|
||||||
"@next/swc-freebsd-x64" "12.2.5"
|
"@next/swc-freebsd-x64" "12.3.1"
|
||||||
"@next/swc-linux-arm-gnueabihf" "12.2.5"
|
"@next/swc-linux-arm-gnueabihf" "12.3.1"
|
||||||
"@next/swc-linux-arm64-gnu" "12.2.5"
|
"@next/swc-linux-arm64-gnu" "12.3.1"
|
||||||
"@next/swc-linux-arm64-musl" "12.2.5"
|
"@next/swc-linux-arm64-musl" "12.3.1"
|
||||||
"@next/swc-linux-x64-gnu" "12.2.5"
|
"@next/swc-linux-x64-gnu" "12.3.1"
|
||||||
"@next/swc-linux-x64-musl" "12.2.5"
|
"@next/swc-linux-x64-musl" "12.3.1"
|
||||||
"@next/swc-win32-arm64-msvc" "12.2.5"
|
"@next/swc-win32-arm64-msvc" "12.3.1"
|
||||||
"@next/swc-win32-ia32-msvc" "12.2.5"
|
"@next/swc-win32-ia32-msvc" "12.3.1"
|
||||||
"@next/swc-win32-x64-msvc" "12.2.5"
|
"@next/swc-win32-x64-msvc" "12.3.1"
|
||||||
|
|
||||||
object-assign@^4.1.1:
|
object-assign@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
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"
|
version "1.12.2"
|
||||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
|
||||||
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
|
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"
|
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
|
||||||
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
|
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"
|
version "4.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
|
resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
|
||||||
integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
|
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"
|
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||||
|
|
||||||
styled-jsx@5.0.4:
|
styled-jsx@5.0.7:
|
||||||
version "5.0.4"
|
version "5.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.4.tgz#5b1bd0b9ab44caae3dd1361295559706e044aa53"
|
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.7.tgz#be44afc53771b983769ac654d355ca8d019dff48"
|
||||||
integrity sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ==
|
integrity sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==
|
||||||
|
|
||||||
supports-color@^7.1.0:
|
supports-color@^7.1.0:
|
||||||
version "7.2.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"
|
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==
|
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:
|
which-boxed-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
"prettier": "2.6.2",
|
"prettier": "2.6.2",
|
||||||
"ts-eager": "2.0.2",
|
"ts-eager": "2.0.2",
|
||||||
"ts-jest": "28.0.5",
|
"ts-jest": "28.0.5",
|
||||||
"turbo": "1.3.2-canary.1"
|
"turbo": "1.4.7"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lerna": "lerna",
|
"lerna": "lerna",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/build-utils",
|
"name": "@vercel/build-utils",
|
||||||
"version": "5.4.1",
|
"version": "5.5.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.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 }[];
|
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'>) {
|
constructor(params: Omit<EdgeFunction, 'type'>) {
|
||||||
this.type = 'EdgeFunction';
|
this.type = 'EdgeFunction';
|
||||||
this.name = params.name;
|
this.name = params.name;
|
||||||
@@ -46,5 +49,6 @@ export class EdgeFunction {
|
|||||||
this.files = params.files;
|
this.files = params.files;
|
||||||
this.envVarsInUse = params.envVarsInUse;
|
this.envVarsInUse = params.envVarsInUse;
|
||||||
this.assets = params.assets;
|
this.assets = params.assets;
|
||||||
|
this.regions = params.regions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { NowBuildError } from '../errors';
|
|||||||
import { Meta, PackageJson, NodeVersion, Config } from '../types';
|
import { Meta, PackageJson, NodeVersion, Config } from '../types';
|
||||||
import { getSupportedNodeVersion, getLatestNodeVersion } from './node-version';
|
import { getSupportedNodeVersion, getLatestNodeVersion } from './node-version';
|
||||||
import { readConfigFile } from './read-config-file';
|
import { readConfigFile } from './read-config-file';
|
||||||
|
import { cloneEnv } from '../clone-env';
|
||||||
|
|
||||||
// Only allow one `runNpmInstall()` invocation to run concurrently
|
// Only allow one `runNpmInstall()` invocation to run concurrently
|
||||||
const runNpmInstallSema = new Sema(1);
|
const runNpmInstallSema = new Sema(1);
|
||||||
@@ -217,7 +218,7 @@ export function getSpawnOptions(
|
|||||||
nodeVersion: NodeVersion
|
nodeVersion: NodeVersion
|
||||||
): SpawnOptions {
|
): SpawnOptions {
|
||||||
const opts = {
|
const opts = {
|
||||||
env: { ...process.env },
|
env: cloneEnv(process.env),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!meta.isDev) {
|
if (!meta.isDev) {
|
||||||
@@ -449,7 +450,7 @@ export async function runNpmInstall(
|
|||||||
debug(`Installing to ${destPath}`);
|
debug(`Installing to ${destPath}`);
|
||||||
|
|
||||||
const opts: SpawnOptionsExtended = { cwd: destPath, ...spawnOpts };
|
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;
|
delete env.NODE_ENV;
|
||||||
opts.env = getEnvForPackageManager({
|
opts.env = getEnvForPackageManager({
|
||||||
cliType,
|
cliType,
|
||||||
@@ -458,12 +459,29 @@ export async function runNpmInstall(
|
|||||||
env,
|
env,
|
||||||
});
|
});
|
||||||
let commandArgs: string[];
|
let commandArgs: string[];
|
||||||
|
const isPotentiallyBrokenNpm =
|
||||||
|
cliType === 'npm' &&
|
||||||
|
nodeVersion?.major === 16 &&
|
||||||
|
!args.includes('--legacy-peer-deps') &&
|
||||||
|
spawnOpts?.env?.ENABLE_EXPERIMENTAL_COREPACK !== '1';
|
||||||
|
|
||||||
if (cliType === 'npm') {
|
if (cliType === 'npm') {
|
||||||
opts.prettyCommand = 'npm install';
|
opts.prettyCommand = 'npm install';
|
||||||
commandArgs = args
|
commandArgs = args
|
||||||
.filter(a => a !== '--prefer-offline')
|
.filter(a => a !== '--prefer-offline')
|
||||||
.concat(['install', '--no-audit', '--unsafe-perm']);
|
.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') {
|
} else if (cliType === 'pnpm') {
|
||||||
// PNPM's install command is similar to NPM's but without the audit nonsense
|
// PNPM's install command is similar to NPM's but without the audit nonsense
|
||||||
// @see options https://pnpm.io/cli/install
|
// @see options https://pnpm.io/cli/install
|
||||||
@@ -480,7 +498,26 @@ export async function runNpmInstall(
|
|||||||
commandArgs.push('--production');
|
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]`);
|
debug(`Install complete [${Date.now() - installTime}ms]`);
|
||||||
return true;
|
return true;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -591,10 +628,7 @@ export async function runPackageJsonScript(
|
|||||||
cliType,
|
cliType,
|
||||||
lockfileVersion,
|
lockfileVersion,
|
||||||
nodeVersion: undefined,
|
nodeVersion: undefined,
|
||||||
env: {
|
env: cloneEnv(process.env, spawnOpts?.env),
|
||||||
...process.env,
|
|
||||||
...spawnOpts?.env,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import debug from './debug';
|
|||||||
import getIgnoreFilter from './get-ignore-filter';
|
import getIgnoreFilter from './get-ignore-filter';
|
||||||
import { getPlatformEnv } from './get-platform-env';
|
import { getPlatformEnv } from './get-platform-env';
|
||||||
import { getPrefixedEnvVars } from './get-prefixed-env-vars';
|
import { getPrefixedEnvVars } from './get-prefixed-env-vars';
|
||||||
|
import { cloneEnv } from './clone-env';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
FileBlob,
|
FileBlob,
|
||||||
@@ -84,6 +85,7 @@ export {
|
|||||||
getLambdaOptionsFromFunction,
|
getLambdaOptionsFromFunction,
|
||||||
scanParentDirs,
|
scanParentDirs,
|
||||||
getIgnoreFilter,
|
getIgnoreFilter,
|
||||||
|
cloneEnv,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { EdgeFunction } from './edge-function';
|
export { EdgeFunction } from './edge-function';
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export interface Config {
|
|||||||
devCommand?: string;
|
devCommand?: string;
|
||||||
framework?: string | null;
|
framework?: string | null;
|
||||||
nodeVersion?: string;
|
nodeVersion?: string;
|
||||||
|
middleware?: boolean;
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,6 +342,7 @@ export interface BuilderV2 {
|
|||||||
version: 2;
|
version: 2;
|
||||||
build: BuildV2;
|
build: BuildV2;
|
||||||
prepareCache?: PrepareCache;
|
prepareCache?: PrepareCache;
|
||||||
|
shouldServe?: ShouldServe;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BuilderV3 {
|
export interface BuilderV3 {
|
||||||
|
|||||||
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,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"name": "20-npm-7",
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ const skipFixtures: string[] = [
|
|||||||
'08-zero-config-middleman',
|
'08-zero-config-middleman',
|
||||||
'21-npm-workspaces',
|
'21-npm-workspaces',
|
||||||
'23-pnpm-workspaces',
|
'23-pnpm-workspaces',
|
||||||
|
'41-nx-monorepo',
|
||||||
|
'42-npm-workspace-with-nx',
|
||||||
];
|
];
|
||||||
|
|
||||||
// eslint-disable-next-line no-restricted-syntax
|
// 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',
|
||||||
|
});
|
||||||
|
});
|
||||||
172
packages/build-utils/test/unit.run-npm-install.test.ts
vendored
Normal file
172
packages/build-utils/test/unit.run-npm-install.test.ts
vendored
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
const spawnMock = jest.fn();
|
||||||
|
jest.mock('cross-spawn', () => {
|
||||||
|
const spawn = (...args: any) => {
|
||||||
|
spawnMock(...args);
|
||||||
|
const child = {
|
||||||
|
on: (type: string, fn: (code: number) => void) => {
|
||||||
|
if (type === 'close') {
|
||||||
|
return fn(0);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return child;
|
||||||
|
};
|
||||||
|
return spawn;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
spawnMock.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
|
import path from 'path';
|
||||||
|
import { runNpmInstall, cloneEnv } from '../src';
|
||||||
|
import type { Meta } from '../src/types';
|
||||||
|
|
||||||
|
function getTestSpawnOpts(env: Record<string, string>) {
|
||||||
|
return { env: cloneEnv(process.env, env) };
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNodeVersion(major: number) {
|
||||||
|
return { major, range: `${major}.x`, runtime: `nodejs${major}.x` };
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should not include peer dependencies when missing VERCEL_NPM_LEGACY_PEER_DEPS on node16', async () => {
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
||||||
|
const meta: Meta = {};
|
||||||
|
const spawnOpts = getTestSpawnOpts({});
|
||||||
|
const nodeVersion = { major: 16 } as any;
|
||||||
|
await runNpmInstall(fixture, [], spawnOpts, meta, nodeVersion);
|
||||||
|
expect(spawnMock.mock.calls.length).toBe(1);
|
||||||
|
const args = spawnMock.mock.calls[0];
|
||||||
|
expect(args[0]).toEqual('npm');
|
||||||
|
expect(args[1]).toEqual(['install', '--no-audit', '--unsafe-perm']);
|
||||||
|
expect(args[2]).toEqual({
|
||||||
|
cwd: fixture,
|
||||||
|
prettyCommand: 'npm install',
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: expect.any(Object),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should include peer dependencies when VERCEL_NPM_LEGACY_PEER_DEPS=1 on node16', async () => {
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
||||||
|
const meta: Meta = {};
|
||||||
|
const spawnOpts = getTestSpawnOpts({ VERCEL_NPM_LEGACY_PEER_DEPS: '1' });
|
||||||
|
const nodeVersion = getNodeVersion(16);
|
||||||
|
await runNpmInstall(fixture, [], spawnOpts, meta, nodeVersion);
|
||||||
|
expect(spawnMock.mock.calls.length).toBe(1);
|
||||||
|
const args = spawnMock.mock.calls[0];
|
||||||
|
expect(args[0]).toEqual('npm');
|
||||||
|
expect(args[1]).toEqual([
|
||||||
|
'install',
|
||||||
|
'--no-audit',
|
||||||
|
'--unsafe-perm',
|
||||||
|
'--legacy-peer-deps',
|
||||||
|
]);
|
||||||
|
expect(args[2]).toEqual({
|
||||||
|
cwd: fixture,
|
||||||
|
prettyCommand: 'npm install',
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: expect.any(Object),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not include peer dependencies when VERCEL_NPM_LEGACY_PEER_DEPS=1 on node14', async () => {
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
||||||
|
const meta: Meta = {};
|
||||||
|
const spawnOpts = getTestSpawnOpts({ VERCEL_NPM_LEGACY_PEER_DEPS: '1' });
|
||||||
|
const nodeVersion = getNodeVersion(14);
|
||||||
|
await runNpmInstall(fixture, [], spawnOpts, meta, nodeVersion);
|
||||||
|
expect(spawnMock.mock.calls.length).toBe(1);
|
||||||
|
const args = spawnMock.mock.calls[0];
|
||||||
|
expect(args[0]).toEqual('npm');
|
||||||
|
expect(args[1]).toEqual(['install', '--no-audit', '--unsafe-perm']);
|
||||||
|
expect(args[2]).toEqual({
|
||||||
|
cwd: fixture,
|
||||||
|
prettyCommand: 'npm install',
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: expect.any(Object),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not include peer dependencies when VERCEL_NPM_LEGACY_PEER_DEPS=1 on node16 with corepack enabled', async () => {
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
|
||||||
|
const meta: Meta = {};
|
||||||
|
const spawnOpts = getTestSpawnOpts({
|
||||||
|
VERCEL_NPM_LEGACY_PEER_DEPS: '1',
|
||||||
|
ENABLE_EXPERIMENTAL_COREPACK: '1',
|
||||||
|
});
|
||||||
|
const nodeVersion = getNodeVersion(16);
|
||||||
|
await runNpmInstall(fixture, [], spawnOpts, meta, nodeVersion);
|
||||||
|
expect(spawnMock.mock.calls.length).toBe(1);
|
||||||
|
const args = spawnMock.mock.calls[0];
|
||||||
|
expect(args[0]).toEqual('npm');
|
||||||
|
expect(args[1]).toEqual(['install', '--no-audit', '--unsafe-perm']);
|
||||||
|
expect(args[2]).toEqual({
|
||||||
|
cwd: fixture,
|
||||||
|
prettyCommand: 'npm install',
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: expect.any(Object),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only invoke `runNpmInstall()` once per `package.json` file (serial)', async () => {
|
||||||
|
const meta: Meta = {};
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||||
|
const apiDir = path.join(fixture, 'api');
|
||||||
|
|
||||||
|
const run1 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||||
|
expect(run1).toEqual(true);
|
||||||
|
expect(
|
||||||
|
(meta.runNpmInstallSet as Set<string>).has(
|
||||||
|
path.join(fixture, 'package.json')
|
||||||
|
)
|
||||||
|
).toEqual(true);
|
||||||
|
|
||||||
|
const run2 = await runNpmInstall(apiDir, [], undefined, meta);
|
||||||
|
expect(run2).toEqual(false);
|
||||||
|
|
||||||
|
const run3 = await runNpmInstall(fixture, [], undefined, meta);
|
||||||
|
expect(run3).toEqual(false);
|
||||||
|
|
||||||
|
expect(spawnMock.mock.calls.length).toBe(1);
|
||||||
|
const args = spawnMock.mock.calls[0];
|
||||||
|
expect(args[0]).toEqual('yarn');
|
||||||
|
expect(args[1]).toEqual(['install']);
|
||||||
|
expect(args[2]).toEqual({
|
||||||
|
cwd: apiDir,
|
||||||
|
prettyCommand: 'yarn install',
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: expect.any(Object),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only invoke `runNpmInstall()` once per `package.json` file (parallel)', async () => {
|
||||||
|
const meta: Meta = {};
|
||||||
|
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
||||||
|
const apiDir = path.join(fixture, 'api');
|
||||||
|
const [run1, run2, run3] = await Promise.all([
|
||||||
|
runNpmInstall(apiDir, [], undefined, meta),
|
||||||
|
runNpmInstall(apiDir, [], undefined, meta),
|
||||||
|
runNpmInstall(fixture, [], undefined, meta),
|
||||||
|
]);
|
||||||
|
expect(run1).toEqual(true);
|
||||||
|
expect(run2).toEqual(false);
|
||||||
|
expect(run3).toEqual(false);
|
||||||
|
expect(
|
||||||
|
(meta.runNpmInstallSet as Set<string>).has(
|
||||||
|
path.join(fixture, 'package.json')
|
||||||
|
)
|
||||||
|
).toEqual(true);
|
||||||
|
|
||||||
|
expect(spawnMock.mock.calls.length).toBe(1);
|
||||||
|
const args = spawnMock.mock.calls[0];
|
||||||
|
expect(args[0]).toEqual('yarn');
|
||||||
|
expect(args[1]).toEqual(['install']);
|
||||||
|
expect(args[2]).toEqual({
|
||||||
|
cwd: apiDir,
|
||||||
|
prettyCommand: 'yarn install',
|
||||||
|
stdio: 'inherit',
|
||||||
|
env: expect.any(Object),
|
||||||
|
});
|
||||||
|
});
|
||||||
63
packages/build-utils/test/unit.test.ts
vendored
63
packages/build-utils/test/unit.test.ts
vendored
@@ -1,7 +1,6 @@
|
|||||||
import ms from 'ms';
|
import ms from 'ms';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs, { readlink } from 'fs-extra';
|
import fs, { readlink } from 'fs-extra';
|
||||||
import retry from 'async-retry';
|
|
||||||
import { strict as assert, strictEqual } from 'assert';
|
import { strict as assert, strictEqual } from 'assert';
|
||||||
import { createZip } from '../src/lambda';
|
import { createZip } from '../src/lambda';
|
||||||
import { getSupportedNodeVersion } from '../src/fs/node-version';
|
import { getSupportedNodeVersion } from '../src/fs/node-version';
|
||||||
@@ -16,7 +15,6 @@ import {
|
|||||||
runPackageJsonScript,
|
runPackageJsonScript,
|
||||||
scanParentDirs,
|
scanParentDirs,
|
||||||
FileBlob,
|
FileBlob,
|
||||||
Meta,
|
|
||||||
} from '../src';
|
} from '../src';
|
||||||
|
|
||||||
jest.setTimeout(10 * 1000);
|
jest.setTimeout(10 * 1000);
|
||||||
@@ -578,53 +576,16 @@ it('should detect package.json in nested frontend', async () => {
|
|||||||
expect(result.packageJsonPath).toEqual(path.join(fixture, 'package.json'));
|
expect(result.packageJsonPath).toEqual(path.join(fixture, 'package.json'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should only invoke `runNpmInstall()` once per `package.json` file (serial)', async () => {
|
it('should retry npm install when peer deps invalid and npm@8 on node@16', async () => {
|
||||||
const meta: Meta = {};
|
const nodeMajor = Number(process.versions.node.split('.')[0]);
|
||||||
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
if (nodeMajor !== 16) {
|
||||||
const apiDir = path.join(fixture, 'api');
|
console.log(`Skipping test on node@${nodeMajor}`);
|
||||||
const retryOpts = { maxRetryTime: 1000 };
|
return;
|
||||||
let run1, run2, run3;
|
}
|
||||||
await retry(async () => {
|
const fixture = path.join(__dirname, 'fixtures', '15-npm-8-legacy-peer-deps');
|
||||||
run1 = await runNpmInstall(apiDir, [], undefined, meta);
|
const nodeVersion = { major: nodeMajor } as any;
|
||||||
expect(run1).toEqual(true);
|
await runNpmInstall(fixture, [], {}, {}, nodeVersion);
|
||||||
expect(
|
expect(warningMessages).toStrictEqual([
|
||||||
(meta.runNpmInstallSet as Set<string>).has(
|
'Warning: Retrying "Install Command" with `--legacy-peer-deps` which may accept a potentially broken dependency and slow install time.',
|
||||||
path.join(fixture, 'package.json')
|
]);
|
||||||
)
|
|
||||||
).toEqual(true);
|
|
||||||
}, retryOpts);
|
|
||||||
await retry(async () => {
|
|
||||||
run2 = await runNpmInstall(apiDir, [], undefined, meta);
|
|
||||||
expect(run2).toEqual(false);
|
|
||||||
}, retryOpts);
|
|
||||||
await retry(async () => {
|
|
||||||
run3 = await runNpmInstall(fixture, [], undefined, meta);
|
|
||||||
expect(run3).toEqual(false);
|
|
||||||
}, retryOpts);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should only invoke `runNpmInstall()` once per `package.json` file (parallel)', async () => {
|
|
||||||
const meta: Meta = {};
|
|
||||||
const fixture = path.join(__dirname, 'fixtures', '02-zero-config-api');
|
|
||||||
const apiDir = path.join(fixture, 'api');
|
|
||||||
let results: [boolean, boolean, boolean] | undefined;
|
|
||||||
await retry(
|
|
||||||
async () => {
|
|
||||||
results = await Promise.all([
|
|
||||||
runNpmInstall(apiDir, [], undefined, meta),
|
|
||||||
runNpmInstall(apiDir, [], undefined, meta),
|
|
||||||
runNpmInstall(fixture, [], undefined, meta),
|
|
||||||
]);
|
|
||||||
},
|
|
||||||
{ maxRetryTime: 3000 }
|
|
||||||
);
|
|
||||||
const [run1, run2, run3] = results || [];
|
|
||||||
expect(run1).toEqual(true);
|
|
||||||
expect(run2).toEqual(false);
|
|
||||||
expect(run3).toEqual(false);
|
|
||||||
expect(
|
|
||||||
(meta.runNpmInstallSet as Set<string>).has(
|
|
||||||
path.join(fixture, 'package.json')
|
|
||||||
)
|
|
||||||
).toEqual(true);
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vercel",
|
"name": "vercel",
|
||||||
"version": "28.2.1",
|
"version": "28.4.2",
|
||||||
"preferGlobal": true,
|
"preferGlobal": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"description": "The command-line interface for Vercel",
|
"description": "The command-line interface for Vercel",
|
||||||
@@ -41,16 +41,16 @@
|
|||||||
"node": ">= 14"
|
"node": ">= 14"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "5.4.1",
|
"@vercel/build-utils": "5.5.0",
|
||||||
"@vercel/go": "2.2.4",
|
"@vercel/go": "2.2.8",
|
||||||
"@vercel/hydrogen": "0.0.17",
|
"@vercel/hydrogen": "0.0.21",
|
||||||
"@vercel/next": "3.1.23",
|
"@vercel/next": "3.1.29",
|
||||||
"@vercel/node": "2.5.12",
|
"@vercel/node": "2.5.18",
|
||||||
"@vercel/python": "3.1.13",
|
"@vercel/python": "3.1.17",
|
||||||
"@vercel/redwood": "1.0.21",
|
"@vercel/redwood": "1.0.26",
|
||||||
"@vercel/remix": "1.0.22",
|
"@vercel/remix": "1.0.27",
|
||||||
"@vercel/ruby": "1.3.30",
|
"@vercel/ruby": "1.3.34",
|
||||||
"@vercel/static-build": "1.0.21",
|
"@vercel/static-build": "1.0.26",
|
||||||
"update-notifier": "5.1.0"
|
"update-notifier": "5.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -95,9 +95,9 @@
|
|||||||
"@types/which": "1.3.2",
|
"@types/which": "1.3.2",
|
||||||
"@types/write-json-file": "2.2.1",
|
"@types/write-json-file": "2.2.1",
|
||||||
"@types/yauzl-promise": "2.1.0",
|
"@types/yauzl-promise": "2.1.0",
|
||||||
"@vercel/client": "12.2.3",
|
"@vercel/client": "12.2.7",
|
||||||
"@vercel/frameworks": "1.1.3",
|
"@vercel/frameworks": "1.1.6",
|
||||||
"@vercel/fs-detectors": "2.1.0",
|
"@vercel/fs-detectors": "3.4.0",
|
||||||
"@vercel/fun": "1.0.4",
|
"@vercel/fun": "1.0.4",
|
||||||
"@vercel/ncc": "0.24.0",
|
"@vercel/ncc": "0.24.0",
|
||||||
"@zeit/source-map-support": "0.6.2",
|
"@zeit/source-map-support": "0.6.2",
|
||||||
|
|||||||
@@ -555,7 +555,150 @@ async function doBuild(
|
|||||||
builds: builderRoutes,
|
builds: builderRoutes,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mergedImages = mergeImages(buildResults.values());
|
const images = vercelConfig?.images
|
||||||
|
if (images) {
|
||||||
|
if (typeof images !== 'object') {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images" should be an object received ${typeof images}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(images.domains)) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.domains" should be an Array received ${typeof images.domains}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (images.domains.length > 50) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.domains" exceeds length of 50 received length (${images.domains.length}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const invalidImageDomains = images.domains.filter(
|
||||||
|
(d: unknown) => typeof d !== 'string'
|
||||||
|
);
|
||||||
|
if (invalidImageDomains.length > 0) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.domains" should be an Array of strings received invalid values (${invalidImageDomains.join(
|
||||||
|
', '
|
||||||
|
)}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (images.remotePatterns) {
|
||||||
|
if (!Array.isArray(images.remotePatterns)) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.remotePatterns" should be an Array received ${typeof images.remotePatterns}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (images.remotePatterns.length > 50) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.remotePatterns" exceeds length of 50, received length (${images.remotePatterns.length}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const validProps = new Set(['protocol', 'hostname', 'pathname', 'port']);
|
||||||
|
const requiredProps = ['hostname'];
|
||||||
|
const invalidPatterns = images.remotePatterns.filter(
|
||||||
|
(d: unknown) =>
|
||||||
|
!d ||
|
||||||
|
typeof d !== 'object' ||
|
||||||
|
Object.entries(d).some(
|
||||||
|
([k, v]) => !validProps.has(k) || typeof v !== 'string'
|
||||||
|
) ||
|
||||||
|
requiredProps.some(k => !(k in d))
|
||||||
|
);
|
||||||
|
if (invalidPatterns.length > 0) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.remotePatterns" received invalid values:\n${invalidPatterns
|
||||||
|
.map(item => JSON.stringify(item))
|
||||||
|
.join(
|
||||||
|
'\n'
|
||||||
|
)}\n\nremotePatterns value must follow format { protocol: 'https', hostname: 'example.com', port: '', pathname: '/imgs/**' }.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(images.sizes)) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.sizes" should be an Array received ${typeof images.sizes}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (images.sizes.length < 1 || images.sizes.length > 50) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.sizes" should be an Array of length between 1 to 50 received length (${images.sizes.length}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const invalidImageSizes = images.sizes.filter((d: unknown) => {
|
||||||
|
return typeof d !== 'number' || d < 1 || d > 10000;
|
||||||
|
});
|
||||||
|
if (invalidImageSizes.length > 0) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.sizes" should be an Array of numbers that are between 1 and 10000, received invalid values (${invalidImageSizes.join(
|
||||||
|
', '
|
||||||
|
)}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (images.minimumCacheTTL) {
|
||||||
|
if (
|
||||||
|
!Number.isInteger(images.minimumCacheTTL) ||
|
||||||
|
images.minimumCacheTTL < 0
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.minimumCacheTTL" should be an integer 0 or more received (${images.minimumCacheTTL}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (images.formats) {
|
||||||
|
if (!Array.isArray(images.formats)) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.formats" should be an Array received ${typeof images.formats}.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (images.formats.length < 1 || images.formats.length > 2) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.formats" must be length 1 or 2, received length (${images.formats.length}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const invalid = images.formats.filter(f => {
|
||||||
|
return f !== 'image/avif' && f !== 'image/webp';
|
||||||
|
});
|
||||||
|
if (invalid.length > 0) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.formats" should be an Array of mime type strings, received invalid values (${invalid.join(
|
||||||
|
', '
|
||||||
|
)}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof images.dangerouslyAllowSVG !== 'undefined' &&
|
||||||
|
typeof images.dangerouslyAllowSVG !== 'boolean'
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.dangerouslyAllowSVG" should be a boolean received (${images.dangerouslyAllowSVG}).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof images.contentSecurityPolicy !== 'undefined' &&
|
||||||
|
typeof images.contentSecurityPolicy !== 'string'
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
`vercel.json "images.contentSecurityPolicy" should be a string received ${images.contentSecurityPolicy}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergedImages = mergeImages(images, buildResults.values());
|
||||||
const mergedWildcard = mergeWildcard(buildResults.values());
|
const mergedWildcard = mergeWildcard(buildResults.values());
|
||||||
const mergedOverrides: Record<string, PathOverride> =
|
const mergedOverrides: Record<string, PathOverride> =
|
||||||
overrides.length > 0 ? Object.assign({}, ...overrides) : undefined;
|
overrides.length > 0 ? Object.assign({}, ...overrides) : undefined;
|
||||||
@@ -624,9 +767,9 @@ function expandBuild(files: string[], build: Builder): Builder[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function mergeImages(
|
function mergeImages(
|
||||||
|
images: BuildResultV2Typical['images'],
|
||||||
buildResults: Iterable<BuildResult>
|
buildResults: Iterable<BuildResult>
|
||||||
): BuildResultV2Typical['images'] {
|
): BuildResultV2Typical['images'] {
|
||||||
let images: BuildResultV2Typical['images'] = undefined;
|
|
||||||
for (const result of buildResults) {
|
for (const result of buildResults) {
|
||||||
if ('images' in result && result.images) {
|
if ('images' in result && result.images) {
|
||||||
images = Object.assign({}, images, result.images);
|
images = Object.assign({}, images, result.images);
|
||||||
|
|||||||
@@ -522,7 +522,12 @@ export default async (client: Client): Promise<number> => {
|
|||||||
quiet,
|
quiet,
|
||||||
wantsPublic: argv['--public'] || localConfig.public,
|
wantsPublic: argv['--public'] || localConfig.public,
|
||||||
type: null,
|
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,
|
regions,
|
||||||
meta,
|
meta,
|
||||||
gitMetadata,
|
gitMetadata,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { resolve, join } from 'path';
|
|||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
|
|
||||||
import DevServer from '../../util/dev/server';
|
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 { ProjectEnvVariable } from '../../types';
|
||||||
import Client from '../../util/client';
|
import Client from '../../util/client';
|
||||||
import { getLinkedProject } from '../../util/projects/link';
|
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 npa from 'npm-package-arg';
|
||||||
import { satisfies } from 'semver';
|
import { satisfies } from 'semver';
|
||||||
import { dirname, join } from 'path';
|
import { dirname, join } from 'path';
|
||||||
import { mkdirp, outputJSON, readJSON, symlink } from 'fs-extra';
|
import { mkdirp, outputJSON, readJSON, symlink } from 'fs-extra';
|
||||||
|
import { isStaticRuntime } from '@vercel/fs-detectors';
|
||||||
import {
|
import {
|
||||||
BuilderV2,
|
BuilderV2,
|
||||||
BuilderV3,
|
BuilderV3,
|
||||||
@@ -13,6 +16,9 @@ import { VERCEL_DIR } from '../projects/link';
|
|||||||
import { Output } from '../output';
|
import { Output } from '../output';
|
||||||
import readJSONFile from '../read-json-file';
|
import readJSONFile from '../read-json-file';
|
||||||
import { CantParseJSONFile } from '../errors-ts';
|
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 {
|
export interface BuilderWithPkg {
|
||||||
path: string;
|
path: string;
|
||||||
@@ -81,7 +87,7 @@ export async function resolveBuilders(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name === '@vercel/static' || name === '@now/static') {
|
if (isStaticRuntime(name)) {
|
||||||
// `@vercel/static` is a special-case built-in builder
|
// `@vercel/static` is a special-case built-in builder
|
||||||
builders.set(name, {
|
builders.set(name, {
|
||||||
builder: staticBuilder,
|
builder: staticBuilder,
|
||||||
@@ -201,15 +207,54 @@ async function installBuilders(
|
|||||||
if (err.code !== 'EEXIST') throw err;
|
if (err.code !== 'EEXIST') throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
output.debug(`Installing Builders: ${Array.from(buildersToAdd).join(', ')}`);
|
output.log(
|
||||||
await spawnAsync('yarn', ['add', '@vercel/build-utils', ...buildersToAdd], {
|
`Installing ${plural('Builder', buildersToAdd.size)}: ${Array.from(
|
||||||
cwd: buildersDir,
|
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
|
// Symlink `@now/build-utils` -> `@vercel/build-utils` to support legacy Builders
|
||||||
const nowScopePath = join(buildersDir, 'node_modules/@now');
|
const nowScopePath = join(buildersDir, 'node_modules/@now');
|
||||||
await mkdirp(nowScopePath);
|
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,
|
// Cross-reference any builderSpecs from the saved `package.json` file,
|
||||||
// in case they were installed from a URL
|
// in case they were installed from a URL
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import minimatch from 'minimatch';
|
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;
|
export const version = 2;
|
||||||
|
|
||||||
@@ -39,3 +40,18 @@ export const build: BuildV2 = async ({ entrypoint, files, config }) => {
|
|||||||
|
|
||||||
return { output };
|
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);
|
||||||
|
};
|
||||||
|
|||||||
@@ -78,16 +78,23 @@ function getLastCommit(directory: string): Promise<git.Commit> {
|
|||||||
|
|
||||||
export function isDirty(directory: string, output: Output): Promise<boolean> {
|
export function isDirty(directory: string, output: Output): Promise<boolean> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
exec('git status -s', { cwd: directory }, function (err, stdout, stderr) {
|
// note: we specify the `--no-optional-locks` git flag so that `git status`
|
||||||
let debugMessage = `Failed to determine if Git repo has been modified:`;
|
// does not perform any "optional" operations such as optimizing the index
|
||||||
if (err || stderr) {
|
// in the background: https://git-scm.com/docs/git-status#_background_refresh
|
||||||
if (err) debugMessage += `\n${err}`;
|
exec(
|
||||||
if (stderr) debugMessage += `\n${stderr.trim()}`;
|
'git --no-optional-locks status -s',
|
||||||
output.debug(debugMessage);
|
{ cwd: directory },
|
||||||
return resolve(false);
|
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,
|
FileFsRef,
|
||||||
normalizePath,
|
normalizePath,
|
||||||
} from '@vercel/build-utils';
|
} from '@vercel/build-utils';
|
||||||
import { isOfficialRuntime } from '@vercel/fs-detectors';
|
import { isStaticRuntime } from '@vercel/fs-detectors';
|
||||||
import plural from 'pluralize';
|
import plural from 'pluralize';
|
||||||
import minimatch from 'minimatch';
|
import minimatch from 'minimatch';
|
||||||
|
|
||||||
@@ -26,7 +26,6 @@ import { relative } from '../path-helpers';
|
|||||||
import { LambdaSizeExceededError } from '../errors-ts';
|
import { LambdaSizeExceededError } from '../errors-ts';
|
||||||
|
|
||||||
import DevServer from './server';
|
import DevServer from './server';
|
||||||
import { getBuilder } from './builder-cache';
|
|
||||||
import {
|
import {
|
||||||
VercelConfig,
|
VercelConfig,
|
||||||
BuildMatch,
|
BuildMatch,
|
||||||
@@ -41,6 +40,7 @@ import {
|
|||||||
import { normalizeRoutes } from '@vercel/routing-utils';
|
import { normalizeRoutes } from '@vercel/routing-utils';
|
||||||
import getUpdateCommand from '../get-update-command';
|
import getUpdateCommand from '../get-update-command';
|
||||||
import { getTitleName } from '../pkg-name';
|
import { getTitleName } from '../pkg-name';
|
||||||
|
import { importBuilders } from '../build/import-builders';
|
||||||
|
|
||||||
interface BuildMessage {
|
interface BuildMessage {
|
||||||
type: string;
|
type: string;
|
||||||
@@ -108,18 +108,18 @@ export async function executeBuild(
|
|||||||
filesRemoved?: string[]
|
filesRemoved?: string[]
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const {
|
const {
|
||||||
builderWithPkg: { runInProcess, requirePath, builder, package: pkg },
|
builderWithPkg: { path: requirePath, builder, pkg },
|
||||||
} = match;
|
} = match;
|
||||||
const { entrypoint } = match;
|
const { entrypoint, use } = match;
|
||||||
|
const isStatic = isStaticRuntime(use);
|
||||||
const { envConfigs, cwd: workPath, devCacheDir } = devServer;
|
const { envConfigs, cwd: workPath, devCacheDir } = devServer;
|
||||||
const debug = devServer.output.isDebugEnabled();
|
const debug = devServer.output.isDebugEnabled();
|
||||||
|
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const showBuildTimestamp =
|
const showBuildTimestamp = !isStatic && (!isInitialBuild || debug);
|
||||||
!isOfficialRuntime('static', match.use) && (!isInitialBuild || debug);
|
|
||||||
|
|
||||||
if (showBuildTimestamp) {
|
if (showBuildTimestamp) {
|
||||||
devServer.output.log(`Building ${match.use}:${entrypoint}`);
|
devServer.output.log(`Building ${use}:${entrypoint}`);
|
||||||
devServer.output.debug(
|
devServer.output.debug(
|
||||||
`Using \`${pkg.name}${pkg.version ? `@${pkg.version}` : ''}\``
|
`Using \`${pkg.name}${pkg.version ? `@${pkg.version}` : ''}\``
|
||||||
);
|
);
|
||||||
@@ -130,7 +130,7 @@ export async function executeBuild(
|
|||||||
let result: BuildResult;
|
let result: BuildResult;
|
||||||
|
|
||||||
let { buildProcess } = match;
|
let { buildProcess } = match;
|
||||||
if (!runInProcess && !buildProcess) {
|
if (!isStatic && !buildProcess) {
|
||||||
buildProcess = await createBuildProcess(
|
buildProcess = await createBuildProcess(
|
||||||
match,
|
match,
|
||||||
envConfigs,
|
envConfigs,
|
||||||
@@ -158,7 +158,7 @@ export async function executeBuild(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let buildResultOrOutputs: BuilderOutputs | BuildResult | BuildResultV3;
|
let buildResultOrOutputs;
|
||||||
if (buildProcess) {
|
if (buildProcess) {
|
||||||
buildProcess.send({
|
buildProcess.send({
|
||||||
type: 'build',
|
type: 'build',
|
||||||
@@ -198,16 +198,12 @@ export async function executeBuild(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort out build result to builder v2 shape
|
// 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)
|
// `BuilderOutputs` map was returned (Now Builder v1 behavior)
|
||||||
result = {
|
result = {
|
||||||
output: buildResultOrOutputs as BuilderOutputs,
|
output: buildResultOrOutputs as BuilderOutputs,
|
||||||
routes: [],
|
routes: [],
|
||||||
watch: [],
|
watch: [],
|
||||||
distPath:
|
|
||||||
typeof buildResultOrOutputs.distPath === 'string'
|
|
||||||
? buildResultOrOutputs.distPath
|
|
||||||
: undefined,
|
|
||||||
};
|
};
|
||||||
} else if (builder.version === 2) {
|
} else if (builder.version === 2) {
|
||||||
result = buildResultOrOutputs as BuildResult;
|
result = buildResultOrOutputs as BuildResult;
|
||||||
@@ -253,7 +249,7 @@ export async function executeBuild(
|
|||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`${getTitleName()} CLI does not support builder version ${
|
`${getTitleName()} CLI does not support builder version ${
|
||||||
builder.version
|
(builder as any).version
|
||||||
}.\nPlease run \`${await getUpdateCommand()}\` to update to the latest CLI.`
|
}.\nPlease run \`${await getUpdateCommand()}\` to update to the latest CLI.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -383,7 +379,7 @@ export async function executeBuild(
|
|||||||
if (showBuildTimestamp) {
|
if (showBuildTimestamp) {
|
||||||
const endTime = Date.now();
|
const endTime = Date.now();
|
||||||
devServer.output.log(
|
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 noMatches: Builder[] = [];
|
||||||
const builds = vercelConfig.builds || [{ src: '**', use: '@vercel/static' }];
|
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) {
|
for (const buildConfig of builds) {
|
||||||
let { src = '**', use, config = {} } = buildConfig;
|
let { src = '**', use, config = {} } = buildConfig;
|
||||||
@@ -439,6 +437,8 @@ export async function getBuildMatches(
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
src = relative(cwd, file);
|
src = relative(cwd, file);
|
||||||
|
|
||||||
|
const entrypoint = mapToEntrypoint.get(src) || src;
|
||||||
|
|
||||||
// Remove the output directory prefix
|
// Remove the output directory prefix
|
||||||
if (config.zeroConfig && config.outputDirectory) {
|
if (config.zeroConfig && config.outputDirectory) {
|
||||||
const outputMatch = 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({
|
matches.push({
|
||||||
...buildConfig,
|
...buildConfig,
|
||||||
src,
|
src,
|
||||||
entrypoint: mapToEntrypoint.get(src) || src,
|
entrypoint,
|
||||||
builderWithPkg,
|
builderWithPkg,
|
||||||
buildOutput: {},
|
buildOutput: {},
|
||||||
buildResults: new Map(),
|
buildResults: new Map(),
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import { parse } from 'url';
|
import { parse } from 'url';
|
||||||
import { ListenSpec } from './types';
|
import { ListenSpec } from './types';
|
||||||
|
|
||||||
export default function parseListen(
|
export function parseListen(str: string, defaultPort = 3000): ListenSpec {
|
||||||
str: string,
|
|
||||||
defaultPort = 3000
|
|
||||||
): ListenSpec {
|
|
||||||
let port = Number(str);
|
let port = Number(str);
|
||||||
|
|
||||||
if (!isNaN(port)) {
|
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 url, { URL } from 'url';
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
@@ -32,6 +31,7 @@ import {
|
|||||||
} from '@vercel/routing-utils';
|
} from '@vercel/routing-utils';
|
||||||
import {
|
import {
|
||||||
Builder,
|
Builder,
|
||||||
|
cloneEnv,
|
||||||
Env,
|
Env,
|
||||||
StartDevServerResult,
|
StartDevServerResult,
|
||||||
FileFsRef,
|
FileFsRef,
|
||||||
@@ -62,11 +62,6 @@ import { devRouter, getRoutesTypes } from './router';
|
|||||||
import getMimeType from './mime-type';
|
import getMimeType from './mime-type';
|
||||||
import { executeBuild, getBuildMatches, shutdownBuilder } from './builder';
|
import { executeBuild, getBuildMatches, shutdownBuilder } from './builder';
|
||||||
import { generateErrorMessage, generateHttpStatusDescription } from './errors';
|
import { generateErrorMessage, generateHttpStatusDescription } from './errors';
|
||||||
import {
|
|
||||||
installBuilders,
|
|
||||||
updateBuilders,
|
|
||||||
builderDirPromise,
|
|
||||||
} from './builder-cache';
|
|
||||||
|
|
||||||
// HTML templates
|
// HTML templates
|
||||||
import errorTemplate from './templates/error';
|
import errorTemplate from './templates/error';
|
||||||
@@ -101,7 +96,9 @@ import {
|
|||||||
isError,
|
isError,
|
||||||
isSpawnError,
|
isSpawnError,
|
||||||
} from '../is-error';
|
} from '../is-error';
|
||||||
|
import isURL from './is-url';
|
||||||
import { pickOverrides } from '../projects/project-settings';
|
import { pickOverrides } from '../projects/project-settings';
|
||||||
|
import { replaceLocalhost } from './parse-listen';
|
||||||
|
|
||||||
const frontendRuntimeSet = new Set(
|
const frontendRuntimeSet = new Set(
|
||||||
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
|
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
|
||||||
@@ -134,9 +131,18 @@ export default class DevServer {
|
|||||||
public proxy: httpProxy;
|
public proxy: httpProxy;
|
||||||
public envConfigs: EnvConfigs;
|
public envConfigs: EnvConfigs;
|
||||||
public files: BuilderInputs;
|
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 currentDevCommand?: string;
|
||||||
private caseSensitive: boolean;
|
private caseSensitive: boolean;
|
||||||
private apiDir: string | null;
|
private apiDir: string | null;
|
||||||
@@ -152,7 +158,7 @@ export default class DevServer {
|
|||||||
private filter: (path: string) => boolean;
|
private filter: (path: string) => boolean;
|
||||||
private podId: string;
|
private podId: string;
|
||||||
private devProcess?: ChildProcess;
|
private devProcess?: ChildProcess;
|
||||||
private devProcessPort?: number;
|
private devProcessOrigin?: string;
|
||||||
private devServerPids: Set<number>;
|
private devServerPids: Set<number>;
|
||||||
private originalProjectSettings?: ProjectSettings;
|
private originalProjectSettings?: ProjectSettings;
|
||||||
private projectSettings?: ProjectSettings;
|
private projectSettings?: ProjectSettings;
|
||||||
@@ -160,8 +166,6 @@ export default class DevServer {
|
|||||||
private vercelConfigWarning: boolean;
|
private vercelConfigWarning: boolean;
|
||||||
private getVercelConfigPromise: Promise<VercelConfig> | null;
|
private getVercelConfigPromise: Promise<VercelConfig> | null;
|
||||||
private blockingBuildsPromise: Promise<void> | null;
|
private blockingBuildsPromise: Promise<void> | null;
|
||||||
private updateBuildersPromise: Promise<void> | null;
|
|
||||||
private updateBuildersTimeout: NodeJS.Timeout | undefined;
|
|
||||||
private startPromise: Promise<void> | null;
|
private startPromise: Promise<void> | null;
|
||||||
|
|
||||||
private systemEnvValues: string[];
|
private systemEnvValues: string[];
|
||||||
@@ -174,17 +178,22 @@ export default class DevServer {
|
|||||||
this.systemEnvValues = options.systemEnvValues || [];
|
this.systemEnvValues = options.systemEnvValues || [];
|
||||||
this.projectEnvs = options.projectEnvs || [];
|
this.projectEnvs = options.projectEnvs || [];
|
||||||
this.files = {};
|
this.files = {};
|
||||||
this.address = '';
|
|
||||||
this.originalProjectSettings = options.projectSettings;
|
this.originalProjectSettings = options.projectSettings;
|
||||||
this.projectSettings = options.projectSettings;
|
this.projectSettings = options.projectSettings;
|
||||||
this.caseSensitive = false;
|
this.caseSensitive = false;
|
||||||
this.apiDir = null;
|
this.apiDir = null;
|
||||||
this.apiExtensions = new Set();
|
this.apiExtensions = new Set();
|
||||||
|
|
||||||
this.proxy = httpProxy.createProxyServer({
|
this.proxy = httpProxy.createProxyServer({
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
ws: true,
|
ws: true,
|
||||||
xfwd: 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 = http.createServer(this.devServerHandler);
|
||||||
this.server.timeout = 0; // Disable timeout
|
this.server.timeout = 0; // Disable timeout
|
||||||
this.stopping = false;
|
this.stopping = false;
|
||||||
@@ -195,7 +204,6 @@ export default class DevServer {
|
|||||||
this.vercelConfigWarning = false;
|
this.vercelConfigWarning = false;
|
||||||
this.getVercelConfigPromise = null;
|
this.getVercelConfigPromise = null;
|
||||||
this.blockingBuildsPromise = null;
|
this.blockingBuildsPromise = null;
|
||||||
this.updateBuildersPromise = null;
|
|
||||||
this.startPromise = null;
|
this.startPromise = null;
|
||||||
|
|
||||||
this.watchAggregationId = 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> {
|
async getLocalEnv(fileName: string, base?: Env): Promise<Env> {
|
||||||
// TODO: use the file watcher to only invalidate the env `dotfile`
|
// TODO: use the file watcher to only invalidate the env `dotfile`
|
||||||
// once a change to the `fileName` occurs
|
// once a change to the `fileName` occurs
|
||||||
@@ -707,7 +688,7 @@ export default class DevServer {
|
|||||||
this.projectEnvs || [],
|
this.projectEnvs || [],
|
||||||
this.systemEnvValues || [],
|
this.systemEnvValues || [],
|
||||||
this.projectSettings?.autoExposeSystemEnvs,
|
this.projectSettings?.autoExposeSystemEnvs,
|
||||||
new URL(this.address).host
|
this.address.host
|
||||||
);
|
);
|
||||||
|
|
||||||
allEnv = { ...cloudEnv };
|
allEnv = { ...cloudEnv };
|
||||||
@@ -842,7 +823,7 @@ export default class DevServer {
|
|||||||
injectSystemValuesInDotenv(env: Env): Env {
|
injectSystemValuesInDotenv(env: Env): Env {
|
||||||
for (const name of Object.keys(env)) {
|
for (const name of Object.keys(env)) {
|
||||||
if (name === 'VERCEL_URL') {
|
if (name === 'VERCEL_URL') {
|
||||||
env['VERCEL_URL'] = new URL(this.address).host;
|
env['VERCEL_URL'] = this.address.host;
|
||||||
} else if (name === 'VERCEL_REGION') {
|
} else if (name === 'VERCEL_REGION') {
|
||||||
env['VERCEL_REGION'] = 'dev1';
|
env['VERCEL_REGION'] = 'dev1';
|
||||||
}
|
}
|
||||||
@@ -915,9 +896,7 @@ export default class DevServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.address = address
|
this._address = new URL(replaceLocalhost(address));
|
||||||
.replace('[::]', 'localhost')
|
|
||||||
.replace('127.0.0.1', 'localhost');
|
|
||||||
|
|
||||||
const vercelConfig = await this.getVercelConfig();
|
const vercelConfig = await this.getVercelConfig();
|
||||||
const devCommandPromise = this.runDevCommand();
|
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);
|
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
|
// 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
|
// executed at boot-up time in order to get the initial assets and/or routes
|
||||||
// that can be served by the builder.
|
// 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.
|
// Configure the server to forward WebSocket "upgrade" events to the proxy.
|
||||||
this.server.on('upgrade', async (req, socket, head) => {
|
this.server.on('upgrade', async (req, socket, head) => {
|
||||||
await this.startPromise;
|
await this.startPromise;
|
||||||
if (!this.devProcessPort) {
|
if (!this.devProcessOrigin) {
|
||||||
this.output.debug(
|
this.output.debug(
|
||||||
`Detected "upgrade" event, but closing socket because no frontend dev server is running`
|
`Detected "upgrade" event, but closing socket because no frontend dev server is running`
|
||||||
);
|
);
|
||||||
socket.destroy();
|
socket.destroy();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const target = `http://127.0.0.1:${this.devProcessPort}`;
|
const target = this.devProcessOrigin;
|
||||||
this.output.debug(`Detected "upgrade" event, proxying to ${target}`);
|
this.output.debug(`Detected "upgrade" event, proxying to ${target}`);
|
||||||
this.proxy.ws(req, socket, head, { target });
|
this.proxy.ws(req, socket, head, { target });
|
||||||
});
|
});
|
||||||
|
|
||||||
await devCommandPromise;
|
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.
|
* Shuts down the `vercel dev` server, and cleans up any temporary resources.
|
||||||
*/
|
*/
|
||||||
async stop(exitCode?: number): Promise<void> {
|
async stop(exitCode?: number): Promise<void> {
|
||||||
const { devProcess } = this;
|
|
||||||
const { debug } = this.output;
|
|
||||||
if (this.stopping) return;
|
if (this.stopping) return;
|
||||||
|
|
||||||
this.stopping = true;
|
this.stopping = true;
|
||||||
|
|
||||||
if (typeof this.updateBuildersTimeout !== 'undefined') {
|
const { devProcess } = this;
|
||||||
clearTimeout(this.updateBuildersTimeout);
|
const { debug } = this.output;
|
||||||
}
|
|
||||||
|
|
||||||
const ops: Promise<any>[] = [];
|
const ops: Promise<any>[] = [];
|
||||||
|
|
||||||
for (const match of this.buildMatches.values()) {
|
for (const match of this.buildMatches.values()) {
|
||||||
@@ -1055,18 +1012,10 @@ export default class DevServer {
|
|||||||
ops.push(this.watcher.close());
|
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) {
|
for (const pid of this.devServerPids) {
|
||||||
ops.push(this.killBuilderDevServer(pid));
|
ops.push(this.killBuilderDevServer(pid));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the builders module cache is created
|
|
||||||
ops.push(builderDirPromise);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.all(ops);
|
await Promise.all(ops);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
@@ -1465,8 +1414,9 @@ export default class DevServer {
|
|||||||
// the middleware server for every HTTP request?
|
// the middleware server for every HTTP request?
|
||||||
const { envConfigs, files, devCacheDir, cwd: workPath } = this;
|
const { envConfigs, files, devCacheDir, cwd: workPath } = this;
|
||||||
try {
|
try {
|
||||||
startMiddlewareResult =
|
const { builder } = middleware.builderWithPkg;
|
||||||
await middleware.builderWithPkg.builder.startDevServer?.({
|
if (builder.version === 3) {
|
||||||
|
startMiddlewareResult = await builder.startDevServer?.({
|
||||||
files,
|
files,
|
||||||
entrypoint: middleware.entrypoint,
|
entrypoint: middleware.entrypoint,
|
||||||
workPath,
|
workPath,
|
||||||
@@ -1480,6 +1430,7 @@ export default class DevServer {
|
|||||||
buildEnv: { ...envConfigs.buildEnv },
|
buildEnv: { ...envConfigs.buildEnv },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (startMiddlewareResult) {
|
if (startMiddlewareResult) {
|
||||||
const { port, pid } = startMiddlewareResult;
|
const { port, pid } = startMiddlewareResult;
|
||||||
@@ -1560,15 +1511,34 @@ export default class DevServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rewritePath) {
|
if (rewritePath) {
|
||||||
// TODO: add validation?
|
|
||||||
debug(`Detected rewrite path from middleware: "${rewritePath}"`);
|
debug(`Detected rewrite path from middleware: "${rewritePath}"`);
|
||||||
prevUrl = rewritePath;
|
prevUrl = rewritePath;
|
||||||
|
|
||||||
// Retain orginal pathname, but override query parameters from the rewrite
|
|
||||||
const beforeRewriteUrl = req.url || '/';
|
const beforeRewriteUrl = req.url || '/';
|
||||||
const rewriteUrlParsed = url.parse(beforeRewriteUrl);
|
|
||||||
rewriteUrlParsed.search = url.parse(rewritePath).search;
|
if (isURL(rewritePath)) {
|
||||||
req.url = url.format(rewriteUrlParsed);
|
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(
|
debug(
|
||||||
`Rewrote incoming HTTP URL from "${beforeRewriteUrl}" to "${req.url}"`
|
`Rewrote incoming HTTP URL from "${beforeRewriteUrl}" to "${req.url}"`
|
||||||
);
|
);
|
||||||
@@ -1617,12 +1587,16 @@ export default class DevServer {
|
|||||||
missRoutes,
|
missRoutes,
|
||||||
phase
|
phase
|
||||||
);
|
);
|
||||||
prevUrl =
|
|
||||||
routeResult.continue && routeResult.dest
|
if (routeResult.continue) {
|
||||||
? getReqUrl(routeResult)
|
if (routeResult.dest) {
|
||||||
: req.url;
|
prevUrl = getReqUrl(routeResult);
|
||||||
prevHeaders =
|
}
|
||||||
routeResult.continue && routeResult.headers ? routeResult.headers : {};
|
|
||||||
|
if (routeResult.headers) {
|
||||||
|
prevHeaders = routeResult.headers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (routeResult.isDestUrl) {
|
if (routeResult.isDestUrl) {
|
||||||
// Mix the `routes` result dest query params into the req path
|
// Mix the `routes` result dest query params into the req path
|
||||||
@@ -1795,8 +1769,8 @@ export default class DevServer {
|
|||||||
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
// If the dev command is started, then proxy to it
|
// If the dev command is started, then proxy to it
|
||||||
if (this.devProcessPort) {
|
if (this.devProcessOrigin) {
|
||||||
const upstream = `http://127.0.0.1:${this.devProcessPort}`;
|
const upstream = this.devProcessOrigin;
|
||||||
debug(`Proxying to frontend dev server: ${upstream}`);
|
debug(`Proxying to frontend dev server: ${upstream}`);
|
||||||
|
|
||||||
// Add the Vercel platform proxy request headers
|
// 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
|
// 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
|
// to. Once the proxied request is finished, vercel dev shuts down the dev
|
||||||
// server child process.
|
// server child process.
|
||||||
const { builder, package: builderPkg } = match.builderWithPkg;
|
const { builder, pkg: builderPkg } = match.builderWithPkg;
|
||||||
if (typeof builder.startDevServer === 'function') {
|
if (builder.version === 3 && typeof builder.startDevServer === 'function') {
|
||||||
let devServerResult: StartDevServerResult = null;
|
let devServerResult: StartDevServerResult = null;
|
||||||
try {
|
try {
|
||||||
const { envConfigs, files, devCacheDir, cwd: workPath } = this;
|
const { envConfigs, files, devCacheDir, cwd: workPath } = this;
|
||||||
@@ -1975,7 +1949,7 @@ export default class DevServer {
|
|||||||
// - when there is no asset
|
// - when there is no asset
|
||||||
// - when the asset is not a Lambda (the dev server must take care of all static files)
|
// - when the asset is not a Lambda (the dev server must take care of all static files)
|
||||||
if (
|
if (
|
||||||
this.devProcessPort &&
|
this.devProcessOrigin &&
|
||||||
(!foundAsset || (foundAsset && foundAsset.asset.type !== 'Lambda'))
|
(!foundAsset || (foundAsset && foundAsset.asset.type !== 'Lambda'))
|
||||||
) {
|
) {
|
||||||
debug('Proxying to frontend dev server');
|
debug('Proxying to frontend dev server');
|
||||||
@@ -1987,14 +1961,7 @@ export default class DevServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.setResponseHeaders(res, requestId);
|
this.setResponseHeaders(res, requestId);
|
||||||
return proxyPass(
|
return proxyPass(req, res, this.devProcessOrigin, this, requestId, false);
|
||||||
req,
|
|
||||||
res,
|
|
||||||
`http://127.0.0.1:${this.devProcessPort}`,
|
|
||||||
this,
|
|
||||||
requestId,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!foundAsset) {
|
if (!foundAsset) {
|
||||||
@@ -2256,18 +2223,22 @@ export default class DevServer {
|
|||||||
|
|
||||||
const port = await getPort();
|
const port = await getPort();
|
||||||
|
|
||||||
const env: Env = {
|
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.
|
// Because of child process 'pipe' below, isTTY will be false.
|
||||||
FORCE_COLOR: process.stdout.isTTY ? '1' : '0',
|
// Most frameworks use `chalk`/`supports-color` so we enable it anyway.
|
||||||
// Prevent framework dev servers from automatically opening a web
|
FORCE_COLOR: process.stdout.isTTY ? '1' : '0',
|
||||||
// browser window, since it will not be the port that `vc dev`
|
// Prevent framework dev servers from automatically opening a web
|
||||||
// is listening on and thus will be missing Vercel features.
|
// browser window, since it will not be the port that `vc dev`
|
||||||
BROWSER: 'none',
|
// is listening on and thus will be missing Vercel features.
|
||||||
...process.env,
|
BROWSER: 'none',
|
||||||
...this.envConfigs.allEnv,
|
},
|
||||||
PORT: `${port}`,
|
process.env,
|
||||||
};
|
this.envConfigs.allEnv,
|
||||||
|
{
|
||||||
|
PORT: `${port}`,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// This is necesary so that the dev command in the Project
|
// This is necesary so that the dev command in the Project
|
||||||
// will work cross-platform (especially Windows).
|
// will work cross-platform (especially Windows).
|
||||||
@@ -2301,7 +2272,6 @@ export default class DevServer {
|
|||||||
|
|
||||||
this.output.debug(`Spawning dev command: ${command}`);
|
this.output.debug(`Spawning dev command: ${command}`);
|
||||||
|
|
||||||
const devPort = new URL(this.address).port;
|
|
||||||
const proxyPort = new RegExp(port.toString(), 'g');
|
const proxyPort = new RegExp(port.toString(), 'g');
|
||||||
const p = spawnCommand(command, {
|
const p = spawnCommand(command, {
|
||||||
stdio: ['inherit', 'pipe', 'pipe'],
|
stdio: ['inherit', 'pipe', 'pipe'],
|
||||||
@@ -2318,17 +2288,16 @@ export default class DevServer {
|
|||||||
p.stdout.setEncoding('utf8');
|
p.stdout.setEncoding('utf8');
|
||||||
|
|
||||||
p.stdout.on('data', (data: string) => {
|
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) => {
|
p.on('exit', (code, signal) => {
|
||||||
this.output.debug(`Dev command exited with "${signal || code}"`);
|
this.output.debug(`Dev command exited with "${signal || code}"`);
|
||||||
this.devProcessPort = undefined;
|
this.devProcessOrigin = undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
await checkForPort(port, 1000 * 60 * 5);
|
const devProcessHost = await checkForPort(port, 1000 * 60 * 5);
|
||||||
|
this.devProcessOrigin = `http://${devProcessHost}:${port}`;
|
||||||
this.devProcessPort = port;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2616,15 +2585,29 @@ function needsBlockingBuild(buildMatch: BuildMatch): boolean {
|
|||||||
return typeof builder.shouldServe !== 'function';
|
return typeof builder.shouldServe !== 'function';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkForPort(port: number, timeout: number): Promise<void> {
|
async function checkForPort(port: number, timeout: number): Promise<string> {
|
||||||
const opts = { host: '127.0.0.1' };
|
let host;
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
while (!(await isPortReachable(port, opts))) {
|
while (!(host = await getReachableHostOnPort(port))) {
|
||||||
if (Date.now() - start > timeout) {
|
if (Date.now() - start > timeout) {
|
||||||
throw new Error(`Detecting port ${port} timed out after ${timeout}ms`);
|
break;
|
||||||
}
|
}
|
||||||
await sleep(100);
|
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) {
|
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,
|
FileBlob,
|
||||||
FileFsRef,
|
FileFsRef,
|
||||||
Lambda,
|
Lambda,
|
||||||
PackageJson,
|
|
||||||
} from '@vercel/build-utils';
|
} from '@vercel/build-utils';
|
||||||
import { VercelConfig } from '@vercel/client';
|
import { VercelConfig } from '@vercel/client';
|
||||||
import { HandleValue, Route } from '@vercel/routing-utils';
|
import { HandleValue, Route } from '@vercel/routing-utils';
|
||||||
import { Output } from '../output';
|
import { Output } from '../output';
|
||||||
import { ProjectEnvVariable, ProjectSettings } from '../../types';
|
import { ProjectEnvVariable, ProjectSettings } from '../../types';
|
||||||
|
import { BuilderWithPkg } from '../build/import-builders';
|
||||||
|
|
||||||
export { VercelConfig };
|
export { VercelConfig };
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ export interface EnvConfigs {
|
|||||||
export interface BuildMatch extends BuildConfig {
|
export interface BuildMatch extends BuildConfig {
|
||||||
entrypoint: string;
|
entrypoint: string;
|
||||||
src: string;
|
src: string;
|
||||||
builderWithPkg: BuilderWithPackage;
|
builderWithPkg: BuilderWithPkg;
|
||||||
buildOutput: BuilderOutputs;
|
buildOutput: BuilderOutputs;
|
||||||
buildResults: Map<string | null, BuildResult>;
|
buildResults: Map<string | null, BuildResult>;
|
||||||
buildTimestamp: number;
|
buildTimestamp: number;
|
||||||
@@ -122,13 +122,6 @@ export interface BuildResultV4 {
|
|||||||
distPath?: string;
|
distPath?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BuilderWithPackage {
|
|
||||||
runInProcess?: boolean;
|
|
||||||
requirePath: string;
|
|
||||||
builder: Readonly<Builder>;
|
|
||||||
package: Readonly<PackageJson>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HttpHeadersConfig {
|
export interface HttpHeadersConfig {
|
||||||
[name: string]: string;
|
[name: string]: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,16 @@ export async function writeProjectSettings(
|
|||||||
project: Project,
|
project: Project,
|
||||||
org: Org
|
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 = {
|
const projectLinkAndSettings: ProjectLinkAndSettings = {
|
||||||
projectId: project.id,
|
projectId: project.id,
|
||||||
orgId: org.id,
|
orgId: org.id,
|
||||||
@@ -41,7 +51,7 @@ export async function writeProjectSettings(
|
|||||||
rootDirectory: project.rootDirectory,
|
rootDirectory: project.rootDirectory,
|
||||||
directoryListing: project.directoryListing,
|
directoryListing: project.directoryListing,
|
||||||
nodeVersion: project.nodeVersion,
|
nodeVersion: project.nodeVersion,
|
||||||
analyticsId: project.analytics?.id,
|
analyticsId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const path = join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT);
|
const path = join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT);
|
||||||
|
|||||||
@@ -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 => {
|
export default req => {
|
||||||
const url = new URL(req.url);
|
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 === '/') {
|
if (url.pathname === '/') {
|
||||||
// Pass-through "index.html" page
|
// Pass-through "index.html" page
|
||||||
return new Response(null, {
|
return new Response(null, {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --port $PORT",
|
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"serve": "vite preview"
|
"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 fs from 'fs-extra';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import listen from 'async-listen';
|
import listen from 'async-listen';
|
||||||
|
import stripAnsi from 'strip-ansi';
|
||||||
import { createServer } from 'http';
|
import { createServer } from 'http';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -85,6 +86,7 @@ test(
|
|||||||
testFixtureStdio('edge-function', async (testPath: any) => {
|
testFixtureStdio('edge-function', async (testPath: any) => {
|
||||||
await testPath(500, '/api/edge-500-response');
|
await testPath(500, '/api/edge-500-response');
|
||||||
await testPath(200, '/api/edge-success');
|
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 () => {
|
test('[vercel dev] prints `npm install` errors', async () => {
|
||||||
const dir = fixture('runtime-not-installed');
|
const dir = fixture('runtime-not-installed');
|
||||||
const result = await exec(dir);
|
const result = await exec(dir);
|
||||||
expect(result.stderr.includes('npm ERR! 404')).toBeTruthy();
|
|
||||||
expect(
|
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();
|
).toBeTruthy();
|
||||||
expect(
|
expect(
|
||||||
result.stderr.includes('https://vercel.link/npm-install-failed-dev')
|
result.stderr.includes(
|
||||||
|
'https://vercel.link/builder-dependencies-install-failed'
|
||||||
|
)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -445,11 +445,7 @@ test(
|
|||||||
test(
|
test(
|
||||||
'[vercel dev] Middleware that has no response',
|
'[vercel dev] Middleware that has no response',
|
||||||
testFixtureStdio('middleware-no-response', async (testPath: any) => {
|
testFixtureStdio('middleware-no-response', async (testPath: any) => {
|
||||||
await testPath(
|
await testPath(200, '/api/hello', 'hello from a serverless function');
|
||||||
500,
|
|
||||||
'/api/hello',
|
|
||||||
'A server error has occurred\n\nEDGE_FUNCTION_INVOCATION_FAILED'
|
|
||||||
);
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -461,9 +457,42 @@ test(
|
|||||||
await testPath(200, '/another', '<h1>Another</h1>');
|
await testPath(200, '/another', '<h1>Another</h1>');
|
||||||
await testPath(200, '/another.html', '<h1>Another</h1>');
|
await testPath(200, '/another.html', '<h1>Another</h1>');
|
||||||
await testPath(200, '/foo', '<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(
|
test(
|
||||||
'[vercel dev] Middleware that rewrites with custom query params',
|
'[vercel dev] Middleware that rewrites with custom query params',
|
||||||
testFixtureStdio('middleware-rewrite-query', async (testPath: any) => {
|
testFixtureStdio('middleware-rewrite-query', async (testPath: any) => {
|
||||||
@@ -481,6 +510,14 @@ test(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'[vercel dev] Middleware that rewrites to 404s',
|
||||||
|
testFixtureStdio('middleware-rewrite-404', async (testPath: any) => {
|
||||||
|
await testPath(404, '/api/edge', /NOT_FOUND/);
|
||||||
|
await testPath(404, '/index.html', /NOT_FOUND/);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'[vercel dev] Middleware that redirects',
|
'[vercel dev] Middleware that redirects',
|
||||||
testFixtureStdio('middleware-redirect', async (testPath: any) => {
|
testFixtureStdio('middleware-redirect', async (testPath: any) => {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const {
|
|||||||
|
|
||||||
jest.setTimeout(6 * 60 * 1000);
|
jest.setTimeout(6 * 60 * 1000);
|
||||||
|
|
||||||
|
const isCI = !!process.env.CI;
|
||||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||||
const isCanary = () => getDistTag(cliVersion) === 'canary';
|
const isCanary = () => getDistTag(cliVersion) === 'canary';
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ function fetchWithRetry(url, opts = {}) {
|
|||||||
return res;
|
return res;
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
retries: opts.retries || 3,
|
retries: opts.retries ?? 3,
|
||||||
factor: 1,
|
factor: 1,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -150,9 +151,9 @@ async function testPath(
|
|||||||
fetchOpts = {}
|
fetchOpts = {}
|
||||||
) {
|
) {
|
||||||
const opts = {
|
const opts = {
|
||||||
|
retries: isCI ? 5 : 0,
|
||||||
...fetchOpts,
|
...fetchOpts,
|
||||||
redirect: 'manual-dont-change',
|
redirect: 'manual-dont-change',
|
||||||
retries: 5,
|
|
||||||
status,
|
status,
|
||||||
};
|
};
|
||||||
const url = `${origin}${path}`;
|
const url = `${origin}${path}`;
|
||||||
@@ -330,7 +331,7 @@ function testFixtureStdio(
|
|||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify(projectSettings),
|
body: JSON.stringify(projectSettings),
|
||||||
retries: 3,
|
retries: isCI ? 3 : 0,
|
||||||
status: 200,
|
status: 200,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
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/webp", "image/avif"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -69,7 +69,7 @@ export function useDeploymentMissingProjectSettings() {
|
|||||||
framework: {
|
framework: {
|
||||||
name: 'Other',
|
name: 'Other',
|
||||||
slug: null,
|
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.',
|
description: 'No framework or an unoptimized framework.',
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
|
|||||||
@@ -895,6 +895,12 @@ describe('build', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should apply project settings overrides from "vercel.json"', async () => {
|
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 cwd = fixture('project-settings-override');
|
||||||
const output = join(cwd, '.vercel/output');
|
const output = join(cwd, '.vercel/output');
|
||||||
try {
|
try {
|
||||||
@@ -914,6 +920,30 @@ describe('build', () => {
|
|||||||
delete process.env.__VERCEL_BUILD_RUNNING;
|
delete process.env.__VERCEL_BUILD_RUNNING;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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/webp', 'image/avif'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
process.chdir(originalCwd);
|
||||||
|
delete process.env.__VERCEL_BUILD_RUNNING;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
describe('should find packages with different main/module/browser keys', function () {
|
describe('should find packages with different main/module/browser keys', function () {
|
||||||
let output: string;
|
let output: string;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import vercelNodePkg from '@vercel/node/package.json';
|
|||||||
|
|
||||||
jest.setTimeout(ms('30 seconds'));
|
jest.setTimeout(ms('30 seconds'));
|
||||||
|
|
||||||
|
const repoRoot = join(__dirname, '../../../../../..');
|
||||||
|
|
||||||
describe('importBuilders()', () => {
|
describe('importBuilders()', () => {
|
||||||
it('should import built-in Builders', async () => {
|
it('should import built-in Builders', async () => {
|
||||||
const specs = new Set(['@vercel/node', '@vercel/next']);
|
const specs = new Set(['@vercel/node', '@vercel/next']);
|
||||||
@@ -19,6 +21,12 @@ describe('importBuilders()', () => {
|
|||||||
expect(builders.size).toEqual(2);
|
expect(builders.size).toEqual(2);
|
||||||
expect(builders.get('@vercel/node')?.pkg).toMatchObject(vercelNodePkg);
|
expect(builders.get('@vercel/node')?.pkg).toMatchObject(vercelNodePkg);
|
||||||
expect(builders.get('@vercel/next')?.pkg).toMatchObject(vercelNextPkg);
|
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(
|
expect(typeof builders.get('@vercel/node')?.builder.build).toEqual(
|
||||||
'function'
|
'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();
|
const cwd = await getWriteableDirectory();
|
||||||
try {
|
try {
|
||||||
const spec = 'vercel-deno@2.0.1';
|
const spec = '@vercel/node@2.0.0';
|
||||||
const specs = new Set([spec]);
|
const specs = new Set([spec]);
|
||||||
const builders = await importBuilders(specs, cwd, client.output);
|
const builders = await importBuilders(specs, cwd, client.output);
|
||||||
expect(builders.size).toEqual(1);
|
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.name).toEqual('vercel-deno');
|
||||||
expect(builders.get(spec)?.pkg.version).toEqual('2.0.1');
|
expect(builders.get(spec)?.pkg.version).toEqual('2.0.1');
|
||||||
expect(builders.get(spec)?.pkgPath).toEqual(
|
expect(builders.get(spec)?.pkgPath).toEqual(
|
||||||
join(cwd, '.vercel/builders/node_modules/vercel-deno/package.json')
|
join(cwd, '.vercel/builders/node_modules/vercel-deno/package.json')
|
||||||
);
|
);
|
||||||
expect(typeof builders.get(spec)?.builder.build).toEqual('function');
|
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 {
|
} finally {
|
||||||
await remove(cwd);
|
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();
|
const cwd = await getWriteableDirectory();
|
||||||
try {
|
try {
|
||||||
const spec = '@frontity/now@1.2.0';
|
const spec = '@frontity/now@1.2.0';
|
||||||
@@ -62,6 +169,31 @@ describe('importBuilders()', () => {
|
|||||||
await remove(cwd);
|
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()', () => {
|
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';
|
const IS_WINDOWS = process.platform === 'win32';
|
||||||
|
|
||||||
@@ -69,3 +72,15 @@ describe('parseListen', () => {
|
|||||||
expect(err.message).toEqual('Unknown `--listen` scheme (protocol): bad:');
|
expect(err.message).toEqual('Unknown `--listen` scheme (protocol): bad:');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('replaceLocalhost', () => {
|
||||||
|
test.each([
|
||||||
|
{ input: 'http://192.168.0.1:1234', output: 'http://192.168.0.1:1234' },
|
||||||
|
{ input: 'http://127.0.0.1:4000', output: 'http://127.0.0.1:4000' },
|
||||||
|
{ input: 'http://[::1]:3001', output: 'http://[::1]:3001' },
|
||||||
|
{ input: 'http://0.0.0.0:3000', output: 'http://localhost:3000' },
|
||||||
|
{ input: 'http://[::]:3002', output: 'http://localhost:3002' },
|
||||||
|
])('"$input" → "$output"', ({ input, output }) => {
|
||||||
|
expect(replaceLocalhost(input)).toEqual(output);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/client",
|
"name": "@vercel/client",
|
||||||
"version": "12.2.3",
|
"version": "12.2.7",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist/index.d.ts",
|
||||||
"homepage": "https://vercel.com",
|
"homepage": "https://vercel.com",
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/build-utils": "5.4.1",
|
"@vercel/build-utils": "5.5.0",
|
||||||
"@vercel/routing-utils": "2.0.2",
|
"@vercel/routing-utils": "2.0.2",
|
||||||
"@zeit/fetch": "5.2.0",
|
"@zeit/fetch": "5.2.0",
|
||||||
"async-retry": "1.2.3",
|
"async-retry": "1.2.3",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type {
|
import type {
|
||||||
Builder,
|
Builder,
|
||||||
BuilderFunctions,
|
BuilderFunctions,
|
||||||
|
Images,
|
||||||
ProjectSettings,
|
ProjectSettings,
|
||||||
} from '@vercel/build-utils';
|
} from '@vercel/build-utils';
|
||||||
import type { Header, Route, Redirect, Rewrite } from '@vercel/routing-utils';
|
import type { Header, Route, Redirect, Rewrite } from '@vercel/routing-utils';
|
||||||
@@ -152,6 +153,7 @@ export interface VercelConfig {
|
|||||||
installCommand?: string | null;
|
installCommand?: string | null;
|
||||||
framework?: string | null;
|
framework?: string | null;
|
||||||
outputDirectory?: string | null;
|
outputDirectory?: string | null;
|
||||||
|
images?: Images;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GitMetadata {
|
export interface GitMetadata {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22.428.013c-.103.01-.431.042-.727.066C14.883.693 8.497 4.37 4.453 10.024A23.754 23.754 0 0 0 .216 20.51C.023 21.828 0 22.217 0 24.005c0 1.787.023 2.177.216 3.495 1.304 9.012 7.718 16.584 16.417 19.39 1.558.501 3.2.844 5.068 1.05.727.08 3.87.08 4.598 0 3.224-.356 5.954-1.154 8.648-2.529.412-.21.492-.267.436-.314-.038-.028-1.797-2.388-3.909-5.24l-3.838-5.184-4.809-7.117c-2.646-3.913-4.824-7.112-4.842-7.112-.019-.005-.038 3.157-.047 7.018-.014 6.76-.019 7.033-.103 7.192-.122.23-.216.324-.413.427-.15.075-.282.09-.99.09h-.812l-.216-.137a.878.878 0 0 1-.314-.342l-.099-.211.01-9.407.014-9.41.145-.184c.075-.098.235-.225.347-.286.193-.094.268-.103 1.08-.103.957 0 1.116.038 1.365.31.07.075 2.674 3.997 5.79 8.721s7.376 11.175 9.469 14.342l3.8 5.756.192-.127c1.704-1.107 3.505-2.683 4.932-4.325a23.888 23.888 0 0 0 5.65-12.268c.192-1.319.215-1.708.215-3.495 0-1.788-.023-2.177-.216-3.495-1.304-9.013-7.718-16.584-16.417-19.39C29.832.623 28.199.28 26.369.074c-.45-.047-3.551-.099-3.94-.061zm9.825 14.515a.947.947 0 0 1 .474.554c.038.122.047 2.73.038 8.608l-.014 8.436-1.488-2.28-1.492-2.28v-6.132c0-3.964.019-6.193.047-6.3a.957.957 0 0 1 .465-.592c.192-.098.262-.108 1-.108.694 0 .816.01.97.094z" fill="#fff"/></svg>
|
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="mask" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="48" height="48"><circle cx="24" cy="24" r="24" fill="#000"/></mask><g mask="url(#mask)"><circle cx="24" cy="24" r="23.2" fill="#000" stroke="#fff" stroke-width="1.6"/><path d="M39.8687 42.0055L18.4378 14.4H14.3999V33.592H17.6302V18.5023L37.333 43.9587C38.222 43.3637 39.069 42.7108 39.8687 42.0055Z" fill="url(#gradient0)"/><rect x="30.6667" y="14.4" width="3.2" height="19.2" fill="url(#gradient1)"/></g><defs><linearGradient id="gradient0" x1="29.0666" y1="31.0667" x2="38.5332" y2="42.8" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="gradient1" x1="32.2667" y1="14.4" x2="32.2132" y2="28.5001" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient></defs></svg>
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 997 B |
@@ -1 +1 @@
|
|||||||
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M22.428.013c-.103.01-.431.042-.727.066C14.883.693 8.497 4.37 4.453 10.024A23.754 23.754 0 0 0 .216 20.51C.023 21.828 0 22.217 0 24.005c0 1.787.023 2.177.216 3.495 1.304 9.012 7.718 16.584 16.417 19.39 1.558.501 3.2.844 5.068 1.05.727.08 3.87.08 4.598 0 3.224-.356 5.954-1.154 8.648-2.529.412-.21.492-.267.436-.314-.038-.028-1.797-2.388-3.909-5.24l-3.838-5.184-4.809-7.117c-2.646-3.913-4.824-7.112-4.842-7.112-.019-.005-.038 3.157-.047 7.018-.014 6.76-.019 7.033-.103 7.192-.122.23-.216.324-.413.427-.15.075-.282.09-.99.09h-.812l-.216-.137a.878.878 0 0 1-.314-.342l-.099-.211.01-9.407.014-9.41.145-.184c.075-.098.235-.225.347-.286.193-.094.268-.103 1.08-.103.957 0 1.116.038 1.365.31.07.075 2.674 3.997 5.79 8.721s7.376 11.175 9.469 14.342l3.8 5.756.192-.127c1.704-1.107 3.505-2.683 4.932-4.325a23.888 23.888 0 0 0 5.65-12.268c.192-1.319.215-1.708.215-3.495 0-1.788-.023-2.177-.216-3.495-1.304-9.013-7.718-16.584-16.417-19.39C29.832.623 28.199.28 26.369.074c-.45-.047-3.551-.099-3.94-.061zm9.825 14.515a.947.947 0 0 1 .474.554c.038.122.047 2.73.038 8.608l-.014 8.436-1.488-2.28-1.492-2.28v-6.132c0-3.964.019-6.193.047-6.3a.957.957 0 0 1 .465-.592c.192-.098.262-.108 1-.108.694 0 .816.01.97.094z" fill="#000"/></svg>
|
<svg width="48" height="48" fill="none" xmlns="http://www.w3.org/2000/svg"><mask id="mask" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="48" height="48"><circle cx="24" cy="24" r="24" fill="#000"/></mask><g mask="url(#mask)"><circle cx="24" cy="24" r="23.2" fill="#000" stroke="#000" stroke-width="1.6"/><path d="M39.8687 42.0055L18.4378 14.4H14.3999V33.592H17.6302V18.5023L37.333 43.9587C38.222 43.3637 39.069 42.7108 39.8687 42.0055Z" fill="url(#gradient0)"/><rect x="30.6667" y="14.4" width="3.2" height="19.2" fill="url(#gradient1)"/></g><defs><linearGradient id="gradient0" x1="29.0666" y1="31.0667" x2="38.5332" y2="42.8" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="gradient1" x1="32.2667" y1="14.4" x2="32.2132" y2="28.5001" gradientUnits="userSpaceOnUse"><stop stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient></defs></svg>
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 997 B |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/frameworks",
|
"name": "@vercel/frameworks",
|
||||||
"version": "1.1.3",
|
"version": "1.1.6",
|
||||||
"main": "./dist/frameworks.js",
|
"main": "./dist/frameworks.js",
|
||||||
"types": "./dist/frameworks.d.ts",
|
"types": "./dist/frameworks.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export const frameworks = [
|
|||||||
name: 'Blitz.js',
|
name: 'Blitz.js',
|
||||||
slug: 'blitzjs',
|
slug: 'blitzjs',
|
||||||
demo: 'https://blitz-template.vercel.app',
|
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',
|
tagline: 'Blitz.js: The Fullstack React Framework',
|
||||||
description:
|
description:
|
||||||
'A brand new Blitz.js app - the result of running `npx blitz new`.',
|
'A brand new Blitz.js app - the result of running `npx blitz new`.',
|
||||||
@@ -58,9 +58,9 @@ export const frameworks = [
|
|||||||
name: 'Next.js',
|
name: 'Next.js',
|
||||||
slug: 'nextjs',
|
slug: 'nextjs',
|
||||||
demo: 'https://nextjs-template.vercel.app',
|
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:
|
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:
|
screenshot:
|
||||||
'https://assets.vercel.com/image/upload/v1647366075/front/import/nextjs.png',
|
'https://assets.vercel.com/image/upload/v1647366075/front/import/nextjs.png',
|
||||||
tagline:
|
tagline:
|
||||||
@@ -108,7 +108,7 @@ export const frameworks = [
|
|||||||
name: 'Gatsby.js',
|
name: 'Gatsby.js',
|
||||||
slug: 'gatsby',
|
slug: 'gatsby',
|
||||||
demo: 'https://gatsby.vercel.app',
|
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:
|
tagline:
|
||||||
'Gatsby helps developers build blazing fast websites and apps with React.',
|
'Gatsby helps developers build blazing fast websites and apps with React.',
|
||||||
description: 'A Gatsby starter app with an API Route.',
|
description: 'A Gatsby starter app with an API Route.',
|
||||||
@@ -195,7 +195,7 @@ export const frameworks = [
|
|||||||
name: 'Remix',
|
name: 'Remix',
|
||||||
slug: 'remix',
|
slug: 'remix',
|
||||||
demo: 'https://remix-run-template.vercel.app',
|
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',
|
tagline: 'Build Better Websites',
|
||||||
description: 'A new Remix app — the result of running `npx create-remix`.',
|
description: 'A new Remix app — the result of running `npx create-remix`.',
|
||||||
website: 'https://remix.run',
|
website: 'https://remix.run',
|
||||||
@@ -232,9 +232,9 @@ export const frameworks = [
|
|||||||
name: 'Astro',
|
name: 'Astro',
|
||||||
slug: 'astro',
|
slug: 'astro',
|
||||||
demo: 'https://astro-template.vercel.app',
|
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:
|
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:
|
tagline:
|
||||||
'Astro is a new kind of static site builder for the modern web. Powerful developer experience meets lightweight output.',
|
'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.',
|
description: 'An Astro site, using the basics starter kit.',
|
||||||
@@ -286,7 +286,7 @@ export const frameworks = [
|
|||||||
name: 'Hexo',
|
name: 'Hexo',
|
||||||
slug: 'hexo',
|
slug: 'hexo',
|
||||||
demo: 'https://hexo-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Hexo is a fast, simple & powerful blog framework powered by Node.js.',
|
'Hexo is a fast, simple & powerful blog framework powered by Node.js.',
|
||||||
description: 'A Hexo site, created with the Hexo CLI.',
|
description: 'A Hexo site, created with the Hexo CLI.',
|
||||||
@@ -323,7 +323,7 @@ export const frameworks = [
|
|||||||
name: 'Eleventy',
|
name: 'Eleventy',
|
||||||
slug: 'eleventy',
|
slug: 'eleventy',
|
||||||
demo: 'https://eleventy-template.vercel.app',
|
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:
|
tagline:
|
||||||
'11ty is a simpler static site generator written in JavaScript, created to be an alternative to Jekyll.',
|
'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.',
|
description: 'An Eleventy site, created with npm init.',
|
||||||
@@ -361,7 +361,7 @@ export const frameworks = [
|
|||||||
name: 'Docusaurus 2',
|
name: 'Docusaurus 2',
|
||||||
slug: 'docusaurus-2',
|
slug: 'docusaurus-2',
|
||||||
demo: 'https://docusaurus-2-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Docusaurus makes it easy to maintain Open Source documentation websites.',
|
'Docusaurus makes it easy to maintain Open Source documentation websites.',
|
||||||
description:
|
description:
|
||||||
@@ -449,7 +449,7 @@ export const frameworks = [
|
|||||||
name: 'Docusaurus 1',
|
name: 'Docusaurus 1',
|
||||||
slug: 'docusaurus',
|
slug: 'docusaurus',
|
||||||
demo: 'https://docusaurus-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Docusaurus makes it easy to maintain Open Source documentation websites.',
|
'Docusaurus makes it easy to maintain Open Source documentation websites.',
|
||||||
description:
|
description:
|
||||||
@@ -501,7 +501,7 @@ export const frameworks = [
|
|||||||
name: 'Preact',
|
name: 'Preact',
|
||||||
slug: 'preact',
|
slug: 'preact',
|
||||||
demo: 'https://preact-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Preact is a fast 3kB alternative to React with the same modern API.',
|
'Preact is a fast 3kB alternative to React with the same modern API.',
|
||||||
description: 'A Preact app, created with the Preact CLI.',
|
description: 'A Preact app, created with the Preact CLI.',
|
||||||
@@ -547,7 +547,7 @@ export const frameworks = [
|
|||||||
name: 'SolidStart',
|
name: 'SolidStart',
|
||||||
slug: 'solidstart',
|
slug: 'solidstart',
|
||||||
demo: 'https://solid-start-template.vercel.app',
|
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.',
|
tagline: 'Simple and performant reactivity for building user interfaces.',
|
||||||
description: 'A Solid app, created with SolidStart.',
|
description: 'A Solid app, created with SolidStart.',
|
||||||
website: 'https://solidjs.com',
|
website: 'https://solidjs.com',
|
||||||
@@ -587,7 +587,7 @@ export const frameworks = [
|
|||||||
name: 'Dojo',
|
name: 'Dojo',
|
||||||
slug: 'dojo',
|
slug: 'dojo',
|
||||||
demo: 'https://dojo-template.vercel.app',
|
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.',
|
tagline: 'Dojo is a modern progressive, TypeScript first framework.',
|
||||||
description:
|
description:
|
||||||
"A Dojo app, created with the Dojo CLI's cli-create-app command.",
|
"A Dojo app, created with the Dojo CLI's cli-create-app command.",
|
||||||
@@ -649,7 +649,7 @@ export const frameworks = [
|
|||||||
name: 'Ember.js',
|
name: 'Ember.js',
|
||||||
slug: 'ember',
|
slug: 'ember',
|
||||||
demo: 'https://ember-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Ember.js helps webapp developers be more productive out of the box.',
|
'Ember.js helps webapp developers be more productive out of the box.',
|
||||||
description: 'An Ember app, created with the Ember CLI.',
|
description: 'An Ember app, created with the Ember CLI.',
|
||||||
@@ -695,7 +695,7 @@ export const frameworks = [
|
|||||||
name: 'Vue.js',
|
name: 'Vue.js',
|
||||||
slug: 'vue',
|
slug: 'vue',
|
||||||
demo: 'https://vue-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Vue.js is a versatile JavaScript framework that is as approachable as it is performant.',
|
'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.',
|
description: 'A Vue.js app, created with the Vue CLI.',
|
||||||
@@ -752,7 +752,7 @@ export const frameworks = [
|
|||||||
name: 'Scully',
|
name: 'Scully',
|
||||||
slug: 'scully',
|
slug: 'scully',
|
||||||
demo: 'https://scully-template.vercel.app',
|
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.',
|
tagline: 'Scully is a static site generator for Angular.',
|
||||||
description: 'The Static Site Generator for Angular apps.',
|
description: 'The Static Site Generator for Angular apps.',
|
||||||
website: 'https://github.com/scullyio/scully',
|
website: 'https://github.com/scullyio/scully',
|
||||||
@@ -788,7 +788,7 @@ export const frameworks = [
|
|||||||
name: 'Ionic Angular',
|
name: 'Ionic Angular',
|
||||||
slug: 'ionic-angular',
|
slug: 'ionic-angular',
|
||||||
demo: 'https://ionic-angular-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Ionic Angular allows you to build mobile PWAs with Angular and the Ionic Framework.',
|
'Ionic Angular allows you to build mobile PWAs with Angular and the Ionic Framework.',
|
||||||
description: 'An Ionic Angular site, created with the Ionic CLI.',
|
description: 'An Ionic Angular site, created with the Ionic CLI.',
|
||||||
@@ -833,7 +833,7 @@ export const frameworks = [
|
|||||||
name: 'Angular',
|
name: 'Angular',
|
||||||
slug: 'angular',
|
slug: 'angular',
|
||||||
demo: 'https://angular-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Angular is a TypeScript-based cross-platform framework from Google.',
|
'Angular is a TypeScript-based cross-platform framework from Google.',
|
||||||
description: 'An Angular app, created with the Angular CLI.',
|
description: 'An Angular app, created with the Angular CLI.',
|
||||||
@@ -893,7 +893,7 @@ export const frameworks = [
|
|||||||
name: 'Polymer',
|
name: 'Polymer',
|
||||||
slug: 'polymer',
|
slug: 'polymer',
|
||||||
demo: 'https://polymer-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Polymer is an open-source webapps library from Google, for building using Web Components.',
|
'Polymer is an open-source webapps library from Google, for building using Web Components.',
|
||||||
description: 'A Polymer app, created with the Polymer CLI.',
|
description: 'A Polymer app, created with the Polymer CLI.',
|
||||||
@@ -950,7 +950,7 @@ export const frameworks = [
|
|||||||
name: 'Svelte',
|
name: 'Svelte',
|
||||||
slug: 'svelte',
|
slug: 'svelte',
|
||||||
demo: 'https://svelte.vercel.app',
|
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:
|
tagline:
|
||||||
'Svelte lets you write high performance reactive apps with significantly less boilerplate.',
|
'Svelte lets you write high performance reactive apps with significantly less boilerplate.',
|
||||||
description: 'A basic Svelte app using the default template.',
|
description: 'A basic Svelte app using the default template.',
|
||||||
@@ -1001,7 +1001,7 @@ export const frameworks = [
|
|||||||
name: 'SvelteKit',
|
name: 'SvelteKit',
|
||||||
slug: 'sveltekit',
|
slug: 'sveltekit',
|
||||||
demo: 'https://sveltekit-template.vercel.app',
|
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:
|
screenshot:
|
||||||
'https://assets.vercel.com/image/upload/v1647366075/front/import/sveltekit.png',
|
'https://assets.vercel.com/image/upload/v1647366075/front/import/sveltekit.png',
|
||||||
tagline:
|
tagline:
|
||||||
@@ -1040,7 +1040,7 @@ export const frameworks = [
|
|||||||
name: 'Ionic React',
|
name: 'Ionic React',
|
||||||
slug: 'ionic-react',
|
slug: 'ionic-react',
|
||||||
demo: 'https://ionic-react-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Ionic React allows you to build mobile PWAs with React and the Ionic Framework.',
|
'Ionic React allows you to build mobile PWAs with React and the Ionic Framework.',
|
||||||
description: 'An Ionic React site, created with the Ionic CLI.',
|
description: 'An Ionic React site, created with the Ionic CLI.',
|
||||||
@@ -1101,7 +1101,7 @@ export const frameworks = [
|
|||||||
name: 'Create React App',
|
name: 'Create React App',
|
||||||
slug: 'create-react-app',
|
slug: 'create-react-app',
|
||||||
demo: 'https://create-react-template.vercel.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.',
|
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.',
|
description: 'A client-side React app created with create-react-app.',
|
||||||
website: 'https://create-react-app.dev',
|
website: 'https://create-react-app.dev',
|
||||||
@@ -1168,7 +1168,7 @@ export const frameworks = [
|
|||||||
name: 'Gridsome',
|
name: 'Gridsome',
|
||||||
slug: 'gridsome',
|
slug: 'gridsome',
|
||||||
demo: 'https://gridsome-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Gridsome is a Vue.js-powered framework for building websites & apps that are fast by default.',
|
'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.',
|
description: 'A Gridsome app, created with the Gridsome CLI.',
|
||||||
@@ -1205,7 +1205,7 @@ export const frameworks = [
|
|||||||
name: 'UmiJS',
|
name: 'UmiJS',
|
||||||
slug: 'umijs',
|
slug: 'umijs',
|
||||||
demo: 'https://umijs-template.vercel.app',
|
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:
|
tagline:
|
||||||
'UmiJS is an extensible enterprise-level React application framework.',
|
'UmiJS is an extensible enterprise-level React application framework.',
|
||||||
description: 'An UmiJS app, created using the Umi CLI.',
|
description: 'An UmiJS app, created using the Umi CLI.',
|
||||||
@@ -1251,7 +1251,7 @@ export const frameworks = [
|
|||||||
name: 'Sapper',
|
name: 'Sapper',
|
||||||
slug: 'sapper',
|
slug: 'sapper',
|
||||||
demo: 'https://sapper-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Sapper is a framework for building high-performance universal web apps with Svelte.',
|
'Sapper is a framework for building high-performance universal web apps with Svelte.',
|
||||||
description: 'A Sapper app, using the Sapper template.',
|
description: 'A Sapper app, using the Sapper template.',
|
||||||
@@ -1288,7 +1288,7 @@ export const frameworks = [
|
|||||||
name: 'Saber',
|
name: 'Saber',
|
||||||
slug: 'saber',
|
slug: 'saber',
|
||||||
demo: 'https://saber-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Saber is a framework for building static sites in Vue.js that supports data from any source.',
|
'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.',
|
description: 'A Saber site, created with npm init.',
|
||||||
@@ -1339,7 +1339,7 @@ export const frameworks = [
|
|||||||
name: 'Stencil',
|
name: 'Stencil',
|
||||||
slug: 'stencil',
|
slug: 'stencil',
|
||||||
demo: 'https://stencil.vercel.app',
|
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:
|
tagline:
|
||||||
'Stencil is a powerful toolchain for building Progressive Web Apps and Design Systems.',
|
'Stencil is a powerful toolchain for building Progressive Web Apps and Design Systems.',
|
||||||
description: 'A Stencil site, created with the Stencil CLI.',
|
description: 'A Stencil site, created with the Stencil CLI.',
|
||||||
@@ -1400,7 +1400,7 @@ export const frameworks = [
|
|||||||
name: 'Nuxt.js',
|
name: 'Nuxt.js',
|
||||||
slug: 'nuxtjs',
|
slug: 'nuxtjs',
|
||||||
demo: 'https://nuxtjs-template.vercel.app',
|
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:
|
screenshot:
|
||||||
'https://assets.vercel.com/image/upload/v1647366075/front/import/nuxtjs.png',
|
'https://assets.vercel.com/image/upload/v1647366075/front/import/nuxtjs.png',
|
||||||
tagline:
|
tagline:
|
||||||
@@ -1460,7 +1460,7 @@ export const frameworks = [
|
|||||||
name: 'RedwoodJS',
|
name: 'RedwoodJS',
|
||||||
slug: 'redwoodjs',
|
slug: 'redwoodjs',
|
||||||
demo: 'https://redwood-template.vercel.app',
|
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.',
|
tagline: 'RedwoodJS is a full-stack framework for the Jamstack.',
|
||||||
description: 'A RedwoodJS app, bootstraped with create-redwood-app.',
|
description: 'A RedwoodJS app, bootstraped with create-redwood-app.',
|
||||||
website: 'https://redwoodjs.com',
|
website: 'https://redwoodjs.com',
|
||||||
@@ -1497,7 +1497,7 @@ export const frameworks = [
|
|||||||
name: 'Hugo',
|
name: 'Hugo',
|
||||||
slug: 'hugo',
|
slug: 'hugo',
|
||||||
demo: 'https://hugo-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Hugo is the world’s fastest framework for building websites, written in Go.',
|
'Hugo is the world’s fastest framework for building websites, written in Go.',
|
||||||
description: 'A Hugo site, created with the Hugo CLI.',
|
description: 'A Hugo site, created with the Hugo CLI.',
|
||||||
@@ -1550,7 +1550,7 @@ export const frameworks = [
|
|||||||
name: 'Jekyll',
|
name: 'Jekyll',
|
||||||
slug: 'jekyll',
|
slug: 'jekyll',
|
||||||
demo: 'https://jekyll-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Jekyll makes it super easy to transform your plain text into static websites and blogs.',
|
'Jekyll makes it super easy to transform your plain text into static websites and blogs.',
|
||||||
description: 'A Jekyll site, created with the Jekyll CLI.',
|
description: 'A Jekyll site, created with the Jekyll CLI.',
|
||||||
@@ -1591,7 +1591,7 @@ export const frameworks = [
|
|||||||
name: 'Brunch',
|
name: 'Brunch',
|
||||||
slug: 'brunch',
|
slug: 'brunch',
|
||||||
demo: 'https://brunch-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Brunch is a fast and simple webapp build tool with seamless incremental compilation for rapid development.',
|
'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.',
|
description: 'A Brunch app, created with the Brunch CLI.',
|
||||||
@@ -1625,7 +1625,7 @@ export const frameworks = [
|
|||||||
name: 'Middleman',
|
name: 'Middleman',
|
||||||
slug: 'middleman',
|
slug: 'middleman',
|
||||||
demo: 'https://middleman-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Middleman is a static site generator that uses all the shortcuts and tools in modern web development.',
|
'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.',
|
description: 'A Middleman app, created with the Middleman CLI.',
|
||||||
@@ -1660,7 +1660,7 @@ export const frameworks = [
|
|||||||
name: 'Zola',
|
name: 'Zola',
|
||||||
slug: 'zola',
|
slug: 'zola',
|
||||||
demo: 'https://zola-template.vercel.app',
|
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.',
|
tagline: 'Everything you need to make a static site engine in one binary.',
|
||||||
description: 'A Zola app, created with the "Getting Started" tutorial.',
|
description: 'A Zola app, created with the "Getting Started" tutorial.',
|
||||||
website: 'https://www.getzola.org',
|
website: 'https://www.getzola.org',
|
||||||
@@ -1694,7 +1694,7 @@ export const frameworks = [
|
|||||||
name: 'Vite',
|
name: 'Vite',
|
||||||
slug: 'vite',
|
slug: 'vite',
|
||||||
demo: 'https://vite-vue-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Vite is a new breed of frontend build tool that significantly improves the frontend development experience.',
|
'Vite is a new breed of frontend build tool that significantly improves the frontend development experience.',
|
||||||
description: 'A Vue.js app, created with Vite.',
|
description: 'A Vue.js app, created with Vite.',
|
||||||
@@ -1732,7 +1732,7 @@ export const frameworks = [
|
|||||||
name: 'Parcel',
|
name: 'Parcel',
|
||||||
slug: 'parcel',
|
slug: 'parcel',
|
||||||
demo: 'https://parcel-template.vercel.app',
|
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:
|
tagline:
|
||||||
'Parcel is a zero configuration build tool for the web that scales to projects of any size and complexity.',
|
'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.',
|
description: 'A vanilla web app built with Parcel.',
|
||||||
@@ -1779,16 +1779,22 @@ export const frameworks = [
|
|||||||
name: 'Sanity',
|
name: 'Sanity',
|
||||||
slug: 'sanity',
|
slug: 'sanity',
|
||||||
demo: 'https://sanity-studio-template.vercel.app',
|
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.',
|
tagline: 'The structured content platform.',
|
||||||
description: 'A Sanity Studio',
|
description: 'A Sanity Studio',
|
||||||
website: 'https://www.sanity.io',
|
website: 'https://www.sanity.io',
|
||||||
envPrefix: 'SANITY_STUDIO_',
|
envPrefix: 'SANITY_STUDIO_',
|
||||||
detectors: {
|
detectors: {
|
||||||
every: [
|
some: [
|
||||||
{
|
{
|
||||||
path: 'sanity.json',
|
path: 'sanity.json',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'sanity.config.js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'sanity.config.ts',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
settings: {
|
settings: {
|
||||||
@@ -1822,7 +1828,7 @@ export const frameworks = [
|
|||||||
name: 'Hydrogen',
|
name: 'Hydrogen',
|
||||||
slug: 'hydrogen',
|
slug: 'hydrogen',
|
||||||
demo: 'https://hydrogen-template.vercel.app',
|
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',
|
tagline: 'React framework for headless commerce',
|
||||||
description: 'React framework for headless commerce',
|
description: 'React framework for headless commerce',
|
||||||
website: 'https://hydrogen.shopify.dev',
|
website: 'https://hydrogen.shopify.dev',
|
||||||
@@ -1856,7 +1862,7 @@ export const frameworks = [
|
|||||||
{
|
{
|
||||||
name: 'Other',
|
name: 'Other',
|
||||||
slug: null,
|
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.',
|
description: 'No framework or an unoptimized framework.',
|
||||||
settings: {
|
settings: {
|
||||||
installCommand: {
|
installCommand: {
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ export interface Framework {
|
|||||||
slug: string | null;
|
slug: string | null;
|
||||||
/**
|
/**
|
||||||
* A URL to the logo of the framework
|
* 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;
|
logo: string;
|
||||||
/**
|
/**
|
||||||
* An additional URL to the logo of the framework optimized for dark mode
|
* 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;
|
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
|
// bump timeout for Windows as network can be slower
|
||||||
jest.setTimeout(15 * 1000);
|
jest.setTimeout(15 * 1000);
|
||||||
|
|
||||||
|
const logoPrefix = 'https://api-frameworks.vercel.sh/framework-logos/';
|
||||||
|
|
||||||
const SchemaFrameworkDetectionItem = {
|
const SchemaFrameworkDetectionItem = {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: [
|
items: [
|
||||||
@@ -172,14 +174,33 @@ describe('frameworks', () => {
|
|||||||
expect(result).toBe(true);
|
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
|
const missing = frameworkList
|
||||||
.map(f => f.logo)
|
.map(f => f.logo)
|
||||||
.filter(url => {
|
.filter(logo => {
|
||||||
const prefix =
|
const filename = logo.slice(logoPrefix.length);
|
||||||
'https://raw.githubusercontent.com/vercel/vercel/main/packages/frameworks/logos/';
|
const filepath = join(__dirname, '..', 'logos', filename);
|
||||||
const name = url.replace(prefix, '');
|
return existsSync(filepath) === false;
|
||||||
return existsSync(join(__dirname, '..', 'logos', name)) === false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(missing).toEqual([]);
|
expect(missing).toEqual([]);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@vercel/fs-detectors",
|
"name": "@vercel/fs-detectors",
|
||||||
"version": "2.1.0",
|
"version": "3.4.0",
|
||||||
"description": "Vercel filesystem detectors",
|
"description": "Vercel filesystem detectors",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
"test-unit": "yarn test"
|
"test-unit": "yarn test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vercel/frameworks": "1.1.3",
|
"@vercel/frameworks": "1.1.6",
|
||||||
"@vercel/routing-utils": "2.0.2",
|
"@vercel/routing-utils": "2.0.2",
|
||||||
"glob": "8.0.3",
|
"glob": "8.0.3",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { posix as posixPath } from 'path';
|
||||||
|
|
||||||
export interface Stat {
|
export interface Stat {
|
||||||
name: string;
|
name: string;
|
||||||
path: string;
|
path: string;
|
||||||
@@ -76,13 +78,45 @@ export abstract class DetectorFilesystem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of Stat objects from the current working directory.
|
* Returns a list of Stat objects from the current working directory.
|
||||||
|
* @param dirPath The path of the directory to read.
|
||||||
|
* @param options.potentialFiles optional. Array of potential file names (relative to the path). If provided, these will be used to mark the filesystem caches as existing or not existing.
|
||||||
*/
|
*/
|
||||||
public readdir = async (name: string): Promise<Stat[]> => {
|
public readdir = async (
|
||||||
let p = this.readdirCache.get(name);
|
dirPath: string,
|
||||||
|
options?: { potentialFiles?: string[] }
|
||||||
|
): Promise<Stat[]> => {
|
||||||
|
let p = this.readdirCache.get(dirPath);
|
||||||
if (!p) {
|
if (!p) {
|
||||||
p = this._readdir(name);
|
p = this._readdir(dirPath);
|
||||||
this.readdirCache.set(name, p);
|
this.readdirCache.set(dirPath, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const directoryContent = await p;
|
||||||
|
const directoryFiles = new Set<string>();
|
||||||
|
|
||||||
|
for (const file of directoryContent) {
|
||||||
|
if (file.type === 'file') {
|
||||||
|
// we know this file exists, mark it as so on the filesystem
|
||||||
|
this.fileCache.set(file.path, Promise.resolve(true));
|
||||||
|
this.pathCache.set(file.path, Promise.resolve(true));
|
||||||
|
directoryFiles.add(file.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.potentialFiles) {
|
||||||
|
// calculate the set of paths that truly do not exist
|
||||||
|
const filesThatDoNotExist = options.potentialFiles.filter(
|
||||||
|
path => !directoryFiles.has(path)
|
||||||
|
);
|
||||||
|
for (const filePath of filesThatDoNotExist) {
|
||||||
|
const fullFilePath =
|
||||||
|
dirPath === '/' ? filePath : posixPath.join(dirPath, filePath);
|
||||||
|
// we know this file does not exist, mark it as so on the filesystem
|
||||||
|
this.fileCache.set(fullFilePath, Promise.resolve(false));
|
||||||
|
this.pathCache.set(fullFilePath, Promise.resolve(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -98,10 +132,9 @@ export abstract class DetectorFilesystem {
|
|||||||
* @param name the name of the file to write
|
* @param name the name of the file to write
|
||||||
* @param content The content of the file
|
* @param content The content of the file
|
||||||
*/
|
*/
|
||||||
public writeFile(name: string, content?: string): void {
|
public writeFile = async (name: string, content: string): Promise<void> => {
|
||||||
if (content)
|
this.readFileCache.set(name, Promise.resolve(Buffer.from(content)));
|
||||||
this.readFileCache.set(name, Promise.resolve(Buffer.from(content)));
|
|
||||||
this.fileCache.set(name, Promise.resolve(true));
|
this.fileCache.set(name, Promise.resolve(true));
|
||||||
this.pathCache.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;
|
export default monorepoManagers;
|
||||||
|
|||||||
@@ -33,6 +33,12 @@ export async function getWorkspacePackagePaths({
|
|||||||
case 'pnpm':
|
case 'pnpm':
|
||||||
results = await getPnpmWorkspacePackagePaths({ fs: workspaceFs });
|
results = await getPnpmWorkspacePackagePaths({ fs: workspaceFs });
|
||||||
break;
|
break;
|
||||||
|
case 'nx':
|
||||||
|
results = await getNxWorkspacePackagePaths({ fs: workspaceFs });
|
||||||
|
break;
|
||||||
|
case 'rush':
|
||||||
|
results = await getRushWorkspacePackagePaths({ fs: workspaceFs });
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown workspace implementation: ${type}`);
|
throw new Error(`Unknown workspace implementation: ${type}`);
|
||||||
}
|
}
|
||||||
@@ -55,6 +61,14 @@ type PnpmWorkspaces = {
|
|||||||
packages?: string[];
|
packages?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type RushWorkspaces = {
|
||||||
|
projects: [
|
||||||
|
{
|
||||||
|
projectFolder: string;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
const isWin = process.platform === 'win32';
|
const isWin = process.platform === 'win32';
|
||||||
const normalizePath = (p: string) => (isWin ? p.replace(/\\/g, '/') : p);
|
const normalizePath = (p: string) => (isWin ? p.replace(/\\/g, '/') : p);
|
||||||
|
|
||||||
@@ -103,6 +117,17 @@ async function getPackageJsonWorkspacePackagePaths({
|
|||||||
return getPackagePaths(packages, fs);
|
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({
|
async function getPnpmWorkspacePackagePaths({
|
||||||
fs,
|
fs,
|
||||||
}: GetPackagePathOptions): Promise<string[]> {
|
}: GetPackagePathOptions): Promise<string[]> {
|
||||||
@@ -113,3 +138,23 @@ async function getPnpmWorkspacePackagePaths({
|
|||||||
|
|
||||||
return getPackagePaths(packages, fs);
|
return getPackagePaths(packages, fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getRushWorkspacePackagePaths({
|
||||||
|
fs,
|
||||||
|
}: GetPackagePathOptions): Promise<string[]> {
|
||||||
|
const rushWorkspaceAsBuffer = await fs.readFile('rush.json');
|
||||||
|
|
||||||
|
const { projects = [] } = JSON.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;
|
cwd?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm';
|
export type WorkspaceType = 'yarn' | 'pnpm' | 'npm' | 'nx' | 'rush';
|
||||||
|
|
||||||
export type Workspace = {
|
export type Workspace = {
|
||||||
type: WorkspaceType;
|
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',
|
name: 'default',
|
||||||
slug: 'yarn',
|
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": []
|
||||||
|
},
|
||||||
|
"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": {}
|
||||||
|
}
|
||||||
27
packages/fs-detectors/test/fixtures/42-rush-json-invalid/rush.json
vendored
Normal file
27
packages/fs-detectors/test/fixtures/42-rush-json-invalid/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": "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"
|
||||||
|
}
|
||||||
|
}
|
||||||
15
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/apps/app-two/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/apps/app-two/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "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"
|
||||||
|
}
|
||||||
|
}
|
||||||
3
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/workspace.json
vendored
Normal file
3
packages/fs-detectors/test/fixtures/43-nx-json-misshaped/workspace.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"version": 2
|
||||||
|
}
|
||||||
15
packages/fs-detectors/test/fixtures/44-nx-json-string/apps/app-one/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/44-nx-json-string/apps/app-one/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "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/44-nx-json-string/apps/app-two/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/44-nx-json-string/apps/app-two/package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "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"
|
||||||
|
}
|
||||||
|
}
|
||||||
4
packages/fs-detectors/test/fixtures/44-nx-json-string/workspace.json
vendored
Normal file
4
packages/fs-detectors/test/fixtures/44-nx-json-string/workspace.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"projects": "hello"
|
||||||
|
}
|
||||||
15
packages/fs-detectors/test/fixtures/45-rush-no-project-folder/apps/my-app/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/45-rush-no-project-folder/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/45-rush-no-project-folder/apps/my-second-app/package.json
vendored
Normal file
15
packages/fs-detectors/test/fixtures/45-rush-no-project-folder/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"
|
||||||
|
}
|
||||||
|
}
|
||||||
35
packages/fs-detectors/test/fixtures/45-rush-no-project-folder/rush.json
vendored
Normal file
35
packages/fs-detectors/test/fixtures/45-rush-no-project-folder/rush.json
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"$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": [
|
||||||
|
{
|
||||||
|
"packageName": "my-app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"packageName": "my-second-app",
|
||||||
|
"projectFolder": "apps/my-second-app"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ describe('monorepo-managers', () => {
|
|||||||
['28-turborepo-with-yarn-workspaces', 'turbo'],
|
['28-turborepo-with-yarn-workspaces', 'turbo'],
|
||||||
['31-turborepo-in-package-json', 'turbo'],
|
['31-turborepo-in-package-json', 'turbo'],
|
||||||
['22-pnpm', null],
|
['22-pnpm', null],
|
||||||
|
['39-nx-monorepo', 'nx'],
|
||||||
|
['40-rush-monorepo', 'rush'],
|
||||||
])('with detectFramework', (fixturePath, frameworkSlug) => {
|
])('with detectFramework', (fixturePath, frameworkSlug) => {
|
||||||
const testName = frameworkSlug
|
const testName = frameworkSlug
|
||||||
? `should detect a ${frameworkSlug} workspace for ${fixturePath}`
|
? `should detect a ${frameworkSlug} workspace for ${fixturePath}`
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import frameworkList from '@vercel/frameworks';
|
import frameworkList from '@vercel/frameworks';
|
||||||
|
import workspaceManagers from '../src/workspaces/workspace-managers';
|
||||||
import { detectFramework, DetectorFilesystem } from '../src';
|
import { detectFramework, DetectorFilesystem } from '../src';
|
||||||
import { Stat } from '../src/detectors/filesystem';
|
import { Stat } from '../src/detectors/filesystem';
|
||||||
|
|
||||||
@@ -135,11 +136,18 @@ describe('DetectorFilesystem', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const fs = new VirtualFilesystem(files);
|
const fs = new VirtualFilesystem(files);
|
||||||
|
const hasPathSpy = jest.spyOn(fs, '_hasPath');
|
||||||
|
|
||||||
expect(await fs.readdir('/')).toEqual([
|
expect(await fs.readdir('/', { potentialFiles: ['config.rb'] })).toEqual([
|
||||||
{ name: 'package.json', path: 'package.json', type: 'file' },
|
{ name: 'package.json', path: 'package.json', type: 'file' },
|
||||||
{ name: 'packages', path: 'packages', type: 'dir' },
|
{ name: 'packages', path: 'packages', type: 'dir' },
|
||||||
]);
|
]);
|
||||||
|
expect(await fs.hasPath('package.json')).toBe(true);
|
||||||
|
expect(hasPathSpy).not.toHaveBeenCalled();
|
||||||
|
expect(await fs.hasPath('config.rb')).toBe(false);
|
||||||
|
expect(hasPathSpy).not.toHaveBeenCalled();
|
||||||
|
expect(await fs.hasPath('tsconfig.json')).toBe(false);
|
||||||
|
expect(hasPathSpy).toHaveBeenCalled();
|
||||||
|
|
||||||
expect(await fs.readdir('packages')).toEqual([
|
expect(await fs.readdir('packages')).toEqual([
|
||||||
{ name: 'app1', path: 'packages/app1', type: 'dir' },
|
{ name: 'app1', path: 'packages/app1', type: 'dir' },
|
||||||
@@ -151,24 +159,51 @@ describe('DetectorFilesystem', () => {
|
|||||||
{ name: 'app2', path: 'packages/app2', type: 'dir' },
|
{ name: 'app2', path: 'packages/app2', type: 'dir' },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(await fs.readdir('packages/app1')).toEqual([
|
expect(
|
||||||
|
await fs.readdir('packages/app1', { potentialFiles: ['package.json'] })
|
||||||
|
).toEqual([
|
||||||
{
|
{
|
||||||
name: 'package.json',
|
name: 'package.json',
|
||||||
path: 'packages/app1/package.json',
|
path: 'packages/app1/package.json',
|
||||||
type: 'file',
|
type: 'file',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
hasPathSpy.mock.calls.length = 0;
|
||||||
|
expect(await fs.hasPath('packages/app1/package.json')).toBe(true);
|
||||||
|
expect(hasPathSpy).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await fs.readdir('packages/app1', { potentialFiles: ['vercel.json'] })
|
||||||
|
).toEqual([
|
||||||
|
{
|
||||||
|
name: 'package.json',
|
||||||
|
path: 'packages/app1/package.json',
|
||||||
|
type: 'file',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
hasPathSpy.mock.calls.length = 0;
|
||||||
|
expect(await fs.hasPath('packages/app1/vercel.json')).toBe(false);
|
||||||
|
expect(hasPathSpy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to write files', async () => {
|
it('should be able to write files', async () => {
|
||||||
const files = {};
|
const files = {};
|
||||||
const fs = new VirtualFilesystem(files);
|
const fs = new VirtualFilesystem(files);
|
||||||
|
const hasPathSpy = jest.spyOn(fs, '_hasPath');
|
||||||
|
const isFileSpy = jest.spyOn(fs, '_isFile');
|
||||||
|
const readFileSpy = jest.spyOn(fs, '_readFile');
|
||||||
|
|
||||||
fs.writeFile('file.txt', 'Hello World');
|
await fs.writeFile('file.txt', 'Hello World');
|
||||||
|
|
||||||
expect(await fs.readFile('file.txt')).toEqual(Buffer.from('Hello World'));
|
expect(await fs.readFile('file.txt')).toEqual(Buffer.from('Hello World'));
|
||||||
expect(await fs.hasPath('file.txt')).toBe(true);
|
expect(await fs.hasPath('file.txt')).toBe(true);
|
||||||
expect(await fs.isFile('file.txt')).toBe(true);
|
expect(await fs.isFile('file.txt')).toBe(true);
|
||||||
|
// We expect that the fs returned values from it's caches instead of calling the underlying functions
|
||||||
|
expect(hasPathSpy).not.toHaveBeenCalled();
|
||||||
|
expect(isFileSpy).not.toHaveBeenCalled();
|
||||||
|
expect(readFileSpy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to change directories', async () => {
|
it('should be able to change directories', async () => {
|
||||||
@@ -251,6 +286,28 @@ describe('DetectorFilesystem', () => {
|
|||||||
expect(await detectFramework({ fs, frameworkList })).toBe(null);
|
expect(await detectFramework({ fs, frameworkList })).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Detect nx', async () => {
|
||||||
|
const fs = new VirtualFilesystem({
|
||||||
|
'workspace.json': JSON.stringify({
|
||||||
|
projects: { 'app-one': 'apps/app-one' },
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await detectFramework({ fs, frameworkList: workspaceManagers })
|
||||||
|
).toBe('nx');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Do not detect anything', async () => {
|
||||||
|
const fs = new VirtualFilesystem({
|
||||||
|
'workspace.json': JSON.stringify({ projects: {} }),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await detectFramework({ fs, frameworkList: workspaceManagers })
|
||||||
|
).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
it('Detect Next.js', async () => {
|
it('Detect Next.js', async () => {
|
||||||
const fs = new VirtualFilesystem({
|
const fs = new VirtualFilesystem({
|
||||||
'package.json': JSON.stringify({
|
'package.json': JSON.stringify({
|
||||||
|
|||||||
@@ -14,7 +14,15 @@ describe.each<[string, string[]]>([
|
|||||||
['/backend/c', '/backend/d', '/frontend/a', '/frontend/b'],
|
['/backend/c', '/backend/d', '/frontend/a', '/frontend/b'],
|
||||||
],
|
],
|
||||||
['22-pnpm', []],
|
['22-pnpm', []],
|
||||||
])('`getWorkspacesPackagePaths()`', (fixturePath, packagePaths) => {
|
['41-nx-workspace', ['/apps/app-one', '/apps/app-two']],
|
||||||
|
['42-npm-workspace-with-nx', ['/apps/app-one', '/apps/app-two']],
|
||||||
|
['43-nx-json-misshaped', []],
|
||||||
|
['44-nx-json-string', []],
|
||||||
|
['40-rush-monorepo', ['/apps/my-app', '/apps/my-second-app']],
|
||||||
|
['41-rush-monorepo-empty', []],
|
||||||
|
['42-rush-json-invalid', []],
|
||||||
|
['45-rush-no-project-folder', ['/apps/my-second-app']],
|
||||||
|
])('`getWorkspacePackagePaths()`', (fixturePath, packagePaths) => {
|
||||||
const testName =
|
const testName =
|
||||||
packagePaths.length > 0
|
packagePaths.length > 0
|
||||||
? `should detect ${packagePaths.join()} package${
|
? `should detect ${packagePaths.join()} package${
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user