mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-27 03:39:11 +00:00
Compare commits
16 Commits
@vercel/cl
...
jake-debug
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6155759e40 | ||
|
|
f0bc911514 | ||
|
|
dc30c134ef | ||
|
|
a56ab4ded9 | ||
|
|
5660dab2ae | ||
|
|
1202cf8792 | ||
|
|
80b8c3d022 | ||
|
|
68e5edb9a2 | ||
|
|
1545e31a31 | ||
|
|
76ea6ea2a7 | ||
|
|
5b8b87739e | ||
|
|
6ff7b34a44 | ||
|
|
97d9e83232 | ||
|
|
a3fb7e6abe | ||
|
|
b9f6d765c0 | ||
|
|
c24d85f574 |
4
.changeset/chatty-pets-hear.md
Normal file
4
.changeset/chatty-pets-hear.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
---
|
||||
|
||||
disable eslint for a few files
|
||||
5
.changeset/early-bears-sip.md
Normal file
5
.changeset/early-bears-sip.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@vercel/go": patch
|
||||
---
|
||||
|
||||
Add support for `1.22` and update Go minor versions `1.19`, `1.20` and `1.21`
|
||||
4
.changeset/healthy-tools-knock.md
Normal file
4
.changeset/healthy-tools-knock.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
---
|
||||
|
||||
[framework-fixtures]: Bump the core group in /packages/static-build/test/fixtures/ionic-react-v7 with 2 updates
|
||||
5
.changeset/honest-rockets-applaud.md
Normal file
5
.changeset/honest-rockets-applaud.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"vercel": patch
|
||||
---
|
||||
|
||||
avoid printing errors when user does ctrl+c
|
||||
4
.changeset/light-maps-tap.md
Normal file
4
.changeset/light-maps-tap.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
---
|
||||
|
||||
[framework-fixtures]: Bump the core group in /packages/static-build/test/fixtures/stencil-v4 with 1 update
|
||||
4
.changeset/lucky-jars-dance.md
Normal file
4
.changeset/lucky-jars-dance.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
---
|
||||
|
||||
[framework-fixtures]: Bump the core group in /packages/static-build/test/fixtures/nuxt-v3 with 3 updates
|
||||
5
.changeset/orange-houses-rest.md
Normal file
5
.changeset/orange-houses-rest.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'vercel': minor
|
||||
---
|
||||
|
||||
improve UX for text input validation
|
||||
5
.changeset/popular-foxes-camp.md
Normal file
5
.changeset/popular-foxes-camp.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'vercel': minor
|
||||
---
|
||||
|
||||
Replace the implementation of the yes/no prompt in several areas to be consistent with the rest of the CLI.
|
||||
4
.changeset/quiet-coins-breathe.md
Normal file
4
.changeset/quiet-coins-breathe.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
---
|
||||
|
||||
[framework-fixtures]: Bump the core group in /packages/static-build/test/fixtures/nuxt-v3 with 3 updates
|
||||
4
.changeset/rude-seas-mate.md
Normal file
4
.changeset/rude-seas-mate.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
---
|
||||
|
||||
[framework-fixtures]: Bump the core group in /packages/static-build/test/fixtures/preact-v10 with 2 updates
|
||||
4
.changeset/sour-countries-heal.md
Normal file
4
.changeset/sour-countries-heal.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
---
|
||||
|
||||
Move CONTRIBUTING into README and improve docs on running integration tests locally
|
||||
2
.changeset/strong-peas-fly.md
Normal file
2
.changeset/strong-peas-fly.md
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
---
|
||||
5
.changeset/stupid-actors-judge.md
Normal file
5
.changeset/stupid-actors-judge.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'vercel': patch
|
||||
---
|
||||
|
||||
Warn that promoting preview deploys is deprecated
|
||||
109
.github/CONTRIBUTING.md
vendored
109
.github/CONTRIBUTING.md
vendored
@@ -1,108 +1,3 @@
|
||||
# Contributing
|
||||
## Contributing
|
||||
|
||||
When contributing to this repository, please first discuss the change you wish to make via [GitHub Discussions](https://github.com/vercel/vercel/discussions/new) with the owners of this repository before submitting a Pull Request.
|
||||
|
||||
Please read our [Code of Conduct](CODE_OF_CONDUCT.md) and follow it in all your interactions with the project.
|
||||
|
||||
## Local development
|
||||
|
||||
This project is configured in a monorepo, where one repository contains multiple npm packages. Dependencies are installed and managed with `pnpm`, not `npm` CLI.
|
||||
|
||||
To get started, execute the following:
|
||||
|
||||
```
|
||||
git clone https://github.com/vercel/vercel
|
||||
cd vercel
|
||||
corepack enable
|
||||
pnpm install
|
||||
pnpm build
|
||||
pnpm lint
|
||||
pnpm test-unit
|
||||
```
|
||||
|
||||
Make sure all the tests pass before making changes.
|
||||
|
||||
### Running Vercel CLI Changes
|
||||
|
||||
You can use `pnpm dev` from the `cli` package to invoke Vercel CLI with local changes:
|
||||
|
||||
```
|
||||
cd ./packages/cli
|
||||
pnpm dev <cli-commands...>
|
||||
```
|
||||
|
||||
See [CLI Local Development](../packages/cli#local-development) for more details.
|
||||
|
||||
## Verifying your change
|
||||
|
||||
Once you are done with your changes (we even suggest doing it along the way), make sure all the tests still pass by running:
|
||||
|
||||
```
|
||||
pnpm test-unit
|
||||
```
|
||||
|
||||
from the root of the project.
|
||||
|
||||
If any test fails, make sure to fix it along with your changes. See [Interpreting test errors](#Interpreting-test-errors) for more information about how the tests are executed, especially the integration tests.
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
Once you are confident that your changes work properly, open a pull request on the main repository.
|
||||
|
||||
The pull request will be reviewed by the maintainers and the tests will be checked by our continuous integration platform.
|
||||
|
||||
## Interpreting test errors
|
||||
|
||||
There are 2 kinds of tests in this repository – Unit tests and Integration tests.
|
||||
|
||||
Unit tests are run locally with `jest` and execute quickly because they are testing the smallest units of code.
|
||||
|
||||
### Integration tests
|
||||
|
||||
Integration tests create deployments to your Vercel account using the `test` project name. After each test is deployed, the `probes` key is used to check if the response is the expected value. If the value doesn't match, you'll see a message explaining the difference. If the deployment failed to build, you'll see a more generic message like the following:
|
||||
|
||||
```
|
||||
[Error: Fetched page https://test-8ashcdlew.vercel.app/root.js does not contain hello Root!. Instead it contains An error occurred with this application.
|
||||
|
||||
NO_STATUS_CODE_FRO Response headers:
|
||||
cache-control=s-maxage=0
|
||||
connection=close
|
||||
content-type=text/plain; charset=utf-8
|
||||
date=Wed, 19 Jun 2019 18:01:37 GMT
|
||||
server=now
|
||||
strict-transport-security=max-age=63072000
|
||||
transfer-encoding=chunked
|
||||
x-now-id=iad1:hgtzj-1560967297876-44ae12559f95
|
||||
x-now-trace=iad1]
|
||||
```
|
||||
|
||||
In such cases, you can visit the URL of the failed deployment and append `/_logs` to see the build error. In the case above, that would be https://test-8ashcdlew.vercel.app/_logs
|
||||
|
||||
The logs of this deployment will contain the actual error which may help you to understand what went wrong.
|
||||
|
||||
### @vercel/nft
|
||||
|
||||
Some of the Builders use `@vercel/nft` to tree-shake files before deployment. If you suspect an error with this tree-shaking mechanism, you can create the following script in your project:
|
||||
|
||||
```js
|
||||
const { nodeFileTrace } = require('@vercel/nft');
|
||||
nodeFileTrace(['path/to/entrypoint.js'], {
|
||||
ts: true,
|
||||
mixedModules: true,
|
||||
})
|
||||
.then(o => console.log(o.fileList))
|
||||
.then(e => console.error(e));
|
||||
```
|
||||
|
||||
When you run this script, you'll see all the imported files. If anything file is missing, the bug is in [@vercel/nft](https://github.com/vercel/nft) and not the Builder.
|
||||
|
||||
## Deploy a Builder with existing project
|
||||
|
||||
Sometimes you want to test changes to a Builder against an existing project, maybe with `vercel dev` or actual deployment. You can avoid publishing every Builder change to npm by uploading the Builder as a tarball.
|
||||
|
||||
1. Change directory to the desired Builder `cd ./packages/node`
|
||||
2. Run `pnpm build` to compile typescript and other build steps
|
||||
3. Run `npm pack` to create a tarball file
|
||||
4. Run `vercel *.tgz` to upload the tarball file and get a URL
|
||||
5. Edit any existing `vercel.json` project and replace `use` with the URL
|
||||
6. Run `vercel` or `vercel dev` to deploy with the experimental Builder
|
||||
See the [Contributing Guidelines](../README.md#contributing) for more details.
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -79,9 +79,6 @@ jobs:
|
||||
run: npm i -g pnpm@8.3.1
|
||||
|
||||
- run: pnpm install
|
||||
- name: fetch ssl certificate before build (linux, os x)
|
||||
if: matrix.runner != 'windows-latest'
|
||||
run: echo | openssl s_client -showcerts -servername 'api.vercel.com' -connect 76.76.21.21:443
|
||||
|
||||
- name: Build ${{matrix.packageName}} and all its dependencies
|
||||
run: node utils/gen.js && node_modules/.bin/turbo run build --cache-dir=".turbo" --log-order=stream --scope=${{matrix.packageName}} --include-dependencies --no-deps
|
||||
@@ -104,9 +101,6 @@ jobs:
|
||||
TURBO_MISS_COUNT=`node utils/determine-turbo-hit-or-miss.js`
|
||||
echo "MISS COUNT: $TURBO_MISS_COUNT"
|
||||
echo "misses=$TURBO_MISS_COUNT" >> $GITHUB_OUTPUT
|
||||
- name: fetch ssl certificate after tests (linux, os x)
|
||||
if: matrix.runner != 'windows-latest'
|
||||
run: echo | openssl s_client -showcerts -servername 'api.vercel.com' -connect 76.76.21.21:443
|
||||
- name: 'Upload Test Report to Datadog'
|
||||
if: ${{ steps['turbo-summary'].outputs.misses != '0' && !cancelled() }}
|
||||
run: 'npx @datadog/datadog-ci@2.18.1 junit upload --service vercel-cli .junit-reports'
|
||||
|
||||
129
README.md
129
README.md
@@ -35,7 +35,134 @@ This project uses [pnpm](https://pnpm.io/) to install dependencies and run scrip
|
||||
|
||||
You can use the `dev` script to run local changes as if you were invoking Vercel CLI. For example, `vercel deploy --cwd=/path/to/project` could be run with local changes with `pnpm dev deploy --cwd=/path/to/project`.
|
||||
|
||||
See the [Contributing Guidelines](./.github/CONTRIBUTING.md) for more details.
|
||||
When contributing to this repository, please first discuss the change you wish to make via [GitHub Discussions](https://github.com/vercel/vercel/discussions/new) with the owners of this repository before submitting a Pull Request.
|
||||
|
||||
Please read our [Code of Conduct](CODE_OF_CONDUCT.md) and follow it in all your interactions with the project.
|
||||
|
||||
### Local development
|
||||
|
||||
This project is configured in a monorepo, where one repository contains multiple npm packages. Dependencies are installed and managed with `pnpm`, not `npm` CLI.
|
||||
|
||||
To get started, execute the following:
|
||||
|
||||
```
|
||||
git clone https://github.com/vercel/vercel
|
||||
cd vercel
|
||||
corepack enable
|
||||
pnpm install
|
||||
pnpm build
|
||||
pnpm lint
|
||||
pnpm test-unit
|
||||
```
|
||||
|
||||
Make sure all the tests pass before making changes.
|
||||
|
||||
#### Running Vercel CLI Changes
|
||||
|
||||
You can use `pnpm dev` from the `cli` package to invoke Vercel CLI with local changes:
|
||||
|
||||
```
|
||||
cd ./packages/cli
|
||||
pnpm dev <cli-commands...>
|
||||
```
|
||||
|
||||
See [CLI Local Development](../packages/cli#local-development) for more details.
|
||||
|
||||
### Verifying your change
|
||||
|
||||
Once you are done with your changes (we even suggest doing it along the way), make sure all the tests still pass by running:
|
||||
|
||||
```
|
||||
pnpm test-unit
|
||||
```
|
||||
|
||||
from the root of the project.
|
||||
|
||||
If any test fails, make sure to fix it along with your changes. See [Interpreting test errors](#Interpreting-test-errors) for more information about how the tests are executed, especially the integration tests.
|
||||
|
||||
### Pull Request Process
|
||||
|
||||
Once you are confident that your changes work properly, open a pull request on the main repository.
|
||||
|
||||
The pull request will be reviewed by the maintainers and the tests will be checked by our continuous integration platform.
|
||||
|
||||
### Interpreting test errors
|
||||
|
||||
There are 2 kinds of tests in this repository – Unit tests and Integration tests.
|
||||
|
||||
Unit tests are run locally with `jest` and execute quickly because they are testing the smallest units of code.
|
||||
|
||||
#### Integration tests
|
||||
|
||||
Integration tests create deployments to your Vercel account using the `test` project name. After each test is deployed, the `probes` key is used to check if the response is the expected value. If the value doesn't match, you'll see a message explaining the difference. If the deployment failed to build, you'll see a more generic message like the following:
|
||||
|
||||
```
|
||||
[Error: Fetched page https://test-8ashcdlew.vercel.app/root.js does not contain hello Root!. Instead it contains An error occurred with this application.
|
||||
|
||||
NO_STATUS_CODE_FRO Response headers:
|
||||
cache-control=s-maxage=0
|
||||
connection=close
|
||||
content-type=text/plain; charset=utf-8
|
||||
date=Wed, 19 Jun 2019 18:01:37 GMT
|
||||
server=now
|
||||
strict-transport-security=max-age=63072000
|
||||
transfer-encoding=chunked
|
||||
x-now-id=iad1:hgtzj-1560967297876-44ae12559f95
|
||||
x-now-trace=iad1]
|
||||
```
|
||||
|
||||
In such cases, you can visit the URL of the failed deployment and append `/_logs` to see the build error. In the case above, that would be https://test-8ashcdlew.vercel.app/_logs
|
||||
|
||||
The logs of this deployment will contain the actual error which may help you to understand what went wrong.
|
||||
|
||||
##### Running integration tests locally
|
||||
|
||||
While running the full integration suite locally is not recommended, it's sometimes useful to isolate a failing test by running it on your machine. To do so, you'll need to ensure you have the appropriate credentials sourced in your shell:
|
||||
|
||||
1. Create an access token. Follow the insructions here https://vercel.com/docs/rest-api#creating-an-access-token. Ensure the token scope is for your personal
|
||||
account.
|
||||
2. Grab the team ID from the Vercel dashboard at `https://vercel.com/<MY-TEAM>/~/settings`.
|
||||
3. Source these into your shell rc file: `echo 'export VERCEL_TOKEN=<MY-TOKEN> VERCEL_TEAM_ID=<MY-TEAM-ID>' >> ~/.zshrc`
|
||||
|
||||
From there, you should be able to trigger an integration test. Choose one
|
||||
that's already isolated to check that things work:
|
||||
|
||||
```
|
||||
cd packages/next
|
||||
```
|
||||
|
||||
Run the test:
|
||||
|
||||
```
|
||||
pnpm test test/fixtures/00-server-build/index.test.js
|
||||
```
|
||||
|
||||
#### @vercel/nft
|
||||
|
||||
Some of the Builders use `@vercel/nft` to tree-shake files before deployment. If you suspect an error with this tree-shaking mechanism, you can create the following script in your project:
|
||||
|
||||
```js
|
||||
const { nodeFileTrace } = require('@vercel/nft');
|
||||
nodeFileTrace(['path/to/entrypoint.js'], {
|
||||
ts: true,
|
||||
mixedModules: true,
|
||||
})
|
||||
.then(o => console.log(o.fileList))
|
||||
.then(e => console.error(e));
|
||||
```
|
||||
|
||||
When you run this script, you'll see all the imported files. If anything file is missing, the bug is in [@vercel/nft](https://github.com/vercel/nft) and not the Builder.
|
||||
|
||||
### Deploy a Builder with existing project
|
||||
|
||||
Sometimes you want to test changes to a Builder against an existing project, maybe with `vercel dev` or actual deployment. You can avoid publishing every Builder change to npm by uploading the Builder as a tarball.
|
||||
|
||||
1. Change directory to the desired Builder `cd ./packages/node`
|
||||
2. Run `pnpm build` to compile typescript and other build steps
|
||||
3. Run `npm pack` to create a tarball file
|
||||
4. Run `vercel *.tgz` to upload the tarball file and get a URL
|
||||
5. Edit any existing `vercel.json` project and replace `use` with the URL
|
||||
6. Run `vercel` or `vercel dev` to deploy with the experimental Builder
|
||||
|
||||
## Reference
|
||||
|
||||
|
||||
@@ -45,10 +45,16 @@ export default async function bisect(client: Client): Promise<number> {
|
||||
|
||||
let bad =
|
||||
argv['--bad'] ||
|
||||
(await prompt(client, `Specify a URL where the bug occurs:`));
|
||||
(await client.input.text({
|
||||
message: `Specify a URL where the bug occurs:`,
|
||||
validate: val => (val ? true : 'A URL must be provided'),
|
||||
}));
|
||||
let good =
|
||||
argv['--good'] ||
|
||||
(await prompt(client, `Specify a URL where the bug does not occur:`));
|
||||
(await client.input.text({
|
||||
message: `Specify a URL where the bug does not occur:`,
|
||||
validate: val => (val ? true : 'A URL must be provided'),
|
||||
}));
|
||||
let subpath = argv['--path'] || '';
|
||||
let run = argv['--run'] || '';
|
||||
const openEnabled = argv['--open'] || false;
|
||||
@@ -97,10 +103,10 @@ export default async function bisect(client: Client): Promise<number> {
|
||||
}
|
||||
|
||||
if (!subpath) {
|
||||
subpath = await prompt(
|
||||
client,
|
||||
`Specify the URL subpath where the bug occurs:`
|
||||
);
|
||||
subpath = await client.input.text({
|
||||
message: `Specify the URL subpath where the bug occurs:`,
|
||||
validate: val => (val ? true : 'A subpath must be provided'),
|
||||
});
|
||||
}
|
||||
|
||||
output.spinner('Retrieving deployments…');
|
||||
@@ -335,15 +341,3 @@ function getCommit(deployment: Deployment) {
|
||||
deployment.meta?.bitbucketCommitMessage;
|
||||
return { sha, message };
|
||||
}
|
||||
|
||||
async function prompt(client: Client, message: string): Promise<string> {
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
const val = await client.input.text({ message });
|
||||
if (val) {
|
||||
return val;
|
||||
} else {
|
||||
client.output.error('A value must be specified');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +169,7 @@ export default async (client: Client): Promise<number> => {
|
||||
const quiet = !client.stdout.isTTY;
|
||||
|
||||
let { path: cwd } = pathValidation;
|
||||
console.log('deploy', { cwd });
|
||||
const autoConfirm = argv['--yes'];
|
||||
|
||||
// deprecate --name
|
||||
@@ -208,6 +209,7 @@ export default async (client: Client): Promise<number> => {
|
||||
|
||||
// retrieve `project` and `org` from .vercel
|
||||
const link = await getLinkedProject(client, cwd);
|
||||
console.log(link);
|
||||
|
||||
if (link.status === 'error') {
|
||||
return link.exitCode;
|
||||
|
||||
@@ -7,7 +7,7 @@ import getDomainPrice from '../../util/domains/get-domain-price';
|
||||
import getDomainStatus from '../../util/domains/get-domain-status';
|
||||
import getScope from '../../util/get-scope';
|
||||
import param from '../../util/output/param';
|
||||
import promptBool from '../../util/input/prompt-bool';
|
||||
import confirm from '../../util/input/confirm';
|
||||
import purchaseDomain from '../../util/domains/purchase-domain';
|
||||
import stamp from '../../util/output/stamp';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
@@ -86,23 +86,25 @@ export default async function buy(
|
||||
autoRenew = true;
|
||||
} else {
|
||||
if (
|
||||
!(await promptBool(
|
||||
!(await confirm(
|
||||
client,
|
||||
`Buy now for ${chalk.bold(`$${price}`)} (${`${period}yr${
|
||||
period > 1 ? 's' : ''
|
||||
}`})?`,
|
||||
client
|
||||
false
|
||||
))
|
||||
) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
autoRenew = await promptBool(
|
||||
autoRenew = await confirm(
|
||||
client,
|
||||
renewalPrice.period === 1
|
||||
? `Auto renew yearly for ${chalk.bold(`$${price}`)}?`
|
||||
: `Auto renew every ${renewalPrice.period} years for ${chalk.bold(
|
||||
`$${price}`
|
||||
)}?`,
|
||||
{ ...client, defaultValue: true }
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import textInput from '../../util/input/text';
|
||||
import param from '../../util/output/param';
|
||||
import getDomainAliases from '../../util/alias/get-domain-aliases';
|
||||
import getDomainByName from '../../util/domains/get-domain-by-name';
|
||||
import promptBool from '../../util/input/prompt-bool';
|
||||
import confirm from '../../util/input/confirm';
|
||||
import getTeams from '../../util/teams/get-teams';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
|
||||
@@ -67,11 +67,12 @@ export default async function move(
|
||||
)} will have 24 hours to accept your move request before it expires.`
|
||||
);
|
||||
if (
|
||||
!(await promptBool(
|
||||
!(await confirm(
|
||||
client,
|
||||
`Are you sure you want to move ${param(domainName)} to ${param(
|
||||
destination
|
||||
)}?`,
|
||||
client
|
||||
false
|
||||
))
|
||||
) {
|
||||
output.log('Canceled');
|
||||
@@ -88,9 +89,10 @@ export default async function move(
|
||||
)} will be removed. Run ${getCommandName(`alias ls`)} to list them.`
|
||||
);
|
||||
if (
|
||||
!(await promptBool(
|
||||
!(await confirm(
|
||||
client,
|
||||
`Are you sure you want to move ${param(domainName)}?`,
|
||||
client
|
||||
false
|
||||
))
|
||||
) {
|
||||
output.log('Canceled');
|
||||
|
||||
@@ -13,7 +13,7 @@ import removeDomainByName from '../../util/domains/remove-domain-by-name';
|
||||
import stamp from '../../util/output/stamp';
|
||||
import * as ERRORS from '../../util/errors-ts';
|
||||
import param from '../../util/output/param';
|
||||
import promptBool from '../../util/input/prompt-bool';
|
||||
import confirm from '../../util/input/confirm';
|
||||
import setCustomSuffix from '../../util/domains/set-custom-suffix';
|
||||
import { findProjectsForDomain } from '../../util/projects/find-projects-for-domain';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
@@ -81,9 +81,10 @@ export default async function rm(
|
||||
const skipConfirmation = opts['--yes'] || false;
|
||||
if (
|
||||
!skipConfirmation &&
|
||||
!(await promptBool(
|
||||
!(await confirm(
|
||||
client,
|
||||
`Are you sure you want to remove ${param(domainName)}?`,
|
||||
client
|
||||
false
|
||||
))
|
||||
) {
|
||||
output.log('Canceled');
|
||||
@@ -222,7 +223,11 @@ async function removeDomain(
|
||||
|
||||
if (
|
||||
!skipConfirmation &&
|
||||
!(await promptBool(`Remove conflicts associated with domain?`, client))
|
||||
!(await confirm(
|
||||
client,
|
||||
`Remove conflicts associated with domain?`,
|
||||
false
|
||||
))
|
||||
) {
|
||||
output.log('Canceled');
|
||||
return 0;
|
||||
|
||||
@@ -9,7 +9,7 @@ import stamp from '../../util/output/stamp';
|
||||
import getAuthCode from '../../util/domains/get-auth-code';
|
||||
import getDomainPrice from '../../util/domains/get-domain-price';
|
||||
import checkTransfer from '../../util/domains/check-transfer';
|
||||
import promptBool from '../../util/input/prompt-bool';
|
||||
import confirm from '../../util/input/confirm';
|
||||
import isRootDomain from '../../util/is-root-domain';
|
||||
import { getCommandName } from '../../util/pkg-name';
|
||||
|
||||
@@ -67,11 +67,12 @@ export default async function transferIn(
|
||||
|
||||
const authCode = await getAuthCode(opts['--code']);
|
||||
|
||||
const shouldTransfer = await promptBool(
|
||||
const shouldTransfer = await confirm(
|
||||
client,
|
||||
transferPolicy === 'no-change'
|
||||
? `Transfer now for ${chalk.bold(`$${price}`)}?`
|
||||
: `Transfer now with 1yr renewal for ${chalk.bold(`$${price}`)}?`,
|
||||
client
|
||||
false
|
||||
);
|
||||
if (!shouldTransfer) {
|
||||
return 0;
|
||||
|
||||
14
packages/cli/src/commands/env/add.ts
vendored
14
packages/cli/src/commands/env/add.ts
vendored
@@ -63,14 +63,11 @@ export default async function add(
|
||||
envTargets.push(envTargetArg);
|
||||
}
|
||||
|
||||
while (!envName) {
|
||||
if (!envName) {
|
||||
envName = await client.input.text({
|
||||
message: `What’s the name of the variable?`,
|
||||
validate: val => (val ? true : 'Name cannot be empty'),
|
||||
});
|
||||
|
||||
if (!envName) {
|
||||
output.error('Name cannot be empty');
|
||||
}
|
||||
}
|
||||
|
||||
const { envs } = await getEnvRecords(
|
||||
@@ -100,11 +97,9 @@ export default async function add(
|
||||
if (stdInput) {
|
||||
envValue = stdInput;
|
||||
} else {
|
||||
const inputValue = await client.input.text({
|
||||
envValue = await client.input.text({
|
||||
message: `What’s the value of ${envName}?`,
|
||||
});
|
||||
|
||||
envValue = inputValue || '';
|
||||
}
|
||||
|
||||
while (envTargets.length === 0) {
|
||||
@@ -124,10 +119,9 @@ export default async function add(
|
||||
envTargets.length === 1 &&
|
||||
envTargets[0] === 'preview'
|
||||
) {
|
||||
const inputValue = await client.input.text({
|
||||
envGitBranch = await client.input.text({
|
||||
message: `Add ${envName} to which Git branch? (leave empty for all Preview branches)?`,
|
||||
});
|
||||
envGitBranch = inputValue || '';
|
||||
}
|
||||
|
||||
const type = opts['--sensitive'] ? 'sensitive' : 'encrypted';
|
||||
|
||||
12
packages/cli/src/commands/env/rm.ts
vendored
12
packages/cli/src/commands/env/rm.ts
vendored
@@ -40,17 +40,11 @@ export default async function rm(
|
||||
|
||||
let [envName, envTarget, envGitBranch] = args;
|
||||
|
||||
while (!envName) {
|
||||
const inputName = await client.input.text({
|
||||
if (!envName) {
|
||||
envName = await client.input.text({
|
||||
message: `What’s the name of the variable?`,
|
||||
validate: val => (val ? true : 'Name cannot be empty'),
|
||||
});
|
||||
|
||||
if (!inputName) {
|
||||
output.error(`Name cannot be empty`);
|
||||
continue;
|
||||
}
|
||||
|
||||
envName = inputName;
|
||||
}
|
||||
|
||||
if (!isValidEnvTarget(envTarget)) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import chalk from 'chalk';
|
||||
// @ts-ignore
|
||||
import listInput from '../../util/input/list';
|
||||
import listItem from '../../util/output/list-item';
|
||||
import promptBool from '../../util/input/prompt-bool';
|
||||
import confirm from '../../util/input/confirm';
|
||||
import toHumanPath from '../../util/humanize-path';
|
||||
import Client from '../../util/client';
|
||||
import info from '../../util/output/info';
|
||||
@@ -46,6 +46,10 @@ export default async function init(
|
||||
const exampleList = examples.filter(x => x.visible).map(x => x.name);
|
||||
|
||||
if (!name) {
|
||||
if (client.stdin.isTTY !== true) {
|
||||
client.output.print(`No framework provided`);
|
||||
return 0;
|
||||
}
|
||||
const chosen = await chooseFromDropdown(
|
||||
client,
|
||||
'Select example:',
|
||||
@@ -122,7 +126,7 @@ async function extractExample(
|
||||
ver: string = 'v2'
|
||||
) {
|
||||
const { output } = client;
|
||||
const folder = prepareFolder(process.cwd(), dir || name, force);
|
||||
const folder = prepareFolder(client.cwd, dir || name, force);
|
||||
output.spinner(`Fetching ${name}`);
|
||||
|
||||
const url = `${EXAMPLE_API}/${ver}/download/${name}.tar.gz`;
|
||||
@@ -147,7 +151,7 @@ async function extractExample(
|
||||
const successLog = `Initialized "${chalk.bold(
|
||||
name
|
||||
)}" example in ${chalk.bold(toHumanPath(folder))}.`;
|
||||
const folderRel = path.relative(process.cwd(), folder);
|
||||
const folderRel = path.relative(client.cwd, folder);
|
||||
const deployHint =
|
||||
folderRel === ''
|
||||
? listItem(`To deploy, run ${getCommandName()}.`)
|
||||
@@ -209,14 +213,14 @@ async function guess(client: Client, exampleList: string[], name: string) {
|
||||
)} to see the list of available examples.`
|
||||
);
|
||||
|
||||
if (process.stdout.isTTY !== true) {
|
||||
if (client.stdin.isTTY !== true) {
|
||||
throw GuessError;
|
||||
}
|
||||
|
||||
const found = didYouMean(name, exampleList, 0.7);
|
||||
|
||||
if (typeof found === 'string') {
|
||||
if (await promptBool(`Did you mean ${chalk.bold(found)}?`, client)) {
|
||||
if (await confirm(client, `Did you mean ${chalk.bold(found)}?`, false)) {
|
||||
return found;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -32,6 +32,12 @@ export default async function requestPromote({
|
||||
output: client.output,
|
||||
});
|
||||
|
||||
if (deployment.target !== 'production') {
|
||||
output.warn(
|
||||
'Promoting a preview deployment to production is deprecated and will be removed in the next major release. This behavior will be removed entirely on 2024-05-03.'
|
||||
);
|
||||
}
|
||||
|
||||
if (deployment.target !== 'production' && !yes) {
|
||||
const question =
|
||||
'This deployment does not target production, therefore promotion will not apply production environment variables. Are you sure you want to continue?';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import chalk from 'chalk';
|
||||
import type { DNSRecordData } from '@vercel-internals/types';
|
||||
import textInput from '../input/text';
|
||||
import promptBool from '../input/prompt-bool';
|
||||
import confirm from '../input/confirm';
|
||||
import Client from '../client';
|
||||
|
||||
const RECORD_TYPES = ['A', 'AAAA', 'ALIAS', 'CAA', 'CNAME', 'MX', 'SRV', 'TXT'];
|
||||
@@ -89,7 +89,7 @@ export default async function getDNSData(
|
||||
}
|
||||
|
||||
async function verifyData(client: Client) {
|
||||
return promptBool('Is this correct?', client);
|
||||
return confirm(client, 'Is this correct?', false);
|
||||
}
|
||||
|
||||
async function getRecordName(type: string) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import Client from '../client';
|
||||
import eraseLines from '../output/erase-lines';
|
||||
import getDomainPrice from './get-domain-price';
|
||||
import getDomainStatus from './get-domain-status';
|
||||
import promptBool from '../input/prompt-bool';
|
||||
import confirm from '../input/confirm';
|
||||
import purchaseDomain from './purchase-domain';
|
||||
import stamp from '../output/stamp';
|
||||
import * as ERRORS from '../errors-ts';
|
||||
@@ -51,11 +51,12 @@ export default async function purchaseDomainIfAvailable(
|
||||
);
|
||||
|
||||
if (
|
||||
!(await promptBool(
|
||||
!(await confirm(
|
||||
client,
|
||||
`Buy ${chalk.underline(domain)} for ${chalk.bold(
|
||||
`$${price}`
|
||||
)} (${plural('yr', period, true)})?`,
|
||||
client
|
||||
false
|
||||
))
|
||||
) {
|
||||
output.print(eraseLines(1));
|
||||
|
||||
@@ -17,6 +17,10 @@ export default function handleError(error: unknown, { debug = false } = {}) {
|
||||
console.log(`> [debug] handling error: ${stack}`);
|
||||
}
|
||||
|
||||
if (message === 'User force closed the prompt with 0 null') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === 403) {
|
||||
console.error(
|
||||
errorOutput(
|
||||
|
||||
@@ -75,64 +75,37 @@ export default async function inputProject(
|
||||
|
||||
if (shouldLinkProject) {
|
||||
// user wants to link a project
|
||||
let project: Project | ProjectNotFound | null = null;
|
||||
|
||||
while (!project || project instanceof ProjectNotFound) {
|
||||
const projectName = await client.input.text({
|
||||
message: 'What’s the name of your existing project?',
|
||||
});
|
||||
|
||||
if (!projectName) {
|
||||
output.error(`Project name cannot be empty`);
|
||||
continue;
|
||||
}
|
||||
|
||||
output.spinner('Verifying project name…', 1000);
|
||||
try {
|
||||
project = await getProjectByIdOrName(client, projectName, org.id);
|
||||
} finally {
|
||||
output.stopSpinner();
|
||||
}
|
||||
|
||||
if (project instanceof ProjectNotFound) {
|
||||
output.error(`Project not found`);
|
||||
}
|
||||
}
|
||||
|
||||
return project;
|
||||
let toLink: Project;
|
||||
await client.input.text({
|
||||
message: 'What’s the name of your existing project?',
|
||||
validate: async val => {
|
||||
if (!val) {
|
||||
return 'Project name cannot be empty';
|
||||
}
|
||||
const project = await getProjectByIdOrName(client, val, org.id);
|
||||
if (project instanceof ProjectNotFound) {
|
||||
return 'Project not found';
|
||||
}
|
||||
toLink = project;
|
||||
return true;
|
||||
},
|
||||
});
|
||||
return toLink!;
|
||||
}
|
||||
|
||||
// user wants to create a new project
|
||||
let newProjectName: string | null = null;
|
||||
|
||||
while (!newProjectName) {
|
||||
newProjectName = await client.input.text({
|
||||
message: `What’s your project’s name?`,
|
||||
default: !detectedProject ? slugifiedName : undefined,
|
||||
});
|
||||
|
||||
if (!newProjectName) {
|
||||
output.error(`Project name cannot be empty`);
|
||||
continue;
|
||||
}
|
||||
|
||||
output.spinner('Verifying project name…', 1000);
|
||||
let existingProject: Project | ProjectNotFound;
|
||||
try {
|
||||
existingProject = await getProjectByIdOrName(
|
||||
client,
|
||||
newProjectName,
|
||||
org.id
|
||||
);
|
||||
} finally {
|
||||
output.stopSpinner();
|
||||
}
|
||||
|
||||
if (existingProject && !(existingProject instanceof ProjectNotFound)) {
|
||||
output.print(`Project already exists`);
|
||||
newProjectName = null;
|
||||
}
|
||||
}
|
||||
|
||||
return newProjectName;
|
||||
return await client.input.text({
|
||||
message: `What’s your project’s name?`,
|
||||
default: !detectedProject ? slugifiedName : undefined,
|
||||
validate: async val => {
|
||||
if (!val) {
|
||||
return 'Project name cannot be empty';
|
||||
}
|
||||
const project = await getProjectByIdOrName(client, val, org.id);
|
||||
if (!(project instanceof ProjectNotFound)) {
|
||||
return 'Project already exists';
|
||||
}
|
||||
return true;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
import chalk from 'chalk';
|
||||
import type { ReadableTTY, WritableTTY } from '@vercel-internals/types';
|
||||
|
||||
type Options = {
|
||||
abortSequences?: Set<string>;
|
||||
defaultValue?: boolean;
|
||||
noChar?: string;
|
||||
resolveChars?: Set<string>;
|
||||
stdin: ReadableTTY;
|
||||
stdout: WritableTTY;
|
||||
trailing?: string;
|
||||
yesChar?: string;
|
||||
};
|
||||
|
||||
export default async function promptBool(label: string, options: Options) {
|
||||
const {
|
||||
stdin,
|
||||
stdout,
|
||||
defaultValue = false,
|
||||
abortSequences = new Set(['\u0003']),
|
||||
resolveChars = new Set(['\r']),
|
||||
yesChar = 'y',
|
||||
noChar = 'n',
|
||||
trailing = '',
|
||||
} = options;
|
||||
|
||||
return new Promise<boolean>(resolve => {
|
||||
const isRaw = Boolean(stdin && stdin.isRaw);
|
||||
|
||||
if (stdin) {
|
||||
if (stdin.setRawMode) {
|
||||
stdin.setRawMode(true);
|
||||
}
|
||||
|
||||
stdin.resume();
|
||||
}
|
||||
|
||||
function restore() {
|
||||
stdout.write(trailing);
|
||||
|
||||
if (stdin) {
|
||||
if (stdin.setRawMode) {
|
||||
stdin.setRawMode(isRaw);
|
||||
}
|
||||
|
||||
stdin.pause();
|
||||
stdin.removeListener('data', onData);
|
||||
}
|
||||
}
|
||||
|
||||
function onData(buffer: Buffer) {
|
||||
const data = buffer.toString();
|
||||
if (data[0].toLowerCase() === yesChar) {
|
||||
restore();
|
||||
stdout.write(`\n`);
|
||||
resolve(true);
|
||||
} else if (data[0].toLowerCase() === noChar) {
|
||||
stdout.write(`\n`);
|
||||
restore();
|
||||
resolve(false);
|
||||
} else if (abortSequences.has(data)) {
|
||||
stdout.write(`\n`);
|
||||
restore();
|
||||
resolve(false);
|
||||
} else if (resolveChars.has(data[0])) {
|
||||
stdout.write(`\n`);
|
||||
restore();
|
||||
resolve(defaultValue);
|
||||
} else {
|
||||
// ignore extraneous input
|
||||
}
|
||||
}
|
||||
|
||||
const defaultText =
|
||||
defaultValue === null
|
||||
? `[${yesChar}|${noChar}]`
|
||||
: defaultValue
|
||||
? `[${chalk.bold(yesChar.toUpperCase())}|${noChar}]`
|
||||
: `[${yesChar}|${chalk.bold(noChar.toUpperCase())}]`;
|
||||
stdout.write(`${chalk.gray('>')} ${label} ${chalk.gray(defaultText)} `);
|
||||
|
||||
if (stdin) {
|
||||
stdin.on('data', onData);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -182,7 +182,7 @@ test(
|
||||
test(
|
||||
'[vercel dev] Should support `*.go` API serverless functions with `go.work` and lib',
|
||||
testFixtureStdio('go-work-with-shared', async (testPath: any) => {
|
||||
await testPath(200, `/api`, 'hello:go1.20.2');
|
||||
await testPath(200, `/api`, 'hello:go1.20.14');
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
116
packages/cli/test/integration-3.test.ts
vendored
116
packages/cli/test/integration-3.test.ts
vendored
@@ -9,7 +9,7 @@ import { runNpmInstall } from '@vercel/build-utils';
|
||||
import { execCli } from './helpers/exec';
|
||||
import fetch, { RequestInit, RequestInfo } from 'node-fetch';
|
||||
import retry from 'async-retry';
|
||||
import fs, { ensureDir } from 'fs-extra';
|
||||
import fs from 'fs-extra';
|
||||
import { logo } from '../src/util/pkg-name';
|
||||
import sleep from '../src/util/sleep';
|
||||
import humanizePath from '../src/util/humanize-path';
|
||||
@@ -38,8 +38,6 @@ const deployHelpMessage = `${logo} vercel [options] <command | path>`;
|
||||
let session = 'temp-session';
|
||||
let secretName: string | undefined;
|
||||
|
||||
const createFile = (dest: fs.PathLike) => fs.closeSync(fs.openSync(dest, 'w'));
|
||||
|
||||
function fetchTokenInformation(token: string, retries = 3) {
|
||||
const url = `https://api.vercel.com/v2/user`;
|
||||
const headers = { Authorization: `Bearer ${token}` };
|
||||
@@ -879,118 +877,6 @@ test('initialize example "angular"', async () => {
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('initialize example ("angular") to specified directory', async () => {
|
||||
const cwd = getNewTmpDir();
|
||||
const goal = '> Success! Initialized "angular" example in';
|
||||
|
||||
const { exitCode, stdout, stderr } = await execCli(
|
||||
binaryPath,
|
||||
['init', 'angular', 'ang'],
|
||||
{
|
||||
cwd,
|
||||
}
|
||||
);
|
||||
|
||||
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
|
||||
expect(stderr).toContain(goal);
|
||||
|
||||
expect(
|
||||
fs.existsSync(path.join(cwd, 'ang', 'package.json')),
|
||||
'package.json'
|
||||
).toBe(true);
|
||||
expect(
|
||||
fs.existsSync(path.join(cwd, 'ang', 'tsconfig.json')),
|
||||
'tsconfig.json'
|
||||
).toBe(true);
|
||||
expect(
|
||||
fs.existsSync(path.join(cwd, 'ang', 'angular.json')),
|
||||
'angular.json'
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('initialize example to existing directory with "-f"', async () => {
|
||||
const cwd = getNewTmpDir();
|
||||
const goal = '> Success! Initialized "angular" example in';
|
||||
|
||||
await ensureDir(path.join(cwd, 'angular'));
|
||||
createFile(path.join(cwd, 'angular', '.gitignore'));
|
||||
const { exitCode, stdout, stderr } = await execCli(
|
||||
binaryPath,
|
||||
['init', 'angular', '-f'],
|
||||
{
|
||||
cwd,
|
||||
}
|
||||
);
|
||||
|
||||
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
|
||||
expect(stderr).toContain(goal);
|
||||
|
||||
expect(
|
||||
fs.existsSync(path.join(cwd, 'angular', 'package.json')),
|
||||
'package.json'
|
||||
).toBe(true);
|
||||
expect(
|
||||
fs.existsSync(path.join(cwd, 'angular', 'tsconfig.json')),
|
||||
'tsconfig.json'
|
||||
).toBe(true);
|
||||
expect(
|
||||
fs.existsSync(path.join(cwd, 'angular', 'angular.json')),
|
||||
'angular.json'
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
test('try to initialize example to existing directory', async () => {
|
||||
const cwd = getNewTmpDir();
|
||||
const goal =
|
||||
'Error: Destination path "angular" already exists and is not an empty directory. You may use `--force` or `-f` to override it.';
|
||||
|
||||
await ensureDir(path.join(cwd, 'angular'));
|
||||
createFile(path.join(cwd, 'angular', '.gitignore'));
|
||||
const { exitCode, stdout, stderr } = await execCli(
|
||||
binaryPath,
|
||||
['init', 'angular'],
|
||||
{
|
||||
cwd,
|
||||
input: '\n',
|
||||
}
|
||||
);
|
||||
|
||||
expect(exitCode, formatOutput({ stdout, stderr })).toBe(1);
|
||||
expect(stderr).toContain(goal);
|
||||
});
|
||||
|
||||
test('try to initialize misspelled example (noce) in non-tty', async () => {
|
||||
const cwd = getNewTmpDir();
|
||||
const goal =
|
||||
'Error: No example found for noce, run `vercel init` to see the list of available examples.';
|
||||
|
||||
const { stdout, stderr, exitCode } = await execCli(
|
||||
binaryPath,
|
||||
['init', 'noce'],
|
||||
{ cwd }
|
||||
);
|
||||
|
||||
expect(exitCode, formatOutput({ stdout, stderr })).toBe(1);
|
||||
expect(stderr).toContain(goal);
|
||||
});
|
||||
|
||||
test('try to initialize example "example-404"', async () => {
|
||||
const cwd = getNewTmpDir();
|
||||
const goal =
|
||||
'Error: No example found for example-404, run `vercel init` to see the list of available examples.';
|
||||
|
||||
const { exitCode, stdout, stderr } = await execCli(
|
||||
binaryPath,
|
||||
['init', 'example-404'],
|
||||
{
|
||||
cwd,
|
||||
}
|
||||
);
|
||||
|
||||
expect(exitCode, formatOutput({ stdout, stderr })).toBe(1);
|
||||
expect(stderr).toContain(goal);
|
||||
});
|
||||
|
||||
test('fail to add a domain without a project', async () => {
|
||||
const output = await execCli(binaryPath, [
|
||||
'domains',
|
||||
|
||||
BIN
packages/cli/test/mocks/example-list-tars/astro.tar.gz
Normal file
BIN
packages/cli/test/mocks/example-list-tars/astro.tar.gz
Normal file
Binary file not shown.
3
packages/cli/test/mocks/example-list-tars/readme.md
Normal file
3
packages/cli/test/mocks/example-list-tars/readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
These mock the example-list server used during `init`. To make a new one, simply download the source in your browser.
|
||||
|
||||
Eg. visit `https://now-example-files.zeit.sh/v2/download/astro.tar.gz` and copy the download intro this directory.
|
||||
278
packages/cli/test/unit/commands/init.test.ts
Executable file
278
packages/cli/test/unit/commands/init.test.ts
Executable file
@@ -0,0 +1,278 @@
|
||||
import init from '../../../src/commands/init';
|
||||
import { client } from '../../mocks/client';
|
||||
import { setupTmpDir } from '../../helpers/setup-unit-fixture';
|
||||
import { FetchOptions } from '../../../src/util/client';
|
||||
import fs from 'fs-extra';
|
||||
import { Response } from 'node-fetch';
|
||||
import { join } from 'path';
|
||||
import { beforeEach, describe, it, expect, vi } from 'vitest';
|
||||
import type { MockInstance } from 'vitest';
|
||||
|
||||
// path to mock tar
|
||||
const mockPath = join(
|
||||
process.cwd(),
|
||||
'test',
|
||||
'mocks',
|
||||
'example-list-tars',
|
||||
'astro.tar.gz'
|
||||
);
|
||||
|
||||
let mock: MockInstance<
|
||||
[url: string, opts?: FetchOptions | undefined],
|
||||
Promise<unknown>
|
||||
>;
|
||||
beforeEach(() => {
|
||||
// The examples list endpoint comes from an API that we don't typically mock
|
||||
mock = vi.spyOn(client, 'fetch').mockImplementation(async url => {
|
||||
const url2 = new URL(url);
|
||||
if (url2.pathname === '/v2/list.json') {
|
||||
return Promise.resolve([
|
||||
{ name: 'angular', visible: true, suggestions: [] },
|
||||
{ name: 'astro', visible: true, suggestions: [] },
|
||||
]);
|
||||
}
|
||||
if (url2.pathname === '/v2/download/astro.tar.gz') {
|
||||
return new Response(fs.createReadStream(mockPath), {
|
||||
status: 200,
|
||||
});
|
||||
}
|
||||
throw new Error(`Unexpected fetch request for url ${url}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('init', () => {
|
||||
it('should allow selecting a framework to download the source into the expected folder', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
client.stdin.write('\x1B[B'); // Down arrow
|
||||
client.stdin.write('\r'); // Return key to select astro
|
||||
|
||||
await expect(client.stderr).toOutput(`Fetching astro`);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Success! Initialized "astro" example`
|
||||
);
|
||||
|
||||
const promiseResult = await exitCodePromise;
|
||||
expect(promiseResult).toEqual(0);
|
||||
const contents = await fs.readdirSync(join(cwd, 'astro'));
|
||||
expect(contents).toContain('package.json');
|
||||
});
|
||||
describe('when stdin is not a TTY', () => {
|
||||
it('should exit 0 with a helpful message when no framework argument is provided', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.stdin.isTTY = false;
|
||||
client.cwd = cwd;
|
||||
|
||||
client.setArgv('init');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(`No framework provided`);
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
});
|
||||
it('should exit 1 with a helpful message when the framework isnt found', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.stdin.isTTY = false;
|
||||
client.cwd = cwd;
|
||||
|
||||
client.setArgv('init', 'astroz');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(`No example found`);
|
||||
await expect(exitCodePromise).resolves.toEqual(1);
|
||||
});
|
||||
});
|
||||
describe('providing the framework argument', () => {
|
||||
it('should succeed', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
client.setArgv('init', 'astro');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(`Fetching astro`);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
|
||||
const promiseResult = await exitCodePromise;
|
||||
expect(promiseResult).toEqual(0);
|
||||
|
||||
const contents = await fs.readdirSync(join(cwd, 'astro'));
|
||||
expect(contents).toContain('package.json');
|
||||
expect(contents).toContain('astro.config.mjs');
|
||||
});
|
||||
it('should succeed when specifying a target directory', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
const targetDirectory = 'my-astro';
|
||||
|
||||
client.setArgv('init', 'astro', targetDirectory);
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(`Fetching astro`);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
|
||||
const promiseResult = await exitCodePromise;
|
||||
expect(promiseResult).toEqual(0);
|
||||
|
||||
const contents = await fs.readdirSync(join(cwd, targetDirectory));
|
||||
expect(contents).toContain('package.json');
|
||||
expect(contents).toContain('astro.config.mjs');
|
||||
});
|
||||
it('should fail when a file matching the framework already exists in the target location', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
// Create a file at the expected destination...
|
||||
await fs.outputFile(
|
||||
join(cwd, 'astro'),
|
||||
JSON.stringify({ name: 'some-package' })
|
||||
);
|
||||
|
||||
client.setArgv('init', 'astro');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Destination path "astro" already exists and is not a directory.`
|
||||
);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
await expect(exitCodePromise).resolves.toEqual(1);
|
||||
});
|
||||
it('should fail when a non-empty folder matching the framework already exists in the target location', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
// Create a folder with some content at the expected destination...
|
||||
await fs.outputFile(
|
||||
join(cwd, 'astro', 'package.json'),
|
||||
JSON.stringify({ name: 'some-package' })
|
||||
);
|
||||
|
||||
client.setArgv('init', 'astro');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Destination path "astro" already exists and is not an empty directory`
|
||||
);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
await expect(exitCodePromise).resolves.toEqual(1);
|
||||
});
|
||||
it('should succeed when an empty folder matching the framework already exists in the target location', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
await fs.mkdirSync(join(cwd, 'astro'));
|
||||
client.setArgv('init', 'astro');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(`Fetching astro`);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
|
||||
const promiseResult = await exitCodePromise;
|
||||
expect(promiseResult).toEqual(0);
|
||||
|
||||
const contents = await fs.readdirSync(join(cwd, 'astro'));
|
||||
expect(contents).toContain('package.json');
|
||||
});
|
||||
it("should fail when providing the framework argument which is so incorrect that it can't be guessed", async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
const frameworkName = 'some-unguessable-framework-name';
|
||||
client.setArgv('init', frameworkName);
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`No example found for ${frameworkName}, run \`vercel init\` to see the list of available examples.`
|
||||
);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
await expect(exitCodePromise).resolves.toEqual(1);
|
||||
});
|
||||
describe('using --force', () => {
|
||||
it('should fail when a file matching the framework already exists in the target location', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
// Create a file at the expected destination...
|
||||
await fs.outputFile(
|
||||
join(cwd, 'astro'),
|
||||
JSON.stringify({ name: 'some-package' })
|
||||
);
|
||||
|
||||
client.setArgv('init', 'astro', '--force');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Destination path "astro" already exists and is not a directory.`
|
||||
);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
await expect(exitCodePromise).resolves.toEqual(1);
|
||||
});
|
||||
it('should succeed when a non-empty folder matching the framework already exists in the target location', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
// Create a folder with some content at the expected destination...
|
||||
await fs.outputFile(
|
||||
join(cwd, 'astro', 'package.json'),
|
||||
JSON.stringify({ name: 'some-package' })
|
||||
);
|
||||
|
||||
client.stderr.pipe(process.stderr);
|
||||
client.setArgv('init', 'astro', '--force');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput(
|
||||
`Success! Initialized "astro" example`
|
||||
);
|
||||
|
||||
const promiseResult = await exitCodePromise;
|
||||
expect(promiseResult).toEqual(0);
|
||||
|
||||
const contents = await fs.readdirSync(join(cwd, 'astro'));
|
||||
expect(contents).toContain('package.json');
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('triggering the guess prompt with by incorrectly spelling "astroz"', () => {
|
||||
it('should succeed when accepting the suggestion', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
client.setArgv('init', 'astroz');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput('? Did you mean astro? (y/N)');
|
||||
client.stdin.write('y');
|
||||
client.stdin.write('\r'); // Return key
|
||||
|
||||
await expect(client.stderr).toOutput(`Fetching astro`);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
|
||||
const promiseResult = await exitCodePromise;
|
||||
expect(promiseResult).toEqual(0);
|
||||
|
||||
const contents = await fs.readdirSync(join(cwd, 'astro'));
|
||||
expect(contents).toContain('package.json');
|
||||
});
|
||||
it('should fail when rejecting the suggestion', async () => {
|
||||
const cwd = setupTmpDir();
|
||||
client.cwd = cwd;
|
||||
|
||||
client.setArgv('init', 'astroz');
|
||||
const exitCodePromise = init(client);
|
||||
|
||||
await expect(client.stderr).toOutput('? Did you mean astro? (y/N)');
|
||||
|
||||
client.stdin.write('\r'); // Return key
|
||||
await expect(client.stderr).toOutput(`> No changes made`);
|
||||
expect(mock).toHaveBeenCalled();
|
||||
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -121,9 +121,8 @@ export default function buildCreateDeployment() {
|
||||
err.code === 'ENOENT' &&
|
||||
err.path
|
||||
) {
|
||||
const errPath = relative(workPath, err.path);
|
||||
err.message = `File does not exist: "${relative(workPath, errPath)}"`;
|
||||
if (errPath.split(sep).includes('node_modules')) {
|
||||
err.message = `File does not exist: "${err.path}"`;
|
||||
if (err.path.split(sep).includes('node_modules')) {
|
||||
err.message = `Please ensure project dependencies have been installed:\n${err.message}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,7 @@ export async function buildFileTree(
|
||||
fileList = await readdir(path, [ignores]);
|
||||
|
||||
if (prebuilt) {
|
||||
console.log('buildFileTree:', { path, vercelOutputDir });
|
||||
// Traverse over the `.vc-config.json` files and include
|
||||
// the files referenced by the "filePathMap" properties
|
||||
const refs = new Set<string>();
|
||||
|
||||
@@ -22,9 +22,10 @@ import type { Env } from '@vercel/build-utils';
|
||||
const streamPipeline = promisify(pipeline);
|
||||
|
||||
const versionMap = new Map([
|
||||
['1.21', '1.21.1'],
|
||||
['1.20', '1.20.2'],
|
||||
['1.19', '1.19.6'],
|
||||
['1.22', '1.22.2'],
|
||||
['1.21', '1.21.8'],
|
||||
['1.20', '1.20.14'],
|
||||
['1.19', '1.19.13'],
|
||||
['1.18', '1.18.10'],
|
||||
['1.17', '1.17.13'],
|
||||
['1.16', '1.16.15'],
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
{ "src": "subdirectory/index.go", "use": "@vercel/go" }
|
||||
],
|
||||
"probes": [
|
||||
{ "path": "/", "mustContain": "cow:go1.21.1:RANDOMNESS_PLACEHOLDER" },
|
||||
{ "path": "/", "mustContain": "cow:go1.22.2:RANDOMNESS_PLACEHOLDER" },
|
||||
{
|
||||
"path": "/subdirectory",
|
||||
"mustContain": "subcow:go1.21.1:RANDOMNESS_PLACEHOLDER"
|
||||
"mustContain": "subcow:go1.22.2:RANDOMNESS_PLACEHOLDER"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"version": 2,
|
||||
"builds": [{ "src": "index.go", "use": "@vercel/go" }],
|
||||
"probes": [
|
||||
{ "path": "/", "mustContain": "version:go1.19.6:RANDOMNESS_PLACEHOLDER" }
|
||||
{ "path": "/", "mustContain": "version:go1.19.13:RANDOMNESS_PLACEHOLDER" }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"probes": [
|
||||
{
|
||||
"path": "/api/index.go",
|
||||
"mustContain": "hello:go1.20.2"
|
||||
"mustContain": "hello:go1.20.14"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global Response */
|
||||
/* eslint-disable */
|
||||
|
||||
import B from 'node:buffer';
|
||||
import { Buffer } from 'buffer';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global Response */
|
||||
/* eslint-disable -- flakey application of `global Response` eslint directive */
|
||||
|
||||
export const config = { runtime: 'edge' };
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/*global TextEncoderStream, ReadableStream, Response, WebSocket */
|
||||
/* eslint-disable -- flakey application of `global TextEncoderStream, ReadableStream, Response, WebSocket` eslint directive */
|
||||
|
||||
export const config = { runtime: 'edge' };
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global ReadableStream, TextEncoderStream, Response */
|
||||
/* eslint-disable -- flakey application of `global ReadableStream, TextEncoderStream, Response` eslint directive */
|
||||
|
||||
export const config = { runtime: 'edge' };
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global ReadableStream, TextEncoderStream, Response */
|
||||
/* eslint-disable -- flakey application of `global ReadableStream, TextEncoderStream, Response` eslint directive */
|
||||
|
||||
const DEFER_MS = 10;
|
||||
|
||||
|
||||
62
packages/static-build/test/fixtures/ionic-react-v7/package-lock.json
generated
vendored
62
packages/static-build/test/fixtures/ionic-react-v7/package-lock.json
generated
vendored
@@ -8,7 +8,7 @@
|
||||
"name": "50-ionic-react",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@ionic/react": "^7.6.1",
|
||||
"@ionic/react": "^7.8.3",
|
||||
"@types/node": "^12.20.55",
|
||||
"@types/react": "^18.2.45",
|
||||
"@types/react-dom": "^18.2.17",
|
||||
@@ -2407,21 +2407,21 @@
|
||||
"integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw=="
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "7.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.6.1.tgz",
|
||||
"integrity": "sha512-o4PSRxokfRB5H3E5DAM7xivG8XFXaXD3+U/tha0QKemiMSntqgPqy0FYX0pNEwIrV3llRzFbAGNqyvB1+BG97Q==",
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.8.3.tgz",
|
||||
"integrity": "sha512-5pFoE8gbhbCuyQlZ7BlRk4+S4PmmqgkALw4IAhtUK1TuzsKJ2KLFBlp0rdlWS+VcKEyrec/ptVki8oN5335vRA==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.8.2",
|
||||
"ionicons": "^7.2.1",
|
||||
"@stencil/core": "^4.12.2",
|
||||
"ionicons": "^7.2.2",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/react": {
|
||||
"version": "7.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-7.6.1.tgz",
|
||||
"integrity": "sha512-Gg6IezbyvMucgNgmCMFr5vrsh2kgB/5S9j/24L07wt4mCNBy5ZGrzHkq9NSmcgU7bj/qD1GzamjoqICLH2vEzw==",
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-7.8.3.tgz",
|
||||
"integrity": "sha512-nush+Ra/KNLv4MvxODwxNe7/FVcDRyc0xgkFKwXu9P/ztUv8qqy0zotHxsJVAb9BAd/r78eBpdyaOnUQcLw2Dg==",
|
||||
"dependencies": {
|
||||
"@ionic/core": "7.6.1",
|
||||
"@ionic/core": "7.8.3",
|
||||
"ionicons": "^7.0.0",
|
||||
"tslib": "*"
|
||||
},
|
||||
@@ -3365,9 +3365,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.8.2.tgz",
|
||||
"integrity": "sha512-KdZEAtz9VnqMtXOkf51+8mphyRt0fN/LYgtj5M8gnveGspG8KzoyTDzlWt0wsstWIsJJ21RA1yd3AgMMZiu3MA==",
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.14.0.tgz",
|
||||
"integrity": "sha512-+s0u/KsNolXZ7tC2hEMgMA3jaNaqOhZvYKwSzjQbc0Wv+cB481Isxzo7ifgEWRYqsJzNSyqhO6cyu/EJrGGTdg==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -8716,9 +8716,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ionicons": {
|
||||
"version": "7.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.2.2.tgz",
|
||||
"integrity": "sha512-I3iYIfc9Q9FRifWyFSwTAvbEABWlWY32i0sAVDDPGYnaIZVugkLCZFbEcrphW6ixVPg8tt1oLwalo/JJwbEqnA==",
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.3.1.tgz",
|
||||
"integrity": "sha512-1boG4EQTBBpQ4/0PU60Yi78Iw/k8iNtKu9c0NmsbzHGnWAcwpiovG9Wi/rk5UlF+DC+CR4XDCxKo91YqvAxkww==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.0.3"
|
||||
}
|
||||
@@ -18765,21 +18765,21 @@
|
||||
"integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw=="
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "7.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.6.1.tgz",
|
||||
"integrity": "sha512-o4PSRxokfRB5H3E5DAM7xivG8XFXaXD3+U/tha0QKemiMSntqgPqy0FYX0pNEwIrV3llRzFbAGNqyvB1+BG97Q==",
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-7.8.3.tgz",
|
||||
"integrity": "sha512-5pFoE8gbhbCuyQlZ7BlRk4+S4PmmqgkALw4IAhtUK1TuzsKJ2KLFBlp0rdlWS+VcKEyrec/ptVki8oN5335vRA==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.8.2",
|
||||
"ionicons": "^7.2.1",
|
||||
"@stencil/core": "^4.12.2",
|
||||
"ionicons": "^7.2.2",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"@ionic/react": {
|
||||
"version": "7.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-7.6.1.tgz",
|
||||
"integrity": "sha512-Gg6IezbyvMucgNgmCMFr5vrsh2kgB/5S9j/24L07wt4mCNBy5ZGrzHkq9NSmcgU7bj/qD1GzamjoqICLH2vEzw==",
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-7.8.3.tgz",
|
||||
"integrity": "sha512-nush+Ra/KNLv4MvxODwxNe7/FVcDRyc0xgkFKwXu9P/ztUv8qqy0zotHxsJVAb9BAd/r78eBpdyaOnUQcLw2Dg==",
|
||||
"requires": {
|
||||
"@ionic/core": "7.6.1",
|
||||
"@ionic/core": "7.8.3",
|
||||
"ionicons": "^7.0.0",
|
||||
"tslib": "*"
|
||||
}
|
||||
@@ -19462,9 +19462,9 @@
|
||||
}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.8.2.tgz",
|
||||
"integrity": "sha512-KdZEAtz9VnqMtXOkf51+8mphyRt0fN/LYgtj5M8gnveGspG8KzoyTDzlWt0wsstWIsJJ21RA1yd3AgMMZiu3MA=="
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.14.0.tgz",
|
||||
"integrity": "sha512-+s0u/KsNolXZ7tC2hEMgMA3jaNaqOhZvYKwSzjQbc0Wv+cB481Isxzo7ifgEWRYqsJzNSyqhO6cyu/EJrGGTdg=="
|
||||
},
|
||||
"@surma/rollup-plugin-off-main-thread": {
|
||||
"version": "2.2.3",
|
||||
@@ -23371,9 +23371,9 @@
|
||||
}
|
||||
},
|
||||
"ionicons": {
|
||||
"version": "7.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.2.2.tgz",
|
||||
"integrity": "sha512-I3iYIfc9Q9FRifWyFSwTAvbEABWlWY32i0sAVDDPGYnaIZVugkLCZFbEcrphW6ixVPg8tt1oLwalo/JJwbEqnA==",
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-7.3.1.tgz",
|
||||
"integrity": "sha512-1boG4EQTBBpQ4/0PU60Yi78Iw/k8iNtKu9c0NmsbzHGnWAcwpiovG9Wi/rk5UlF+DC+CR4XDCxKo91YqvAxkww==",
|
||||
"requires": {
|
||||
"@stencil/core": "^4.0.3"
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@ionic/react": "^7.6.1",
|
||||
"@ionic/react": "^7.8.3",
|
||||
"@types/node": "^12.20.55",
|
||||
"@types/react": "^18.2.45",
|
||||
"@types/react-dom": "^18.2.17",
|
||||
|
||||
9700
packages/static-build/test/fixtures/nuxt-v3/package-lock.json
generated
vendored
9700
packages/static-build/test/fixtures/nuxt-v3/package-lock.json
generated
vendored
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nuxt/devtools": "latest",
|
||||
"nuxt": "^3.7.4",
|
||||
"nuxt": "^3.11.1",
|
||||
"vue": "^3.3.4",
|
||||
"vue-router": "^4.2.5"
|
||||
}
|
||||
|
||||
28
packages/static-build/test/fixtures/preact-v10/package-lock.json
generated
vendored
28
packages/static-build/test/fixtures/preact-v10/package-lock.json
generated
vendored
@@ -9,8 +9,8 @@
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"preact": "^10.18.1",
|
||||
"preact-render-to-string": "^6.2.2",
|
||||
"preact": "^10.20.1",
|
||||
"preact-render-to-string": "^6.4.1",
|
||||
"preact-router": "^4.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -15572,9 +15572,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/preact": {
|
||||
"version": "10.18.1",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.18.1.tgz",
|
||||
"integrity": "sha512-mKUD7RRkQQM6s7Rkmi7IFkoEHjuFqRQUaXamO61E6Nn7vqF/bo7EZCmSyrUnp2UWHw0O7XjZ2eeXis+m7tf4lg==",
|
||||
"version": "10.20.1",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.20.1.tgz",
|
||||
"integrity": "sha512-JIFjgFg9B2qnOoGiYMVBtrcFxHqn+dNXbq76bVmcaHYJFYR4lW67AOcXgAYQQTDYXDOg/kTZrKPNCdRgJ2UJmw==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/preact"
|
||||
@@ -15795,9 +15795,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/preact-render-to-string": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.2.2.tgz",
|
||||
"integrity": "sha512-YDfXQiVeYZutFR8/DpxLSbW3W6b7GgjBExRBxOOqcjrGq5rA9cziitQdNPMZe4RVMSdfBnf4hYqyeLs/KvtIuA==",
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.4.1.tgz",
|
||||
"integrity": "sha512-oHKIFIv+/N0i3fNRF4ANMr2I93maycuXK78ERJ0vUW+nz6MXXMO6mTOFxp3itvSVBS/GXtLAy2jio3ZPeD8lZQ==",
|
||||
"dependencies": {
|
||||
"pretty-format": "^3.8.0"
|
||||
},
|
||||
@@ -33825,9 +33825,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"preact": {
|
||||
"version": "10.18.1",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.18.1.tgz",
|
||||
"integrity": "sha512-mKUD7RRkQQM6s7Rkmi7IFkoEHjuFqRQUaXamO61E6Nn7vqF/bo7EZCmSyrUnp2UWHw0O7XjZ2eeXis+m7tf4lg=="
|
||||
"version": "10.20.1",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.20.1.tgz",
|
||||
"integrity": "sha512-JIFjgFg9B2qnOoGiYMVBtrcFxHqn+dNXbq76bVmcaHYJFYR4lW67AOcXgAYQQTDYXDOg/kTZrKPNCdRgJ2UJmw=="
|
||||
},
|
||||
"preact-cli": {
|
||||
"version": "3.5.0",
|
||||
@@ -33992,9 +33992,9 @@
|
||||
}
|
||||
},
|
||||
"preact-render-to-string": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.2.2.tgz",
|
||||
"integrity": "sha512-YDfXQiVeYZutFR8/DpxLSbW3W6b7GgjBExRBxOOqcjrGq5rA9cziitQdNPMZe4RVMSdfBnf4hYqyeLs/KvtIuA==",
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.4.1.tgz",
|
||||
"integrity": "sha512-oHKIFIv+/N0i3fNRF4ANMr2I93maycuXK78ERJ0vUW+nz6MXXMO6mTOFxp3itvSVBS/GXtLAy2jio3ZPeD8lZQ==",
|
||||
"requires": {
|
||||
"pretty-format": "^3.8.0"
|
||||
}
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
"preact-cli": "^3.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"preact": "^10.18.1",
|
||||
"preact-render-to-string": "^6.2.2",
|
||||
"preact": "^10.20.1",
|
||||
"preact-render-to-string": "^6.4.1",
|
||||
"preact-router": "^4.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
14
packages/static-build/test/fixtures/stencil-v4/package-lock.json
generated
vendored
14
packages/static-build/test/fixtures/stencil-v4/package-lock.json
generated
vendored
@@ -9,7 +9,7 @@
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.10.0"
|
||||
"@stencil/core": "^4.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.5.2",
|
||||
@@ -1039,9 +1039,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.10.0.tgz",
|
||||
"integrity": "sha512-7lDTPY1IxXN2/C+wQPHt3e/dYgY4YgelA8MxOsU3ZftXtpzWad/QNWhSAtKisJMrSjQh41jMDOgD0yLBwV6E7w==",
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.14.0.tgz",
|
||||
"integrity": "sha512-+s0u/KsNolXZ7tC2hEMgMA3jaNaqOhZvYKwSzjQbc0Wv+cB481Isxzo7ifgEWRYqsJzNSyqhO6cyu/EJrGGTdg==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -5781,9 +5781,9 @@
|
||||
}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.10.0.tgz",
|
||||
"integrity": "sha512-7lDTPY1IxXN2/C+wQPHt3e/dYgY4YgelA8MxOsU3ZftXtpzWad/QNWhSAtKisJMrSjQh41jMDOgD0yLBwV6E7w=="
|
||||
"version": "4.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.14.0.tgz",
|
||||
"integrity": "sha512-+s0u/KsNolXZ7tC2hEMgMA3jaNaqOhZvYKwSzjQbc0Wv+cB481Isxzo7ifgEWRYqsJzNSyqhO6cyu/EJrGGTdg=="
|
||||
},
|
||||
"@tootallnate/once": {
|
||||
"version": "1.1.2",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"generate": "stencil generate"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.10.0"
|
||||
"@stencil/core": "^4.14.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.5.2",
|
||||
|
||||
Reference in New Issue
Block a user