Compare commits

..

7 Commits

Author SHA1 Message Date
Javi Velasco
b27501c281 wip 2024-02-06 09:58:28 +01:00
dvoytenko
3f29798a5a strip to .next, report more failures 2024-01-31 16:17:45 +01:00
dvoytenko
5358a00611 Use absolute paths for require 2024-01-31 16:17:45 +01:00
Javi Velasco
70db54f59b Add measures 2024-01-31 16:17:45 +01:00
Javi Velasco
aafdd66b79 Use require 2024-01-31 16:17:45 +01:00
Javi Velasco
ca59387aac Add common and rest of chunks to the server launcher template 2024-01-31 16:17:45 +01:00
Javi Velasco
fb5eac2fbc Add logic to add common and rest of chunks 2024-01-31 16:17:45 +01:00
916 changed files with 11265 additions and 76503 deletions

View File

@@ -0,0 +1,5 @@
---
"@vercel/next": patch
---
Fix rewrite RSC handling with trailingSlash

View File

@@ -10,7 +10,6 @@ packages/*/test/fixtures
packages/cli/@types
packages/cli/download
packages/cli/dist
packages/cli/test/fixtures
packages/cli/test/dev/fixtures
packages/cli/bin
packages/cli/link
@@ -39,7 +38,7 @@ packages/static-build/test/cache-fixtures
packages/redwood/test/fixtures
# remix
packages/remix/test/fixtures-*
packages/remix/test/fixtures
# gatsby-plugin-vercel-analytics
packages/gatsby-plugin-vercel-analytics

22
.github/CODEOWNERS vendored
View File

@@ -2,17 +2,17 @@
# https://help.github.com/en/articles/about-code-owners
# Restricted Paths
* @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads
/.github/workflows @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @ijjk
/packages/fs-detectors @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @agadzik @chloetedder
/packages/next @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @timneutkens @ijjk @ztanner @huozhi @Ethan-Arrowood @styfle
/packages/routing-utils @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @ijjk
/packages/static-build @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads
/packages/edge @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @vercel/compute
/examples @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @leerob
/examples/create-react-app @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @Timer
/examples/nextjs @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @timneutkens @ijjk @ztanner @huozhi @Ethan-Arrowood @styfle
/packages/node @TooTallNate @EndangeredMassa @trek @onsclom @jeffsee55 @erikareads @Kikobeats
* @TooTallNate @EndangeredMassa @trek
/.github/workflows @TooTallNate @EndangeredMassa @trek @ijjk
/packages/fs-detectors @TooTallNate @EndangeredMassa @trek @agadzik @chloetedder
/packages/next @TooTallNate @EndangeredMassa @Ethan-Arrowood @trek @ijjk @ztanner
/packages/routing-utils @TooTallNate @EndangeredMassa @trek @ijjk
/packages/static-build @TooTallNate @EndangeredMassa @trek
/packages/edge @vercel/compute @TooTallNate @EndangeredMassa @trek
/examples @leerob
/examples/create-react-app @Timer
/examples/nextjs @timneutkens @ijjk @ztanner @huozhi
/packages/node @TooTallNate @EndangeredMassa @trek @Kikobeats
# Unrestricted Paths
.changeset/

View File

@@ -1,3 +1,108 @@
## Contributing
# Contributing
See the [Contributing Guidelines](../README.md#contributing) 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.
### @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

224
.github/dependabot.yml vendored
View File

@@ -1,224 +0,0 @@
version: 2
updates:
- directory: /packages/static-build/test/fixtures/angular-v17
schedule:
interval: 'daily'
open-pull-requests-limit: 1
reviewers:
- 'trek'
- 'TooTallNate'
- 'EndangeredMassa'
commit-message:
prefix: '[framework-fixtures]'
package-ecosystem: 'npm'
allow:
- dependency-name: '@angular*'
ignore:
- dependency-name: '@angular*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
groups:
core:
patterns:
- '@angular*'
update-types:
- 'minor'
- directory: /packages/static-build/test/fixtures/astro-v4
schedule:
interval: 'daily'
open-pull-requests-limit: 1
reviewers:
- 'trek'
- 'TooTallNate'
- 'EndangeredMassa'
commit-message:
prefix: '[framework-fixtures]'
package-ecosystem: 'npm'
allow:
- dependency-name: 'astro*'
ignore:
- dependency-name: 'astro*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
groups:
core:
patterns:
- 'astro*'
update-types:
- 'minor'
- directory: /packages/static-build/test/fixtures/hydrogen-v2023
schedule:
interval: 'daily'
open-pull-requests-limit: 1
reviewers:
- 'trek'
- 'TooTallNate'
- 'EndangeredMassa'
commit-message:
prefix: '[framework-fixtures]'
package-ecosystem: 'npm'
allow:
- dependency-name: '@remix-run*'
- dependency-name: '@shopify*'
ignore:
- dependency-name: '@remix-run*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
- dependency-name: '@shopify*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
groups:
core:
patterns:
- '@remix-run*'
- '@shopify*'
update-types:
- 'minor'
- directory: /packages/static-build/test/fixtures/ionic-angular-v7
schedule:
interval: 'daily'
open-pull-requests-limit: 1
reviewers:
- 'trek'
- 'TooTallNate'
- 'EndangeredMassa'
commit-message:
prefix: '[framework-fixtures]'
package-ecosystem: 'npm'
allow:
- dependency-name: '@ionic*'
- dependency-name: '@angular*'
ignore:
- dependency-name: '@ionic*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
- dependency-name: '@angular*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
groups:
core:
patterns:
- '@angular*'
- '@ionic*'
update-types:
- 'minor'
- directory: /packages/static-build/test/fixtures/ionic-react-v7
schedule:
interval: 'daily'
open-pull-requests-limit: 1
reviewers:
- 'trek'
- 'TooTallNate'
- 'EndangeredMassa'
commit-message:
prefix: '[framework-fixtures]'
package-ecosystem: 'npm'
allow:
- dependency-name: '@ionic*'
- dependency-name: 'react*'
ignore:
- dependency-name: '@ionic*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
- dependency-name: 'react*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
groups:
core:
patterns:
- '@ionic*'
- 'react*'
update-types:
- 'minor'
- directory: /packages/static-build/test/fixtures/nuxt-v3
schedule:
interval: 'daily'
open-pull-requests-limit: 1
reviewers:
- 'trek'
- 'TooTallNate'
- 'EndangeredMassa'
commit-message:
prefix: '[framework-fixtures]'
package-ecosystem: 'npm'
allow:
- dependency-name: 'nuxt'
- dependency-name: 'vue'
- dependency-name: 'vue-router'
- dependency-name: '@nuxt-devtools'
ignore:
- dependency-name: 'nuxt'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
- dependency-name: 'vue'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
- dependency-name: 'vue-router'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
- dependency-name: '@nuxt-devtools'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
groups:
core:
patterns:
- 'nuxt'
- 'vue'
- 'vue-router'
- '@nuxt-devtools'
update-types:
- 'minor'
- directory: /packages/static-build/test/fixtures/preact-v10
schedule:
interval: 'daily'
open-pull-requests-limit: 1
reviewers:
- 'trek'
- 'TooTallNate'
- 'EndangeredMassa'
commit-message:
prefix: '[framework-fixtures]'
package-ecosystem: 'npm'
allow:
- dependency-name: 'preact*'
ignore:
- dependency-name: 'preact*'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
groups:
core:
patterns:
- 'preact*'
update-types:
- 'minor'
- directory: /packages/static-build/test/fixtures/stencil-v4
schedule:
interval: 'daily'
open-pull-requests-limit: 1
reviewers:
- 'trek'
- 'TooTallNate'
- 'EndangeredMassa'
commit-message:
prefix: '[framework-fixtures]'
package-ecosystem: 'npm'
allow:
- dependency-name: '@stencil/core'
ignore:
- dependency-name: '@stencil/core'
update-types:
['version-update:semver-major', 'version-update:semver-patch']
groups:
core:
patterns:
- '@stencil/core'
update-types:
- 'minor'

View File

@@ -79,13 +79,16 @@ 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
env:
FORCE_COLOR: '1'
- name: Test ${{matrix.packageName}}
run: node utils/gen.js && node_modules/.bin/turbo run ${{matrix.testScript}} --summarize --cache-dir=".turbo" --log-order=stream --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }}
run: node utils/gen.js && node_modules/.bin/turbo run test --summarize --cache-dir=".turbo" --log-order=stream --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }}
shell: bash
env:
JEST_JUNIT_OUTPUT_FILE: ${{github.workspace}}/.junit-reports/${{matrix.scriptName}}-${{matrix.packageName}}-${{matrix.chunkNumber}}-${{ matrix.runner }}.xml
@@ -101,6 +104,9 @@ 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'

View File

@@ -29,7 +29,6 @@ turbo-cache-key.json
packages/*/dist
packages/*/node_modules
packages/**/test/fixtures
packages/**/test/fixtures-*
packages/**/test/dev/fixtures
packages/**/test/build-fixtures
packages/**/test/cache-fixtures

133
README.md
View File

@@ -13,7 +13,7 @@
<a href="https://vercel.com/docs"><strong>Documentation</strong></a> ·
<a href="https://vercel.com/changelog"><strong>Changelog</strong></a> ·
<a href="https://vercel.com/templates"><strong>Templates</strong></a> ·
<a href="https://vercel.com/docs/cli"><strong>CLI</strong></a>
<a href="https://vercel.com/cli"><strong>CLI</strong></a>
</p>
<br/>
@@ -23,7 +23,7 @@ Vercels Frontend Cloud provides the developer experience and infrastructure t
## Deploy
Get started by [importing a project](https://vercel.com/new) or using the [Vercel CLI](https://vercel.com/docs/cli). Then, `git push` to deploy.
Get started by [importing a project](https://vercel.com/new) or using the [Vercel CLI](https://vercel.com/cli). Then, `git push` to deploy.
## Documentation
@@ -35,134 +35,7 @@ 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`.
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
See the [Contributing Guidelines](./.github/CONTRIBUTING.md) for more details.
## Reference

View File

@@ -50,4 +50,4 @@ Ensure any segments used in the `destination` property are also used in the `sou
- [path-to-regexp](https://github.com/pillarjs/path-to-regexp/tree/v6.1.0)
- [named parameters](https://github.com/pillarjs/path-to-regexp/blob/v6.1.0/Readme.md#named-parameters)
- [un-named parameters](https://github.com/pillarjs/path-to-regexp/blob/v6.1.0/Readme.md#unnamed-parameters)
- [un-named paramters](https://github.com/pillarjs/path-to-regexp/blob/v6.1.0/Readme.md#unnamed-parameters)

2
examples/README.md vendored
View File

@@ -1,6 +1,6 @@
# Vercel Examples
To get started using any of these examples as your own project, [install Vercel](https://vercel.com/docs/cli) and use either of the following commands in your terminal:
To get started using any of these examples as your own project, [install Vercel](https://vercel.com/cli) and use either of the following commands in your terminal:
```sh
vercel init # Pick an example in the CLI

View File

@@ -4,7 +4,7 @@ import { lstatSync, readdirSync } from 'fs';
export async function deployExample(filename: string) {
const { testDeployment } = require('../../test/lib/deployment/test-deployment.js');
const example = basename(filename).replace(/\.test\.ts$/, '');
await testDeployment(join(process.cwd(), example));
await testDeployment(join(filename, '..', '..', '..', example));
}
export function getExamples() {

View File

@@ -1,5 +0,0 @@
{
"engines": {
"node": "18.x"
}
}

View File

@@ -8,6 +8,6 @@ menu:
main: {}
---
This is an example of a custom shortcode that you can put right into your content. You will need to add a form action to the shortcode to make it work. Check out [Formspree](https://formspree.io/) for a simple, free form service.
This is an example of a custom shortcode that you can put right into your content. You will need to add a form action to the the shortcode to make it work. Check out [Formspree](https://formspree.io/) for a simple, free form service.
{{< form-contact action="https://example.com" >}}

View File

@@ -8,7 +8,7 @@ This directory is a brief example of a [Hydrogen v2](https://shopify.dev/custom-
_Live Example: https://hydrogen-v2-template.vercel.app_
You can also deploy using the [Vercel CLI](https://vercel.com/docs/cli):
You can also deploy using the [Vercel CLI](https://vercel.com/cli):
```sh
npm i -g vercel

View File

@@ -27,6 +27,3 @@ end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
# Webrick not installed by default in Ruby 3.0+
gem "webrick"

View File

@@ -1,20 +1,20 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
colorator (1.1.0)
concurrent-ruby (1.2.3)
em-websocket (0.5.3)
concurrent-ruby (1.1.8)
em-websocket (0.5.2)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
http_parser.rb (~> 0.6.0)
eventmachine (1.2.7)
ffi (1.16.3)
ffi (1.14.2)
forwardable-extended (2.6.0)
http_parser.rb (0.8.0)
i18n (1.14.1)
http_parser.rb (0.6.0)
i18n (1.8.9)
concurrent-ruby (~> 1.0)
jekyll (4.2.2)
jekyll (4.2.0)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
@@ -29,20 +29,20 @@ GEM
rouge (~> 3.0)
safe_yaml (~> 1.0)
terminal-table (~> 2.0)
jekyll-feed (0.17.0)
jekyll-feed (0.15.1)
jekyll (>= 3.7, < 5.0)
jekyll-sass-converter (2.2.0)
jekyll-sass-converter (2.1.0)
sassc (> 2.0.1, < 3.0)
jekyll-seo-tag (2.8.0)
jekyll-seo-tag (2.7.1)
jekyll (>= 3.8, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
kramdown (2.4.0)
kramdown (2.3.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.9.0)
liquid (4.0.3)
listen (3.4.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.4.0)
@@ -52,22 +52,21 @@ GEM
jekyll-seo-tag (~> 2.1)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (5.0.4)
rb-fsevent (0.11.2)
public_suffix (4.0.6)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.6)
rouge (3.30.0)
rexml (3.2.4)
rouge (3.26.0)
safe_yaml (1.0.5)
sassc (2.4.0)
ffi (~> 1.9)
terminal-table (2.0.0)
unicode-display_width (~> 1.1, >= 1.1.1)
unicode-display_width (1.8.0)
webrick (1.8.1)
unicode-display_width (1.7.0)
PLATFORMS
ruby
x86_64-linux
DEPENDENCIES
jekyll (~> 4.2.0)
@@ -76,7 +75,6 @@ DEPENDENCIES
tzinfo (~> 1.2)
tzinfo-data
wdm (~> 0.1.1)
webrick
BUNDLED WITH
2.5.6
2.2.4

View File

@@ -1,5 +0,0 @@
{
"engines": {
"node": "18.x"
}
}

View File

@@ -1,6 +1,6 @@
source 'https://rubygems.org'
gem 'middleman', '~> 4.5'
gem 'middleman-autoprefixer', '~> 3.0'
gem 'middleman', '~> 4.2'
gem 'middleman-autoprefixer', '~> 2.7'
gem 'tzinfo-data', platforms: [:mswin, :mingw, :jruby, :x64_mingw]
gem 'wdm', '~> 0.1', platforms: [:mswin, :mingw, :x64_mingw]

View File

@@ -1,60 +1,59 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.0.8.1)
activesupport (5.2.4.5)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
autoprefixer-rails (10.4.16.0)
execjs (~> 2)
backports (3.24.1)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
autoprefixer-rails (9.8.6.5)
execjs
backports (3.20.2)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
concurrent-ruby (1.2.3)
contracts (0.16.1)
dotenv (3.1.0)
concurrent-ruby (1.1.8)
contracts (0.13.0)
dotenv (2.7.6)
erubis (2.7.0)
execjs (2.9.1)
fast_blank (1.0.1)
fastimage (2.3.0)
ffi (1.16.3)
haml (6.3.0)
temple (>= 0.8.2)
thor
execjs (2.7.0)
fast_blank (1.0.0)
fastimage (2.2.2)
ffi (1.14.2)
haml (5.2.1)
temple (>= 0.8.0)
tilt
hamster (3.0.0)
concurrent-ruby (~> 1.0)
hashie (3.6.0)
i18n (1.6.0)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
kramdown (2.4.0)
kramdown (2.3.0)
rexml
listen (3.9.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
memoist (0.16.2)
middleman (4.5.1)
middleman (4.3.11)
coffee-script (~> 2.2)
haml (>= 4.0.5)
kramdown (>= 2.3.0)
middleman-cli (= 4.5.1)
middleman-core (= 4.5.1)
middleman-autoprefixer (3.0.0)
autoprefixer-rails (~> 10.0)
middleman-core (>= 4.0.0)
middleman-cli (4.5.1)
thor (>= 0.17.0, < 1.3.0)
middleman-core (4.5.1)
activesupport (>= 6.1, < 7.1)
addressable (~> 2.4)
middleman-cli (= 4.3.11)
middleman-core (= 4.3.11)
middleman-autoprefixer (2.10.1)
autoprefixer-rails (~> 9.1)
middleman-core (>= 3.3.3)
middleman-cli (4.3.11)
thor (>= 0.17.0, < 2.0)
middleman-core (4.3.11)
activesupport (>= 4.2, < 6.0)
addressable (~> 2.3)
backports (~> 3.6)
bundler (~> 2.0)
contracts (~> 0.13, < 0.17)
bundler
contracts (~> 0.13.0)
dotenv
erubis
execjs (~> 2.0)
@@ -62,52 +61,48 @@ GEM
fastimage (~> 2.0)
hamster (~> 3.0)
hashie (~> 3.4)
i18n (~> 1.6.0)
listen (~> 3.0)
i18n (~> 0.9.0)
listen (~> 3.0.0)
memoist (~> 0.14)
padrino-helpers (~> 0.15.0)
padrino-helpers (~> 0.13.0)
parallel
rack (>= 1.4.5, < 3)
sassc (~> 2.0)
servolux
tilt (~> 2.0.9)
toml
uglifier (~> 3.0)
webrick
minitest (5.22.2)
padrino-helpers (0.15.3)
i18n (>= 0.6.7, < 2)
padrino-support (= 0.15.3)
minitest (5.14.3)
padrino-helpers (0.13.3.4)
i18n (~> 0.6, >= 0.6.7)
padrino-support (= 0.13.3.4)
tilt (>= 1.4.1, < 3)
padrino-support (0.15.3)
parallel (1.24.0)
parslet (2.0.0)
public_suffix (5.0.4)
rack (2.2.8.1)
rb-fsevent (0.11.2)
padrino-support (0.13.3.4)
activesupport (>= 3.1)
parallel (1.20.1)
public_suffix (4.0.6)
rack (2.2.3)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.6)
rexml (3.2.4)
sassc (2.4.0)
ffi (~> 1.9)
servolux (0.13.0)
temple (0.10.3)
thor (1.2.2)
tilt (2.0.11)
toml (0.3.0)
parslet (>= 1.8.0, < 3.0.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
temple (0.8.2)
thor (1.1.0)
thread_safe (0.3.6)
tilt (2.0.10)
tzinfo (1.2.9)
thread_safe (~> 0.1)
uglifier (3.2.0)
execjs (>= 0.3.0, < 3)
webrick (1.8.1)
PLATFORMS
x86_64-linux
DEPENDENCIES
middleman (~> 4.5)
middleman-autoprefixer (~> 3.0)
middleman (~> 4.2)
middleman-autoprefixer (~> 2.7)
tzinfo-data
wdm (~> 0.1)

View File

@@ -1,5 +0,0 @@
{
"engines": {
"node": "18.x"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -11,7 +11,7 @@
"dependencies": {
"react": "^18",
"react-dom": "^18",
"next": "14.1.4"
"next": "14.1.0"
},
"devDependencies": {
"typescript": "^5",
@@ -22,6 +22,6 @@
"postcss": "^8",
"tailwindcss": "^3.3.0",
"eslint": "^8",
"eslint-config-next": "14.1.4"
"eslint-config-next": "14.1.0"
}
}

View File

@@ -9,8 +9,7 @@
},
"devDependencies": {
"@types/jest": "27.4.1",
"@vercel/build-utils": "7.11.0",
"@vercel/frameworks": "3.0.1"
"@vercel/frameworks": "2.0.6"
},
"version": null
}

View File

@@ -1,5 +1,7 @@
node_modules
/.cache
/build
/public/build
.env
.vercel

View File

@@ -14,7 +14,7 @@ npx create-remix@latest --template vercel/vercel/examples/remix
_Live Example: https://remix-run-template.vercel.app_
You can also deploy using the [Vercel CLI](https://vercel.com/docs/cli):
You can also deploy using the [Vercel CLI](https://vercel.com/cli):
```sh
npm i -g vercel
@@ -35,4 +35,4 @@ Afterwards, start the Remix development server like so:
npm run dev
```
Open up [http://localhost:5173](http://localhost:5173) and you should be ready to go!
Open up [http://localhost:3000](http://localhost:3000) and you should be ready to go!

View File

@@ -1,13 +1,20 @@
import { cssBundleHref } from "@remix-run/css-bundle";
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react";
import { Analytics } from "@vercel/analytics/react";
import type { LinksFunction } from "@vercel/remix";
export function Layout({ children }: { children: React.ReactNode }) {
export const links: LinksFunction = () => [
...(cssBundleHref ? [{ rel: "stylesheet", href: cssBundleHref }] : []),
];
export default function App() {
return (
<html lang="en">
<head>
@@ -17,15 +24,12 @@ export function Layout({ children }: { children: React.ReactNode }) {
<Links />
</head>
<body>
{children}
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
<Analytics />
</body>
</html>
);
}
export default function App() {
return <Outlet />;
}

View File

@@ -4,29 +4,29 @@
"sideEffects": false,
"type": "module",
"scripts": {
"build": "remix vite:build",
"dev": "remix vite:dev",
"build": "remix build",
"dev": "remix dev --manual",
"start": "remix-serve ./build/index.js",
"typecheck": "tsc"
},
"dependencies": {
"@remix-run/node": "^2.8.0",
"@remix-run/react": "^2.8.0",
"@remix-run/server-runtime": "^2.8.0",
"@vercel/analytics": "^1.2.2",
"@vercel/remix": "^2.8.0",
"isbot": "^4",
"@remix-run/css-bundle": "^2.0.0",
"@remix-run/node": "^2.0.0",
"@remix-run/react": "^2.0.0",
"@remix-run/serve": "^2.0.0",
"@vercel/analytics": "^1.0.2",
"@vercel/remix": "^2.0.0",
"isbot": "^3.6.8",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@remix-run/dev": "^2.8.0",
"@remix-run/eslint-config": "^2.8.0",
"@remix-run/dev": "^2.0.0",
"@remix-run/eslint-config": "^2.0.0",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
"eslint": "^8.38.0",
"typescript": "^5.1.6",
"vite": "^5.1.0",
"vite-tsconfig-paths": "^4.2.1"
"typescript": "^5.1.6"
},
"engines": {
"node": ">=18.0.0"

View File

@@ -1,25 +1,22 @@
{
"include": ["**/*.ts", "**/*.tsx"],
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"types": ["@vercel/remix", "node", "vite/client"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",
"module": "ESNext",
"moduleResolution": "Bundler",
"resolveJsonModule": true,
"target": "ES2022",
"strict": true,
"allowJs": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"~/*": ["./app/*"]
},
// Vite takes care of building everything, not tsc.
// Remix takes care of building everything in `remix build`.
"noEmit": true
}
}

View File

@@ -1,11 +0,0 @@
import { vitePlugin as remix } from "@remix-run/dev";
import { installGlobals } from "@remix-run/node";
import { defineConfig } from "vite";
import { vercelPreset } from '@vercel/remix/vite';
import tsconfigPaths from "vite-tsconfig-paths";
installGlobals();
export default defineConfig({
plugins: [remix({ presets: [vercelPreset()] }), tsconfigPaths()],
});

View File

@@ -18,7 +18,7 @@ Install dependencies:
npx @sanity/cli install
```
Pull down environment variables from your Vercel project (requires the [Vercel CLI](https://vercel.com/docs/cli)):
Pull down environment variables from your Vercel project (requires the [Vercel CLI](https://vercel.com/cli)):
```sh
vercel env pull

View File

@@ -1,5 +0,0 @@
{
"engines": {
"node": "18.x"
}
}

View File

@@ -1,61 +1,5 @@
# @vercel-internals/types
## 1.0.29
### Patch Changes
- Updated dependencies [[`73b112b1f`](https://github.com/vercel/vercel/commit/73b112b1f74480e1bb941e1b754105fc7dace401)]:
- @vercel/build-utils@7.11.0
## 1.0.28
### Patch Changes
- Updated dependencies [[`1825b58df`](https://github.com/vercel/vercel/commit/1825b58df8d783e79f0addf262618f422246f4b3)]:
- @vercel/build-utils@7.10.0
## 1.0.27
### Patch Changes
- Updated dependencies [[`11218a179`](https://github.com/vercel/vercel/commit/11218a179870a5420c5a6ff720cd4aec4f7e1c5e)]:
- @vercel/build-utils@7.9.1
## 1.0.26
### Patch Changes
- Updated dependencies [[`8ea93839c`](https://github.com/vercel/vercel/commit/8ea93839ccc70816f3ece9d7cfdb857aa7a4b015)]:
- @vercel/build-utils@7.9.0
## 1.0.25
### Patch Changes
- Updated dependencies [[`908e7837d`](https://github.com/vercel/vercel/commit/908e7837d55bc02e708f402c700e00208415e954), [`5e3656ec1`](https://github.com/vercel/vercel/commit/5e3656ec1b3f0561091636582715ba09ddd8cb2d)]:
- @vercel/build-utils@7.8.0
## 1.0.24
### Patch Changes
- Updated dependencies [[`37b193c84`](https://github.com/vercel/vercel/commit/37b193c845d8b63d93bb0017fbc1a6a35306ef1f)]:
- @vercel/build-utils@7.7.1
## 1.0.23
### Patch Changes
- Updated dependencies [[`24c3dd282`](https://github.com/vercel/vercel/commit/24c3dd282d7714cd63d2b94fb94745c45fdc79ab)]:
- @vercel/build-utils@7.7.0
## 1.0.22
### Patch Changes
- Updated dependencies [[`b6ed28b9b`](https://github.com/vercel/vercel/commit/b6ed28b9b1712f882c93fe053b70d3eb1df21819), [`8ba0ce932`](https://github.com/vercel/vercel/commit/8ba0ce932434c6295fedb5307bee59a804b7e6a8), [`0d034b682`](https://github.com/vercel/vercel/commit/0d034b6820c0f3252949c0ffc483048c5aac7f04), [`abaa700ce`](https://github.com/vercel/vercel/commit/abaa700cea44c723cfc851baa2dfe9e1ae2e8a5c)]:
- @vercel/build-utils@7.6.0
## 1.0.21
### Patch Changes

View File

@@ -1,7 +1,7 @@
{
"private": true,
"name": "@vercel-internals/types",
"version": "1.0.29",
"version": "1.0.21",
"types": "index.d.ts",
"main": "index.d.ts",
"files": [
@@ -10,7 +10,7 @@
"dependencies": {
"@types/node": "14.14.31",
"@vercel-internals/constants": "1.0.4",
"@vercel/build-utils": "7.11.0",
"@vercel/build-utils": "7.5.1",
"@vercel/routing-utils": "3.1.0"
},
"devDependencies": {

View File

@@ -33,7 +33,7 @@
"source-map-support": "0.5.12",
"ts-eager": "2.0.2",
"ts-jest": "29.1.0",
"turbo": "1.13.2",
"turbo": "1.11.3",
"typescript": "4.9.5"
},
"scripts": {

View File

@@ -1,65 +1,5 @@
# @vercel/build-utils
## 7.11.0
### Minor Changes
- Add `getOsRelease()` and `getProvidedRuntime()` functions ([#11370](https://github.com/vercel/vercel/pull/11370))
## 7.10.0
### Minor Changes
- Allow environment variables to be specified for `EdgeFunction` ([#11029](https://github.com/vercel/vercel/pull/11029))
## 7.9.1
### Patch Changes
- Export `getSupportedNodeVersion` ([#11277](https://github.com/vercel/vercel/pull/11277))
## 7.9.0
### Minor Changes
- Add `base` parameter to `scanParentDirs()` ([#11261](https://github.com/vercel/vercel/pull/11261))
## 7.8.0
### Minor Changes
- Remove `VERCEL_ENABLE_NPM_DEFAULT` env var check ([#11242](https://github.com/vercel/vercel/pull/11242))
### Patch Changes
- Rename variants to flags and remove legacy flags ([#11121](https://github.com/vercel/vercel/pull/11121))
## 7.7.1
### Patch Changes
- [build-utils] increase max memory limit ([#11209](https://github.com/vercel/vercel/pull/11209))
## 7.7.0
### Minor Changes
- Revert "Revert "Default ruby to only currently supported version (3.2.0)"" ([#11137](https://github.com/vercel/vercel/pull/11137))
## 7.6.0
### Minor Changes
- Revert "Default ruby to only currently supported version (3.2.0)" ([#11135](https://github.com/vercel/vercel/pull/11135))
- Mark `flags` as deprecated and replace them with `variants` ([#11098](https://github.com/vercel/vercel/pull/11098))
- [build-utils] change default package manager when no lockfile detected from `yarn` to `npm` (gated behind feature flag) ([#11131](https://github.com/vercel/vercel/pull/11131))
### Patch Changes
- Update internal type for variants ([#11111](https://github.com/vercel/vercel/pull/11111))
## 7.5.1
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "7.11.0",
"version": "7.5.1",
"license": "Apache-2.0",
"main": "./dist/index.js",
"types": "./dist/index.d.js",

View File

@@ -1,4 +1,4 @@
import type { Env, Files, FunctionFramework } from './types';
import type { Files, FunctionFramework } from './types';
/**
* An Edge Functions output
@@ -23,11 +23,6 @@ export class EdgeFunction {
*/
entrypoint: string;
/**
* Environment variables for the edge function to use at runtime.
*/
environment?: Env;
/**
* The list of files to be included in the edge function bundle.
*/
@@ -53,6 +48,5 @@ export class EdgeFunction {
this.assets = params.assets;
this.regions = params.regions;
this.framework = params.framework;
this.environment = params.environment;
}
}

View File

@@ -276,13 +276,12 @@ export async function getNodeVersion(
export async function scanParentDirs(
destPath: string,
readPackageJson = false,
base = '/'
readPackageJson = false
): Promise<ScanParentDirsResult> {
assert(path.isAbsolute(destPath));
const pkgJsonPath = await walkParentDirs({
base,
base: '/',
start: destPath,
filename: 'package.json',
});
@@ -292,7 +291,7 @@ export async function scanParentDirs(
: undefined;
const [yarnLockPath, npmLockPath, pnpmLockPath, bunLockPath] =
await walkParentDirsMulti({
base,
base: '/',
start: destPath,
filenames: [
'yarn.lock',
@@ -303,7 +302,7 @@ export async function scanParentDirs(
});
let lockfilePath: string | undefined;
let lockfileVersion: number | undefined;
let cliType: CliType;
let cliType: CliType = 'yarn';
const [hasYarnLock, packageLockJson, pnpmLockYaml, bunLockBin] =
await Promise.all([
@@ -339,8 +338,6 @@ export async function scanParentDirs(
lockfilePath = bunLockPath;
// TODO: read "bun-lockfile-format-v0"
lockfileVersion = 0;
} else {
cliType = 'npm';
}
const packageJsonPath = pkgJsonPath || undefined;
@@ -417,14 +414,6 @@ export async function runNpmInstall(
destPath
);
if (!packageJsonPath) {
debug(
`Skipping dependency installation because no package.json was found for ${destPath}`
);
runNpmInstallSema.release();
return false;
}
// Only allow `runNpmInstall()` to run once per `package.json`
// when doing a default install (no additional args)
if (meta && packageJsonPath && args.length === 0) {

View File

@@ -38,7 +38,6 @@ import {
import {
getLatestNodeVersion,
getDiscontinuedNodeVersions,
getSupportedNodeVersion,
} from './fs/node-version';
import streamToBuffer from './fs/stream-to-buffer';
import debug from './debug';
@@ -73,7 +72,6 @@ export {
walkParentDirs,
getNodeBinPath,
getNodeBinPaths,
getSupportedNodeVersion,
runNpmInstall,
runBundleInstall,
runPipInstall,
@@ -103,7 +101,6 @@ export {
export { EdgeFunction } from './edge-function';
export { readConfigFile } from './fs/read-config-file';
export { normalizePath } from './fs/normalize-path';
export { getOsRelease, getProvidedRuntime } from './os';
export * from './should-serve';
export * from './schemas';

View File

@@ -5,7 +5,11 @@ import minimatch from 'minimatch';
import { readlink } from 'fs-extra';
import { isSymbolicLink, isDirectory } from './fs/download';
import streamToBuffer from './fs/stream-to-buffer';
import type { Config, Env, Files, FunctionFramework } from './types';
import type { Files, Config, FunctionFramework } from './types';
interface Environment {
[key: string]: string;
}
export type LambdaOptions = LambdaOptionsWithFiles | LambdaOptionsWithZipBuffer;
@@ -17,7 +21,7 @@ export interface LambdaOptionsBase {
architecture?: LambdaArchitecture;
memory?: number;
maxDuration?: number;
environment?: Env;
environment?: Environment;
allowQuery?: string[];
regions?: string[];
supportsMultiPayloads?: boolean;
@@ -65,7 +69,7 @@ export class Lambda {
architecture?: LambdaArchitecture;
memory?: number;
maxDuration?: number;
environment: Env;
environment: Environment;
allowQuery?: string[];
regions?: string[];
/**

View File

@@ -1,42 +0,0 @@
import { readFile } from 'fs-extra';
import { isErrnoException } from '@vercel/error-utils';
export async function getOsRelease() {
try {
const data = await readFile('/etc/os-release', 'utf8');
return await parseOsRelease(data);
} catch (err) {
if (isErrnoException(err) && err.code === 'ENOENT') {
return null;
}
throw err;
}
}
export async function parseOsRelease(data: string) {
const obj: Record<string, string> = {};
// Example file contents:
// NAME="Amazon Linux"
// VERSION="2023"
// ID="amzn"
// ID_LIKE="fedora"
for (const line of data.trim().split('\n')) {
const m = /(?<key>.*)="(?<value>.*)"/.exec(line);
if (!m?.groups) {
continue;
}
obj[m.groups.key] = m.groups.value;
}
return obj;
}
export async function getProvidedRuntime() {
const os = await getOsRelease();
if (!os) {
return 'provided.al2023';
}
return os.PRETTY_NAME === 'Amazon Linux 2'
? 'provided.al2'
: 'provided.al2023';
}

View File

@@ -14,7 +14,7 @@ export const functionsSchema = {
},
memory: {
minimum: 128,
maximum: 3009,
maximum: 3008,
},
maxDuration: {
type: 'number',

View File

@@ -440,6 +440,13 @@ export interface Cron {
schedule: string;
}
// TODO: Proper description once complete
export interface Flag {
key: string;
defaultValue?: unknown;
metadata: Record<string, unknown>;
}
/** The framework which created the function */
export interface FunctionFramework {
slug: string;
@@ -464,7 +471,7 @@ export interface BuildResultV2Typical {
framework?: {
version: string;
};
flags?: { definitions: FlagDefinitions };
flags?: Flag[];
}
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;
@@ -484,30 +491,3 @@ export type ShouldServe = (
export type StartDevServer = (
options: StartDevServerOptions
) => Promise<StartDevServerResult>;
/**
* TODO: The following types will eventually be exported by a more
* relevant package.
*/
type FlagJSONArray = ReadonlyArray<FlagJSONValue>;
type FlagJSONValue =
| string
| boolean
| number
| null
| FlagJSONArray
| { [key: string]: FlagJSONValue };
type FlagOption = {
value: FlagJSONValue;
label?: string;
};
export interface FlagDefinition {
options?: FlagOption[];
origin?: string;
description?: string;
}
export type FlagDefinitions = Record<string, FlagDefinition>;

View File

@@ -1,4 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1

View File

@@ -1,4 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1

View File

@@ -1,4 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1

View File

@@ -3,8 +3,5 @@
"version": "1.0.0",
"scripts": {
"build": "mkdir -p public && (printf \"npm version: \" && npm -v) > public/index.txt"
},
"engines": {
"node": "16.x"
}
}

View File

@@ -5,8 +5,5 @@
},
"dependencies": {
"once": "^1.4.0"
},
"engines": {
"node": "16.x"
}
}

View File

@@ -6,8 +6,5 @@
"dependencies": {
"exeggcute": "^1.0.0",
"once": "^1.4.0"
},
"engines": {
"node": "16.x"
}
}

View File

@@ -1,12 +0,0 @@
{
"private": true,
"scripts": {
"build": "mkdir -p public && (printf \"npm version: \" && npm -v) > public/index.txt"
},
"dependencies": {
"sharp": "0.33.2"
},
"engines": {
"node": "16.x"
}
}

View File

@@ -1,3 +0,0 @@
{
"probes": [{ "path": "/", "mustContain": "npm version: 8" }]
}

View File

@@ -23,6 +23,8 @@ const skipFixtures: string[] = [
'23-pnpm-workspaces',
'41-nx-monorepo',
'42-npm-workspace-with-nx',
'jekyll-v4',
'middleman-v4',
];
// eslint-disable-next-line no-restricted-syntax

View File

@@ -1,89 +0,0 @@
import { parseOsRelease } from '../src/os';
describe('getOsRelease()', () => {
it('should parse `amazonlinux:2`', async () => {
const data = `NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
SUPPORT_END="2025-06-30"
`;
const parsed = await parseOsRelease(data);
expect(parsed).toMatchObject({
ANSI_COLOR: '0;33',
CPE_NAME: 'cpe:2.3:o:amazon:amazon_linux:2',
HOME_URL: 'https://amazonlinux.com/',
ID: 'amzn',
ID_LIKE: 'centos rhel fedora',
NAME: 'Amazon Linux',
PRETTY_NAME: 'Amazon Linux 2',
SUPPORT_END: '2025-06-30',
VERSION: '2',
VERSION_ID: '2',
});
});
it('should parse `amazonlinux:2023`', async () => {
const data = `NAME="Amazon Linux"
VERSION="2023"
ID="amzn"
ID_LIKE="fedora"
VERSION_ID="2023"
PLATFORM_ID="platform:al2023"
PRETTY_NAME="Amazon Linux 2023"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2023"
HOME_URL="https://aws.amazon.com/linux/"
BUG_REPORT_URL="https://github.com/amazonlinux/amazon-linux-2023"
SUPPORT_END="2028-03-01"
`;
const parsed = await parseOsRelease(data);
expect(parsed).toMatchObject({
NAME: 'Amazon Linux',
VERSION: '2023',
ID: 'amzn',
ID_LIKE: 'fedora',
VERSION_ID: '2023',
PLATFORM_ID: 'platform:al2023',
PRETTY_NAME: 'Amazon Linux 2023',
ANSI_COLOR: '0;33',
CPE_NAME: 'cpe:2.3:o:amazon:amazon_linux:2023',
HOME_URL: 'https://aws.amazon.com/linux/',
BUG_REPORT_URL: 'https://github.com/amazonlinux/amazon-linux-2023',
SUPPORT_END: '2028-03-01',
});
});
it('should parse `ubuntu:jammy`', async () => {
const data = `PRETTY_NAME="Ubuntu 22.04.3 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.3 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
`;
const parsed = await parseOsRelease(data);
expect(parsed).toMatchObject({
PRETTY_NAME: 'Ubuntu 22.04.3 LTS',
NAME: 'Ubuntu',
VERSION_ID: '22.04',
VERSION: '22.04.3 LTS (Jammy Jellyfish)',
HOME_URL: 'https://www.ubuntu.com/',
SUPPORT_URL: 'https://help.ubuntu.com/',
BUG_REPORT_URL: 'https://bugs.launchpad.net/ubuntu/',
PRIVACY_POLICY_URL:
'https://www.ubuntu.com/legal/terms-and-policies/privacy-policy',
});
});
});

View File

@@ -576,28 +576,6 @@ it(
ms('1m')
);
it('should return cliType "npm" when no lockfile is present', async () => {
const originalRepoLockfilePath = path.join(
__dirname,
'..',
'..',
'..',
'pnpm-lock.yaml'
);
const originalRepoLockfileData = await fs.readFile(originalRepoLockfilePath);
await fs.remove(originalRepoLockfilePath);
try {
const fixture = path.join(__dirname, 'fixtures', '40-no-lockfile');
const result = await scanParentDirs(fixture);
expect(result.cliType).toEqual('npm');
expect(result.lockfileVersion).toEqual(undefined);
expect(result.lockfilePath).toEqual(undefined);
expect(result.packageJsonPath).toEqual(path.join(fixture, 'package.json'));
} finally {
await fs.writeFile(originalRepoLockfilePath, originalRepoLockfileData);
}
});
it('should return cliType bun and correct lock file for bun v1', async () => {
const fixture = path.join(__dirname, 'fixtures', '31-bun-v1-with-yarn-lock');
const result = await scanParentDirs(fixture);

View File

@@ -1,181 +1,5 @@
# vercel
## 34.0.0
### Major Changes
- Disables promotion of preview deployments ([#11411](https://github.com/vercel/vercel/pull/11411))
### Patch Changes
- Always set `projectSettings.nodeVersion` in `vc deploy` ([#11351](https://github.com/vercel/vercel/pull/11351))
- [cli] optional override of existing environment variables with --force ([#11348](https://github.com/vercel/vercel/pull/11348))
## 33.7.1
### Patch Changes
- fix flickering during interactive UI rerendering ([#11392](https://github.com/vercel/vercel/pull/11392))
- fix `vc ls` message to be `vc projects ls` ([#11400](https://github.com/vercel/vercel/pull/11400))
- Updated dependencies [[`2461b571a`](https://github.com/vercel/vercel/commit/2461b571af037fbfdf92299a272010a5a8f4898b)]:
- @vercel/next@4.2.0
## 33.7.0
### Minor Changes
- improve UX for text input validation ([#11388](https://github.com/vercel/vercel/pull/11388))
- Replace the implementation of the yes/no prompt in several areas to be consistent with the rest of the CLI. ([#11279](https://github.com/vercel/vercel/pull/11279))
### Patch Changes
- [cli] Fix how we determine the GIT_CONFIG_PATH to support git worktrees and git submodules ([#11283](https://github.com/vercel/vercel/pull/11283))
- avoid printing errors when user does ctrl+c ([#11377](https://github.com/vercel/vercel/pull/11377))
- Warn that promoting preview deploys is deprecated ([#11376](https://github.com/vercel/vercel/pull/11376))
- Updated dependencies [[`a3fb7e6ab`](https://github.com/vercel/vercel/commit/a3fb7e6abe9bb619a653850decd739728b1af225)]:
- @vercel/go@3.1.1
## 33.6.3
### Patch Changes
- Handle `--repo` linked in `vc deploy --prebuilt` ([#11309](https://github.com/vercel/vercel/pull/11309))
- Revert "[cli] extract `isZeroConfigBuild` into utility function (#11316)" ([#11350](https://github.com/vercel/vercel/pull/11350))
- Replace `inquirer` with `@inquirer/prompts` ([#11321](https://github.com/vercel/vercel/pull/11321))
- Updated dependencies [[`73b112b1f`](https://github.com/vercel/vercel/commit/73b112b1f74480e1bb941e1b754105fc7dace401), [`346e665bb`](https://github.com/vercel/vercel/commit/346e665bb021e6034bc70c82ef336485622595fe), [`73b112b1f`](https://github.com/vercel/vercel/commit/73b112b1f74480e1bb941e1b754105fc7dace401), [`548afd371`](https://github.com/vercel/vercel/commit/548afd371aa7a9dd3a7f4c60f7f94a7084d8023e)]:
- @vercel/go@3.1.0
- @vercel/node@3.0.26
- @vercel/build-utils@7.11.0
- @vercel/static-build@2.4.6
## 33.6.2
### Patch Changes
- Added sunset warning to secrets command. ([#11333](https://github.com/vercel/vercel/pull/11333))
- Swap jest for vitest in CLI unit tests ([#11302](https://github.com/vercel/vercel/pull/11302))
- Updated dependencies [[`988f7b75a`](https://github.com/vercel/vercel/commit/988f7b75a27387e84fce541b844f984d2c151980), [`1825b58df`](https://github.com/vercel/vercel/commit/1825b58df8d783e79f0addf262618f422246f4b3)]:
- @vercel/remix-builder@2.1.5
- @vercel/build-utils@7.10.0
- @vercel/node@3.0.25
- @vercel/static-build@2.4.5
## 33.6.1
### Patch Changes
- Don't send `projectSettings.nodeVersion` for unsupported versions ([#11277](https://github.com/vercel/vercel/pull/11277))
- Updated dependencies [[`4bca0c6d0`](https://github.com/vercel/vercel/commit/4bca0c6d0bc25052b95bd02b12a0b891c86c4b49), [`a67ad4b5a`](https://github.com/vercel/vercel/commit/a67ad4b5a130bf0e56e18111b3f9ddad69cec0e1), [`11218a179`](https://github.com/vercel/vercel/commit/11218a179870a5420c5a6ff720cd4aec4f7e1c5e), [`64b97bf4b`](https://github.com/vercel/vercel/commit/64b97bf4b5203ecf9a95f63ce26a5c3360208966)]:
- @vercel/next@4.1.6
- @vercel/remix-builder@2.1.4
- @vercel/build-utils@7.9.1
- @vercel/static-build@2.4.4
- @vercel/node@3.0.24
## 33.6.0
### Minor Changes
- Set `projectSettings.nodeVersion` in `vc deploy` based on "engines.node" field ([#11261](https://github.com/vercel/vercel/pull/11261))
### Patch Changes
- Stops warning about legacy Speed Insights for Next.js apps ([#11268](https://github.com/vercel/vercel/pull/11268))
- Fix framework version detection in monorepos ([#11212](https://github.com/vercel/vercel/pull/11212))
- Updated dependencies [[`8ea93839c`](https://github.com/vercel/vercel/commit/8ea93839ccc70816f3ece9d7cfdb857aa7a4b015), [`58ef91bfe`](https://github.com/vercel/vercel/commit/58ef91bfe8c2e7176e8783cc4eb91ee8580c70dc)]:
- @vercel/build-utils@7.9.0
- @vercel/remix-builder@2.1.3
- @vercel/node@3.0.23
- @vercel/static-build@2.4.3
## 33.5.5
### Patch Changes
- Rename variants to flags and remove legacy flags ([#11121](https://github.com/vercel/vercel/pull/11121))
- fix vc with root dir issues ([#11243](https://github.com/vercel/vercel/pull/11243))
- Updated dependencies [[`908e7837d`](https://github.com/vercel/vercel/commit/908e7837d55bc02e708f402c700e00208415e954), [`5e3656ec1`](https://github.com/vercel/vercel/commit/5e3656ec1b3f0561091636582715ba09ddd8cb2d), [`a53d1b0d3`](https://github.com/vercel/vercel/commit/a53d1b0d38efa9637f8b8f81a70898add87530e3)]:
- @vercel/build-utils@7.8.0
- @vercel/next@4.1.5
- @vercel/remix-builder@2.1.2
- @vercel/node@3.0.22
- @vercel/static-build@2.4.2
## 33.5.4
### Patch Changes
- [build-utils] increase max memory limit ([#11209](https://github.com/vercel/vercel/pull/11209))
- Updated dependencies [[`b1d8b83ab`](https://github.com/vercel/vercel/commit/b1d8b83abbf23a3485aedb490992d0a3bf44573f), [`37b193c84`](https://github.com/vercel/vercel/commit/37b193c845d8b63d93bb0017fbc1a6a35306ef1f), [`20237d4f7`](https://github.com/vercel/vercel/commit/20237d4f7b55b0697b57db15636c11204cb0dc39), [`f8fab639b`](https://github.com/vercel/vercel/commit/f8fab639bf49a60389b8d0b7b265a737c17b4ae1), [`6ed0fe6fb`](https://github.com/vercel/vercel/commit/6ed0fe6fb1e487545a790ff5b9fc691cf625f005)]:
- @vercel/next@4.1.4
- @vercel/build-utils@7.7.1
- @vercel/remix-builder@2.1.1
- @vercel/static-build@2.4.1
- @vercel/node@3.0.21
## 33.5.3
### Patch Changes
- Updated dependencies [[`c2d99855e`](https://github.com/vercel/vercel/commit/c2d99855ea6132380434ed29643120680f95fad7), [`1333071a3`](https://github.com/vercel/vercel/commit/1333071a3a2d324679327bfdd4e872f8fd3521c6)]:
- @vercel/next@4.1.3
- @vercel/remix-builder@2.1.0
## 33.5.2
### Patch Changes
- Updated dependencies [[`e109e3325`](https://github.com/vercel/vercel/commit/e109e3325ab5299da0903034175fabe72d486a4e), [`d17abf463`](https://github.com/vercel/vercel/commit/d17abf463acabf9e1e43b91200f18efd34e91f62), [`644721a90`](https://github.com/vercel/vercel/commit/644721a90da8cf98414d272be9da0a821a2ce217), [`ea0e9aeae`](https://github.com/vercel/vercel/commit/ea0e9aeaec8ddddb5a726be0d252df9cdbd84808), [`e318a0eea`](https://github.com/vercel/vercel/commit/e318a0eea55c9b8536b0874f66cfd03aca6f0adf), [`1fee87e76`](https://github.com/vercel/vercel/commit/1fee87e76f18d2f5e5524247cfce615fa1832e49), [`bfc01fd98`](https://github.com/vercel/vercel/commit/bfc01fd98f760a008d0d2e6c52b5216503b44b75), [`7910f2f30`](https://github.com/vercel/vercel/commit/7910f2f3070ff69742e845e795d4db77d598c181), [`440ef3ba9`](https://github.com/vercel/vercel/commit/440ef3ba98af8f05e7714c86c67c36dbda11e85c)]:
- @vercel/remix-builder@2.0.20
- @vercel/next@4.1.2
- @vercel/node@3.0.20
- @vercel/redwood@2.0.8
## 33.5.1
### Patch Changes
- build: upgrade edge-runtime ([#11148](https://github.com/vercel/vercel/pull/11148))
- Updated dependencies [[`24c3dd282`](https://github.com/vercel/vercel/commit/24c3dd282d7714cd63d2b94fb94745c45fdc79ab), [`10e200e0b`](https://github.com/vercel/vercel/commit/10e200e0bf8f692b6740e098e0572b4e7de83850), [`678ebbe52`](https://github.com/vercel/vercel/commit/678ebbe5255766656bf2dddc574e86b2999f11c8)]:
- @vercel/build-utils@7.7.0
- @vercel/static-build@2.4.0
- @vercel/node@3.0.19
## 33.5.0
### Minor Changes
- Mark `flags` as deprecated and replace them with `variants` ([#11098](https://github.com/vercel/vercel/pull/11098))
### Patch Changes
- Updated dependencies [[`c32a909af`](https://github.com/vercel/vercel/commit/c32a909afcedf0ee55777d5dcaecc0c8383dd8c8), [`b6ed28b9b`](https://github.com/vercel/vercel/commit/b6ed28b9b1712f882c93fe053b70d3eb1df21819), [`d21bb9f87`](https://github.com/vercel/vercel/commit/d21bb9f87e1d837666fe8104d4e199b2590725d6), [`4027a1833`](https://github.com/vercel/vercel/commit/4027a1833718a92be74b2b3c5a4df23745d19a36), [`8ba0ce932`](https://github.com/vercel/vercel/commit/8ba0ce932434c6295fedb5307bee59a804b7e6a8), [`0d034b682`](https://github.com/vercel/vercel/commit/0d034b6820c0f3252949c0ffc483048c5aac7f04), [`abaa700ce`](https://github.com/vercel/vercel/commit/abaa700cea44c723cfc851baa2dfe9e1ae2e8a5c), [`3bad73401`](https://github.com/vercel/vercel/commit/3bad73401b4ec1f61e515965732cde8dcc052b17)]:
- @vercel/next@4.1.1
- @vercel/node@3.0.18
- @vercel/redwood@2.0.7
- @vercel/remix-builder@2.0.19
- @vercel/build-utils@7.6.0
- @vercel/static-build@2.3.0
## 33.4.1
### Patch Changes

View File

@@ -7,7 +7,6 @@ module.exports = {
{
diagnostics: true,
isolatedModules: true,
tsconfig: 'test/tsconfig.json',
},
],
},

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "34.0.0",
"version": "33.4.1",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -12,8 +12,7 @@
},
"scripts": {
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail",
"vitest-unit-run": "pnpm vitest",
"vitest-unit": "pnpm jest test/unit/ --listTests",
"test-unit": "pnpm test test/unit/",
"test-e2e": "rimraf test/fixtures/integration && pnpm test test/integration-1.test.ts test/integration-2.test.ts test/integration-3.test.ts",
"test-dev": "pnpm test test/dev/",
"coverage": "codecov",
@@ -32,27 +31,22 @@
"node": ">= 16"
},
"dependencies": {
"@vercel/build-utils": "7.11.0",
"@vercel/build-utils": "7.5.1",
"@vercel/fun": "1.1.0",
"@vercel/go": "3.1.1",
"@vercel/go": "3.0.5",
"@vercel/hydrogen": "1.0.2",
"@vercel/next": "4.2.0",
"@vercel/node": "3.0.26",
"@vercel/next": "4.1.0",
"@vercel/node": "3.0.17",
"@vercel/python": "4.1.1",
"@vercel/redwood": "2.0.8",
"@vercel/remix-builder": "2.1.5",
"@vercel/redwood": "2.0.6",
"@vercel/remix-builder": "2.0.18",
"@vercel/ruby": "2.0.5",
"@vercel/static-build": "2.4.6",
"@vercel/static-build": "2.2.0",
"chokidar": "3.3.1"
},
"devDependencies": {
"@alex_neo/jest-expect-message": "1.0.5",
"@edge-runtime/node-utils": "2.3.0",
"@inquirer/checkbox": "2.2.2",
"@inquirer/confirm": "3.1.2",
"@inquirer/expand": "2.1.2",
"@inquirer/input": "2.1.2",
"@inquirer/select": "2.2.2",
"@edge-runtime/node-utils": "2.2.2",
"@next/env": "11.1.2",
"@sentry/node": "5.5.0",
"@sindresorhus/slugify": "0.11.0",
@@ -69,6 +63,7 @@
"@types/glob": "7.1.1",
"@types/http-proxy": "1.16.2",
"@types/ini": "1.3.31",
"@types/inquirer": "7.3.1",
"@types/jest": "27.4.1",
"@types/jest-expect-message": "1.0.3",
"@types/json-parse-better-errors": "1.0.0",
@@ -84,6 +79,7 @@
"@types/qs": "6.9.7",
"@types/semver": "6.0.1",
"@types/tar-fs": "1.16.1",
"@types/text-table": "0.2.0",
"@types/title": "3.4.1",
"@types/universal-analytics": "0.4.2",
"@types/update-notifier": "5.1.0",
@@ -92,13 +88,12 @@
"@types/yauzl-promise": "2.1.0",
"@vercel-internals/constants": "1.0.4",
"@vercel-internals/get-package-json": "1.0.0",
"@vercel-internals/types": "1.0.29",
"@vercel/client": "13.2.0",
"@vercel-internals/types": "1.0.21",
"@vercel/client": "13.1.1",
"@vercel/error-utils": "2.0.2",
"@vercel/frameworks": "3.0.1",
"@vercel/fs-detectors": "5.2.2",
"@vercel/frameworks": "2.0.6",
"@vercel/fs-detectors": "5.1.6",
"@vercel/routing-utils": "3.1.0",
"@vitest/expect": "1.4.0",
"ajv": "6.12.2",
"alpha-sort": "2.0.1",
"ansi-escapes": "4.3.2",
@@ -131,6 +126,7 @@
"glob": "7.1.2",
"http-proxy": "1.18.1",
"ini": "3.0.0",
"inquirer": "7.0.4",
"is-docker": "2.2.1",
"is-port-reachable": "3.1.0",
"is-url": "1.2.2",
@@ -162,14 +158,13 @@
"strip-ansi": "6.0.1",
"supports-hyperlinks": "3.0.0",
"tar-fs": "1.16.3",
"text-table": "0.2.0",
"title": "3.4.1",
"tmp-promise": "1.0.3",
"tree-kill": "1.2.2",
"ts-node": "10.9.1",
"universal-analytics": "0.4.20",
"utility-types": "2.1.0",
"vite": "5.1.6",
"vitest": "1.3.1",
"which": "3.0.0",
"write-json-file": "2.2.0",
"xdg-app-paths": "5.1.0",

View File

@@ -1,6 +1,6 @@
import chalk from 'chalk';
import ms from 'ms';
import table from '../../util/output/table';
import table from 'text-table';
import Client from '../../util/client';
import getAliases from '../../util/alias/get-aliases';
import getScope from '../../util/get-scope';
@@ -9,6 +9,7 @@ import {
getPaginationOpts,
} from '../../util/get-pagination-opts';
import stamp from '../../util/output/stamp';
import strlen from '../../util/strlen';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name';
import type { Alias } from '@vercel-internals/types';
@@ -77,6 +78,10 @@ function printAliasTable(aliases: Alias[]) {
ms(Date.now() - a.createdAt),
]),
],
{ align: ['l', 'l', 'r'], hsep: 4 }
{
align: ['l', 'l', 'r'],
hsep: ' '.repeat(4),
stringLength: strlen,
}
).replace(/^/gm, ' ')}\n\n`;
}

View File

@@ -1,10 +1,11 @@
import chalk from 'chalk';
import ms from 'ms';
import table from '../../util/output/table';
import table from 'text-table';
import Client from '../../util/client';
import getScope from '../../util/get-scope';
import removeAliasById from '../../util/alias/remove-alias-by-id';
import stamp from '../../util/output/stamp';
import strlen from '../../util/strlen';
import confirm from '../../util/input/confirm';
import findAliasByAliasOrId from '../../util/alias/find-alias-by-alias-or-id';
@@ -83,7 +84,11 @@ async function confirmAliasRemove(client: Client, alias: Alias) {
chalk.gray(`${ms(Date.now() - alias.createdAt)} ago`),
],
],
{ hsep: 4 }
{
align: ['l', 'l', 'r'],
hsep: ' '.repeat(4),
stringLength: strlen,
}
);
client.output.log(`The following alias will be removed permanently`);

View File

@@ -45,16 +45,10 @@ export default async function bisect(client: Client): Promise<number> {
let bad =
argv['--bad'] ||
(await client.input.text({
message: `Specify a URL where the bug occurs:`,
validate: val => (val ? true : 'A URL must be provided'),
}));
(await prompt(client, `Specify a URL where the bug occurs:`));
let good =
argv['--good'] ||
(await client.input.text({
message: `Specify a URL where the bug does not occur:`,
validate: val => (val ? true : 'A URL must be provided'),
}));
(await prompt(client, `Specify a URL where the bug does not occur:`));
let subpath = argv['--path'] || '';
let run = argv['--run'] || '';
const openEnabled = argv['--open'] || false;
@@ -103,10 +97,10 @@ export default async function bisect(client: Client): Promise<number> {
}
if (!subpath) {
subpath = await client.input.text({
message: `Specify the URL subpath where the bug occurs:`,
validate: val => (val ? true : 'A subpath must be provided'),
});
subpath = await prompt(
client,
`Specify the URL subpath where the bug occurs:`
);
}
output.spinner('Retrieving deployments…');
@@ -284,7 +278,9 @@ export default async function bisect(client: Client): Promise<number> {
if (openEnabled) {
await open(testUrl);
}
action = await client.input.expand({
const answer = await client.prompt({
type: 'expand',
name: 'action',
message: 'Select an action:',
choices: [
{ key: 'g', name: 'Good', value: 'good' },
@@ -292,6 +288,7 @@ export default async function bisect(client: Client): Promise<number> {
{ key: 's', name: 'Skip', value: 'skip' },
],
});
action = answer.action;
}
if (action === 'good') {
@@ -341,3 +338,19 @@ 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.prompt({
type: 'input',
name: 'val',
message,
});
if (val) {
return val;
} else {
client.output.error('A value must be specified');
}
}
}

View File

@@ -4,7 +4,7 @@ import dotenv from 'dotenv';
import semver from 'semver';
import minimatch from 'minimatch';
import { join, normalize, relative, resolve, sep } from 'path';
import { frameworkList } from '@vercel/frameworks';
import frameworks from '@vercel/frameworks';
import {
getDiscontinuedNodeVersions,
normalizePath,
@@ -21,7 +21,7 @@ import {
NowBuildError,
Cron,
validateNpmrc,
type FlagDefinitions,
Flag,
} from '@vercel/build-utils';
import {
detectBuilders,
@@ -95,6 +95,7 @@ interface BuildOutputConfig {
version: string;
};
crons?: Cron[];
flags?: Flag[];
}
/**
@@ -257,6 +258,9 @@ export default async function main(client: Client): Promise<number> {
if (project.settings.analyticsId) {
envToUnset.add('VERCEL_ANALYTICS_ID');
process.env.VERCEL_ANALYTICS_ID = project.settings.analyticsId;
output.warn(
'Vercel Speed Insights auto-injection is deprecated in favor of @vercel/speed-insights package. Learn more: https://vercel.link/upgrate-to-speed-insights-package'
);
}
// Some build processes use these env vars to platform detect Vercel
@@ -660,8 +664,9 @@ async function doBuild(
const mergedWildcard = mergeWildcard(buildResults.values());
const mergedOverrides: Record<string, PathOverride> =
overrides.length > 0 ? Object.assign({}, ...overrides) : undefined;
const mergedFlags = mergeFlags(buildResults.values());
const framework = await getFramework(workPath, buildResults);
const framework = await getFramework(cwd, buildResults);
// Write out the final `config.json` file based on the
// user configuration and Builder build results
@@ -673,11 +678,10 @@ async function doBuild(
overrides: mergedOverrides,
framework,
crons: mergedCrons,
flags: mergedFlags,
};
await fs.writeJSON(join(outputDir, 'config.json'), config, { spaces: 2 });
await writeFlagsJSON(client, buildResults.values(), outputDir);
const relOutputDir = relative(cwd, outputDir);
output.print(
`${prependEmoji(
@@ -695,7 +699,7 @@ async function getFramework(
): Promise<{ version: string } | undefined> {
const detectedFramework = await detectFrameworkRecord({
fs: new LocalFileSystemDetector(cwd),
frameworkList,
frameworkList: frameworks,
});
if (!detectedFramework) {
@@ -810,52 +814,16 @@ function mergeWildcard(
return wildcard;
}
/**
* Takes the build output and writes all the flags into the `flags.json`
* file. It'll skip flags that already exist.
*/
async function writeFlagsJSON(
{ output }: Client,
buildResults: Iterable<BuildResult | BuildOutputConfig>,
outputDir: string
): Promise<void> {
const flagsFilePath = join(outputDir, 'flags.json');
let hasFlags = true;
const flags = (await fs.readJSON(flagsFilePath).catch(error => {
if (error.code === 'ENOENT') {
hasFlags = false;
return { definitions: {} };
function mergeFlags(
buildResults: Iterable<BuildResult | BuildOutputConfig>
): BuildResultV2Typical['flags'] {
return Array.from(buildResults).flatMap(result => {
if ('flags' in result) {
return result.flags ?? [];
}
throw error;
})) as { definitions: FlagDefinitions };
for (const result of buildResults) {
if (!('flags' in result) || !result.flags || !result.flags.definitions)
continue;
for (const [key, definition] of Object.entries(result.flags.definitions)) {
if (result.flags.definitions[key]) {
output.warn(
`The flag "${key}" was found multiple times. Only its first occurrence will be considered.`
);
continue;
}
hasFlags = true;
flags.definitions[key] = definition;
}
}
// Only create the file when there are flags to write,
// or when the file already exists.
// Checking `definitions` alone won't be enough in case there
// are other properties set.
if (hasFlags) {
await fs.writeJSON(flagsFilePath, flags, { spaces: 2 });
}
return [];
});
}
async function writeBuildJson(buildsJson: BuildsManifest, outputDir: string) {

View File

@@ -1,6 +1,6 @@
import chalk from 'chalk';
import ms from 'ms';
import table from '../../util/output/table';
import table from 'text-table';
import Client from '../../util/client';
import getScope from '../../util/get-scope';
import {
@@ -9,6 +9,7 @@ import {
} from '../../util/get-pagination-opts';
import stamp from '../../util/output/stamp';
import getCerts from '../../util/certs/get-certs';
import strlen from '../../util/strlen';
import type { Cert } from '@vercel-internals/types';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name';
@@ -69,7 +70,11 @@ async function ls(
function formatCertsTable(certsList: Cert[]) {
return `${table(
[formatCertsTableHead(), ...formatCertsTableBody(certsList)],
{ align: ['l', 'l', 'r', 'c', 'r'], hsep: 2 }
{
align: ['l', 'l', 'r', 'c', 'r'],
hsep: ' '.repeat(2),
stringLength: strlen,
}
).replace(/^(.*)/gm, ' $1')}\n`;
}

View File

@@ -1,7 +1,7 @@
import chalk from 'chalk';
import ms from 'ms';
import plural from 'pluralize';
import table from '../../util/output/table';
import table from 'text-table';
import type { Cert } from '@vercel-internals/types';
import * as ERRORS from '../../util/errors-ts';
import { Output } from '../../util/output';
@@ -98,11 +98,11 @@ function readConfirmation(output: Output, msg: string, certs: Cert[]) {
output.print(
`${table(certs.map(formatCertRow), {
align: ['l', 'r', 'l'],
hsep: 6,
hsep: ' '.repeat(6),
}).replace(/^(.*)/gm, ' $1')}\n`
);
output.print(
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('(y/N) ')}`
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[y/N] ')}`
);
process.stdin
.on('data', d => {

View File

@@ -1,77 +1,73 @@
import {
getPrettyError,
getSupportedNodeVersion,
scanParentDirs,
} from '@vercel/build-utils';
import ms from 'ms';
import fs from 'fs-extra';
import bytes from 'bytes';
import chalk from 'chalk';
import { join, resolve } from 'path';
import {
fileNameSymbol,
VALID_ARCHIVE_FORMATS,
VercelConfig,
} from '@vercel/client';
import { errorToString, isErrnoException, isError } from '@vercel/error-utils';
import bytes from 'bytes';
import chalk from 'chalk';
import fs from 'fs-extra';
import ms from 'ms';
import { join, resolve } from 'path';
import Now, { CreateOptions } from '../../util';
import Client from '../../util/client';
import code from '../../util/output/code';
import highlight from '../../util/output/highlight';
import { readLocalConfig } from '../../util/config/files';
import { createGitMeta } from '../../util/create-git-meta';
import createDeploy from '../../util/deploy/create-deploy';
import { getDeploymentChecks } from '../../util/deploy/get-deployment-checks';
import getPrebuiltJson from '../../util/deploy/get-prebuilt-json';
import parseTarget from '../../util/deploy/parse-target';
import { printDeploymentStatus } from '../../util/deploy/print-deployment-status';
import { isValidArchive } from '../../util/deploy/validate-archive-format';
import purchaseDomainIfAvailable from '../../util/domains/purchase-domain-if-available';
import { emoji, prependEmoji } from '../../util/emoji';
import getArgs from '../../util/get-args';
import { handleError } from '../../util/error';
import { SchemaValidationFailed } from '../../util/errors';
import Client from '../../util/client';
import { getPrettyError } from '@vercel/build-utils';
import toHumanPath from '../../util/humanize-path';
import Now, { CreateOptions } from '../../util';
import stamp from '../../util/output/stamp';
import createDeploy from '../../util/deploy/create-deploy';
import getDeployment from '../../util/get-deployment';
import parseMeta from '../../util/parse-meta';
import param from '../../util/output/param';
import {
AliasDomainConfigured,
BuildError,
BuildsRateLimited,
ConflictingFilePath,
ConflictingPathSegment,
DeploymentNotFound,
DeploymentsRateLimited,
DomainNotFound,
DomainNotVerified,
DomainPermissionDenied,
DomainVerificationFailed,
InvalidDomain,
isAPIError,
MissingBuildScript,
NotDomainOwner,
TooManyRequests,
UserAborted,
DeploymentsRateLimited,
AliasDomainConfigured,
MissingBuildScript,
ConflictingFilePath,
ConflictingPathSegment,
BuildError,
NotDomainOwner,
isAPIError,
} from '../../util/errors-ts';
import getArgs from '../../util/get-args';
import getDeployment from '../../util/get-deployment';
import getProjectName from '../../util/get-project-name';
import toHumanPath from '../../util/humanize-path';
import { SchemaValidationFailed } from '../../util/errors';
import purchaseDomainIfAvailable from '../../util/domains/purchase-domain-if-available';
import confirm from '../../util/input/confirm';
import editProjectSettings from '../../util/input/edit-project-settings';
import inputProject from '../../util/input/input-project';
import { inputRootDirectory } from '../../util/input/input-root-directory';
import selectOrg from '../../util/input/select-org';
import { Output } from '../../util/output';
import code from '../../util/output/code';
import highlight from '../../util/output/highlight';
import param from '../../util/output/param';
import stamp from '../../util/output/stamp';
import { parseEnv } from '../../util/parse-env';
import parseMeta from '../../util/parse-meta';
import { getCommandName } from '../../util/pkg-name';
import {
getLinkedProject,
linkFolderToProject,
} from '../../util/projects/link';
import { pickOverrides } from '../../util/projects/project-settings';
import getProjectName from '../../util/get-project-name';
import selectOrg from '../../util/input/select-org';
import inputProject from '../../util/input/input-project';
import { prependEmoji, emoji } from '../../util/emoji';
import { inputRootDirectory } from '../../util/input/input-root-directory';
import validatePaths, {
validateRootDirectory,
} from '../../util/validate-paths';
import { getCommandName } from '../../util/pkg-name';
import { Output } from '../../util/output';
import { getDeploymentChecks } from '../../util/deploy/get-deployment-checks';
import parseTarget from '../../util/deploy/parse-target';
import getPrebuiltJson from '../../util/deploy/get-prebuilt-json';
import { createGitMeta } from '../../util/create-git-meta';
import { isValidArchive } from '../../util/deploy/validate-archive-format';
import { parseEnv } from '../../util/parse-env';
import { errorToString, isErrnoException, isError } from '@vercel/error-utils';
import { pickOverrides } from '../../util/projects/project-settings';
import { printDeploymentStatus } from '../../util/deploy/print-deployment-status';
import { help } from '../help';
import { deployCommand } from './command';
@@ -303,10 +299,7 @@ export default async (client: Client): Promise<number> => {
}
// build `--prebuilt`
let vercelOutputDir: string | undefined;
if (argv['--prebuilt']) {
vercelOutputDir = join(cwd, '.vercel/output');
// For repo-style linking, update `cwd` to be the Project
// subdirectory when `rootDirectory` setting is defined
if (
@@ -314,10 +307,10 @@ export default async (client: Client): Promise<number> => {
link.repoRoot &&
link.project.rootDirectory
) {
vercelOutputDir = join(cwd, link.project.rootDirectory, '.vercel/output');
cwd = join(cwd, link.project.rootDirectory);
}
const prebuiltExists = await fs.pathExists(vercelOutputDir);
const prebuiltExists = await fs.pathExists(join(cwd, '.vercel/output'));
if (!prebuiltExists) {
error(
`The ${param(
@@ -329,7 +322,7 @@ export default async (client: Client): Promise<number> => {
return 1;
}
const prebuiltBuild = await getPrebuiltJson(vercelOutputDir);
const prebuiltBuild = await getPrebuiltJson(cwd);
// Ensure that there was not a build error
const prebuiltError =
@@ -531,7 +524,6 @@ export default async (client: Client): Promise<number> => {
forceNew: argv['--force'],
withCache: argv['--with-cache'],
prebuilt: argv['--prebuilt'],
vercelOutputDir,
rootDirectory,
quiet,
wantsPublic: Boolean(argv['--public'] || localConfig.public),
@@ -553,43 +545,14 @@ export default async (client: Client): Promise<number> => {
if (!localConfig.builds || localConfig.builds.length === 0) {
// Only add projectSettings for zero config deployments
createArgs.projectSettings = {
sourceFilesOutsideRootDirectory,
rootDirectory,
};
if (status === 'linked') {
createArgs.projectSettings = {
...createArgs.projectSettings,
...localConfigurationOverrides,
};
}
createArgs.projectSettings =
status === 'not_linked'
? {
sourceFilesOutsideRootDirectory,
}
: { ...localConfigurationOverrides, sourceFilesOutsideRootDirectory };
}
// Read the `engines.node` field from `package.json` and send as a
// `projectSettings` property as an optimization (so that the API
// does not need to retrieve the file to do this check).
const { packageJson } = await scanParentDirs(
join(cwd, project?.rootDirectory ?? ''),
true,
cwd
);
let nodeVersion: string | undefined;
if (packageJson?.engines?.node) {
try {
const { range } = await getSupportedNodeVersion(
packageJson.engines.node
);
nodeVersion = range;
} catch (error) {
if (error instanceof Error) {
output.warn(error.message);
}
}
}
if (!createArgs.projectSettings) createArgs.projectSettings = {};
createArgs.projectSettings.nodeVersion = nodeVersion;
deployment = await createDeploy(
client,
now,

View File

@@ -1,6 +1,6 @@
import chalk from 'chalk';
import ms from 'ms';
import table from '../../util/output/table';
import table from 'text-table';
import type { DNSRecord } from '@vercel-internals/types';
import { Output } from '../../util/output';
import Client from '../../util/client';
@@ -71,11 +71,11 @@ function readConfirmation(
output.print(
`${table([getDeleteTableRow(domainName, record)], {
align: ['l', 'r', 'l'],
hsep: 6,
hsep: ' '.repeat(6),
}).replace(/^(.*)/gm, ' $1')}\n`
);
output.print(
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('(y/N) ')}`
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[y/N] ')}`
);
process.stdin
.on('data', d => {

View File

@@ -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 confirm from '../../util/input/confirm';
import promptBool from '../../util/input/prompt-bool';
import purchaseDomain from '../../util/domains/purchase-domain';
import stamp from '../../util/output/stamp';
import { getCommandName } from '../../util/pkg-name';
@@ -86,25 +86,23 @@ export default async function buy(
autoRenew = true;
} else {
if (
!(await confirm(
client,
!(await promptBool(
`Buy now for ${chalk.bold(`$${price}`)} (${`${period}yr${
period > 1 ? 's' : ''
}`})?`,
false
client
))
) {
return 0;
}
autoRenew = await confirm(
client,
autoRenew = await promptBool(
renewalPrice.period === 1
? `Auto renew yearly for ${chalk.bold(`$${price}`)}?`
: `Auto renew every ${renewalPrice.period} years for ${chalk.bold(
`$${price}`
)}?`,
true
{ ...client, defaultValue: true }
);
}

View File

@@ -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 confirm from '../../util/input/confirm';
import promptBool from '../../util/input/prompt-bool';
import getTeams from '../../util/teams/get-teams';
import { getCommandName } from '../../util/pkg-name';
@@ -67,12 +67,11 @@ export default async function move(
)} will have 24 hours to accept your move request before it expires.`
);
if (
!(await confirm(
client,
!(await promptBool(
`Are you sure you want to move ${param(domainName)} to ${param(
destination
)}?`,
false
client
))
) {
output.log('Canceled');
@@ -89,10 +88,9 @@ export default async function move(
)} will be removed. Run ${getCommandName(`alias ls`)} to list them.`
);
if (
!(await confirm(
client,
!(await promptBool(
`Are you sure you want to move ${param(domainName)}?`,
false
client
))
) {
output.log('Canceled');

View File

@@ -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 confirm from '../../util/input/confirm';
import promptBool from '../../util/input/prompt-bool';
import setCustomSuffix from '../../util/domains/set-custom-suffix';
import { findProjectsForDomain } from '../../util/projects/find-projects-for-domain';
import { getCommandName } from '../../util/pkg-name';
@@ -81,10 +81,9 @@ export default async function rm(
const skipConfirmation = opts['--yes'] || false;
if (
!skipConfirmation &&
!(await confirm(
client,
!(await promptBool(
`Are you sure you want to remove ${param(domainName)}?`,
false
client
))
) {
output.log('Canceled');
@@ -223,11 +222,7 @@ async function removeDomain(
if (
!skipConfirmation &&
!(await confirm(
client,
`Remove conflicts associated with domain?`,
false
))
!(await promptBool(`Remove conflicts associated with domain?`, client))
) {
output.log('Canceled');
return 0;

View File

@@ -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 confirm from '../../util/input/confirm';
import promptBool from '../../util/input/prompt-bool';
import isRootDomain from '../../util/is-root-domain';
import { getCommandName } from '../../util/pkg-name';
@@ -67,12 +67,11 @@ export default async function transferIn(
const authCode = await getAuthCode(opts['--code']);
const shouldTransfer = await confirm(
client,
const shouldTransfer = await promptBool(
transferPolicy === 'no-change'
? `Transfer now for ${chalk.bold(`$${price}`)}?`
: `Transfer now with 1yr renewal for ${chalk.bold(`$${price}`)}?`,
false
client
);
if (!shouldTransfer) {
return 0;

View File

@@ -20,7 +20,6 @@ import { isAPIError } from '../../util/errors-ts';
type Options = {
'--debug': boolean;
'--sensitive': boolean;
'--force': boolean;
};
export default async function add(
@@ -30,6 +29,9 @@ export default async function add(
args: string[],
output: Output
) {
// improve the way we show inquirer prompts
require('../../util/input/patch-inquirer');
const stdInput = await readStandardInput(client.stdin);
let [envName, envTargetArg, envGitBranch] = args;
@@ -64,11 +66,18 @@ export default async function add(
envTargets.push(envTargetArg);
}
if (!envName) {
envName = await client.input.text({
while (!envName) {
const { inputName } = await client.prompt({
type: 'input',
name: 'inputName',
message: `Whats the name of the variable?`,
validate: val => (val ? true : 'Name cannot be empty'),
});
envName = inputName;
if (!inputName) {
output.error('Name cannot be empty');
}
}
const { envs } = await getEnvRecords(
@@ -82,7 +91,7 @@ export default async function add(
);
const choices = envTargetChoices.filter(c => !existing.has(c.value));
if (choices.length === 0 && !opts['--force']) {
if (choices.length === 0) {
output.error(
`The variable ${param(
envName
@@ -98,18 +107,26 @@ export default async function add(
if (stdInput) {
envValue = stdInput;
} else {
envValue = await client.input.text({
const { inputValue } = await client.prompt({
type: 'input',
name: 'inputValue',
message: `Whats the value of ${envName}?`,
});
envValue = inputValue || '';
}
while (envTargets.length === 0) {
envTargets = await client.input.checkbox({
const { inputTargets } = await client.prompt({
name: 'inputTargets',
type: 'checkbox',
message: `Add ${envName} to which Environments (select multiple)?`,
choices,
});
if (envTargets.length === 0) {
envTargets = inputTargets;
if (inputTargets.length === 0) {
output.error('Please select at least one Environment');
}
}
@@ -120,13 +137,15 @@ export default async function add(
envTargets.length === 1 &&
envTargets[0] === 'preview'
) {
envGitBranch = await client.input.text({
const { inputValue } = await client.prompt({
type: 'input',
name: 'inputValue',
message: `Add ${envName} to which Git branch? (leave empty for all Preview branches)?`,
});
envGitBranch = inputValue || '';
}
const type = opts['--sensitive'] ? 'sensitive' : 'encrypted';
const upsert = opts['--force'] ? 'true' : '';
const addStamp = stamp();
try {
@@ -135,7 +154,6 @@ export default async function add(
output,
client,
project.id,
upsert,
type,
envName,
envValue,
@@ -152,11 +170,9 @@ export default async function add(
output.print(
`${prependEmoji(
`${
opts['--force'] ? 'Overrode' : 'Added'
} Environment Variable ${chalk.bold(envName)} to Project ${chalk.bold(
project.name
)} ${chalk.gray(addStamp())}`,
`Added Environment Variable ${chalk.bold(
envName
)} to Project ${chalk.bold(project.name)} ${chalk.gray(addStamp())}`,
emoji('success')
)}\n`
);

View File

@@ -43,14 +43,6 @@ export const envCommand: Command = {
deprecated: false,
multi: false,
},
{
name: 'force',
description: 'Force overwrites when a command would normally fail',
shorthand: null,
type: 'boolean',
deprecated: false,
multi: false,
},
],
examples: [],
},
@@ -134,10 +126,6 @@ export const envCommand: Command = {
`${packageName} env add DB_PASS production`,
],
},
{
name: 'Override an existing Environment Variable of same target (production, preview, deployment)',
value: `${packageName} env add API_TOKEN --force`,
},
{
name: 'Add a sensitive Environment Variable',
value: `${packageName} env add API_TOKEN --sensitive`,

View File

@@ -35,7 +35,6 @@ export default async function main(client: Client) {
'--environment': String,
'--git-branch': String,
'--sensitive': Boolean,
'--force': Boolean,
});
} catch (error) {
handleError(error);

View File

@@ -29,6 +29,9 @@ export default async function rm(
args: string[],
output: Output
) {
// improve the way we show inquirer prompts
require('../../util/input/patch-inquirer');
if (args.length > 3) {
output.error(
`Invalid number of arguments. Usage: ${getCommandName(
@@ -40,11 +43,19 @@ export default async function rm(
let [envName, envTarget, envGitBranch] = args;
if (!envName) {
envName = await client.input.text({
while (!envName) {
const { inputName } = await client.prompt({
type: 'input',
name: 'inputName',
message: `Whats 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)) {
@@ -75,7 +86,9 @@ export default async function rm(
}
while (envs.length > 1) {
const id = await client.input.select({
const { id } = await client.prompt({
name: 'id',
type: 'list',
message: `Remove ${envName} from which Environments?`,
choices: envs.map(env => ({ value: env.id, name: formatEnvTarget(env) })),
});

View File

@@ -1,7 +1,6 @@
import chalk from 'chalk';
import { LOGO, NAME } from '@vercel-internals/constants';
import Table, { CellOptions } from 'cli-table3';
import { noBorderChars } from '../util/output/table';
const INDENT = ' '.repeat(2);
const NEWLINE = '\n';
@@ -40,7 +39,23 @@ type _CellOptions = CellOptions & {
};
const tableOptions = {
chars: noBorderChars,
chars: {
top: '',
'top-mid': '',
'top-left': '',
'top-right': '',
bottom: '',
'bottom-mid': '',
'bottom-left': '',
'bottom-right': '',
left: '',
'left-mid': '',
mid: '',
'mid-mid': '',
right: '',
'right-mid': '',
middle: '',
},
style: {
'padding-left': 0,
'padding-right': 0,

View File

@@ -6,7 +6,7 @@ import chalk from 'chalk';
// @ts-ignore
import listInput from '../../util/input/list';
import listItem from '../../util/output/list-item';
import confirm from '../../util/input/confirm';
import promptBool from '../../util/input/prompt-bool';
import toHumanPath from '../../util/humanize-path';
import Client from '../../util/client';
import info from '../../util/output/info';
@@ -46,10 +46,6 @@ 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:',
@@ -126,7 +122,7 @@ async function extractExample(
ver: string = 'v2'
) {
const { output } = client;
const folder = prepareFolder(client.cwd, dir || name, force);
const folder = prepareFolder(process.cwd(), dir || name, force);
output.spinner(`Fetching ${name}`);
const url = `${EXAMPLE_API}/${ver}/download/${name}.tar.gz`;
@@ -151,7 +147,7 @@ async function extractExample(
const successLog = `Initialized "${chalk.bold(
name
)}" example in ${chalk.bold(toHumanPath(folder))}.`;
const folderRel = path.relative(client.cwd, folder);
const folderRel = path.relative(process.cwd(), folder);
const deployHint =
folderRel === ''
? listItem(`To deploy, run ${getCommandName()}.`)
@@ -213,14 +209,14 @@ async function guess(client: Client, exampleList: string[], name: string) {
)} to see the list of available examples.`
);
if (client.stdin.isTTY !== true) {
if (process.stdout.isTTY !== true) {
throw GuessError;
}
const found = didYouMean(name, exampleList, 0.7);
if (typeof found === 'string') {
if (await confirm(client, `Did you mean ${chalk.bold(found)}?`, false)) {
if (await promptBool(`Did you mean ${chalk.bold(found)}?`, client)) {
return found;
}
} else {

View File

@@ -1,11 +1,12 @@
import chalk from 'chalk';
import ms from 'ms';
import table from '../../util/output/table';
import table from 'text-table';
import title from 'title';
import Now from '../../util';
import getArgs from '../../util/get-args';
import { handleError } from '../../util/error';
import elapsed from '../../util/output/elapsed';
import strlen from '../../util/strlen';
import toHost from '../../util/to-host';
import parseMeta from '../../util/parse-meta';
import { isValidName } from '../../util/is-valid-name';
@@ -274,7 +275,11 @@ export default async function list(client: Client) {
app === null ? filterUniqueApps() : () => true
),
],
{ hsep: 5 }
{
align: ['l', 'l', 'l', 'l', 'l'],
hsep: ' '.repeat(5),
stringLength: strlen,
}
).replace(/^/gm, ' ')}\n\n`
);

View File

@@ -1,10 +1,11 @@
import chalk from 'chalk';
import ms from 'ms';
import table from '../../util/output/table';
import table from 'text-table';
import type { Project } from '@vercel-internals/types';
import Client from '../../util/client';
import getCommandFlags from '../../util/get-command-flags';
import { getCommandName } from '../../util/pkg-name';
import strlen from '../../util/strlen';
import { NODE_VERSIONS } from '@vercel/build-utils';
export default async function list(
@@ -99,7 +100,11 @@ export default async function list(
])
.flat(),
],
{ hsep: 3 }
{
align: ['l', 'l', 'l'],
hsep: ' '.repeat(3),
stringLength: strlen,
}
).replace(/^/gm, ' ');
output.print(`\n${tablePrint}\n\n`);

View File

@@ -34,7 +34,7 @@ export default async function requestPromote({
if (deployment.target !== 'production' && !yes) {
const question =
'This deployment is not a production deployment and cannot be directly promoted. A new deployment will be built using your production environment. Are you sure you want to continue?';
'This deployment does not target production, therefore promotion will not apply production environment variables. Are you sure you want to continue?';
const answer = await confirm(client, question, false);
if (!answer) {
output.error('Canceled');
@@ -43,7 +43,7 @@ export default async function requestPromote({
}
// request the promotion
await client.fetch(`/v10/projects/${project.id}/promote/${deployment.id}`, {
await client.fetch(`/v9/projects/${project.id}/promote/${deployment.id}`, {
body: {}, // required
json: false,
method: 'POST',

View File

@@ -1,7 +1,7 @@
import chalk from 'chalk';
import ms from 'ms';
import plural from 'pluralize';
import table from '../../util/output/table';
import table from 'text-table';
import Now from '../../util';
import getAliases from '../../util/alias/get-aliases';
import elapsed from '../../util/output/elapsed';
@@ -169,7 +169,7 @@ export default async function remove(client: Client) {
`or projects matching ` +
`${ids
.map(id => chalk.bold(`"${id}"`))
.join(', ')}. Run ${getCommandName('projects ls')} to list.`
.join(', ')}. Run ${getCommandName('ls')} to list.`
);
return 1;
}
@@ -245,7 +245,7 @@ function readConfirmation(
const url = depl.url ? chalk.underline(`https://${depl.url}`) : '';
return [` ${depl.id}`, url, time];
}),
{ align: ['l', 'r', 'l'], hsep: 6 }
{ align: ['l', 'r', 'l'], hsep: ' '.repeat(6) }
);
output.print(`${deploymentTable}\n`);
}
@@ -277,7 +277,7 @@ function readConfirmation(
}
output.print(
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('(y/N) ')}`
`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[y/N] ')}`
);
process.stdin

View File

@@ -2,14 +2,9 @@ import { packageName, getCommandName } from '../../util/pkg-name';
export const secretsCommand = {
name: 'secrets',
description:
'WARNING: On May 1st, 2024 secrets will be automatically converted to sensitive Environment Variables for Preview and Production environments. Secrets attached to Development environments will not be migrated.\n' +
`The ${getCommandName(
'secrets'
)} command will be deprecated at this time, please use the ${getCommandName(
'env'
)} command instead.\n` +
'See https://vercel.com/changelog/legacy-environment-variable-secrets-are-being-sunset for more information.',
description: `NOTE: The ${getCommandName(
'env'
)} command is recommended instead of ${getCommandName('secrets')}`,
arguments: [
{
name: 'command',

View File

@@ -1,7 +1,8 @@
import isErrnoException from '@vercel/error-utils';
import chalk from 'chalk';
import table from '../../util/output/table';
import table from 'text-table';
import ms from 'ms';
import strlen from '../../util/strlen';
import { handleError, error } from '../../util/error';
import NowSecrets from '../../util/secrets';
import getScope from '../../util/get-scope';
@@ -77,12 +78,6 @@ async function run({ output, contextName, currentTeam, client }) {
const commandName = getCommandName('secret ' + subcommand);
output.warn(
'On May 1st, 2024 secrets will be automatically converted to sensitive Environment Variables for Preview and Production environments.\n' +
'Secrets attached to Development environments will not be migrated.' +
'See https://vercel.com/changelog/legacy-environment-variable-secrets-are-being-sunset for more information.'
);
if (subcommand === 'ls' || subcommand === 'list') {
output.note(
`The ${getCommandName(
@@ -123,7 +118,11 @@ async function run({ output, contextName, currentTeam, client }) {
chalk.gray(`${ms(cur - new Date(secret.created))} ago`),
])
),
{ hsep: 2 }
{
align: ['l', 'l', 'l'],
hsep: ' '.repeat(2),
stringLength: strlen,
}
);
if (out) {
@@ -280,7 +279,7 @@ async function readConfirmation(client, output, secret, contextName) {
const time = chalk.gray(`${ms(new Date() - new Date(secret.created))} ago`);
const tbl = table([[chalk.bold(secret.name), time]], {
align: ['r', 'l'],
hsep: 6,
hsep: ' '.repeat(6),
});
output.print(

View File

@@ -1,6 +1,5 @@
import chars from '../../util/output/chars';
import table from '../../util/output/table';
import { gray } from 'chalk';
import getUser from '../../util/get-user';
import getTeams from '../../util/teams/get-teams';
import { packageName } from '../../util/pkg-name';
@@ -54,7 +53,7 @@ export default async function list(client: Client): Promise<number> {
id,
name,
value: slug,
prefix: id === currentTeam ? chars.tick : ' ',
current: id === currentTeam ? chars.tick : '',
}));
if (user.version !== 'northstar') {
@@ -62,7 +61,7 @@ export default async function list(client: Client): Promise<number> {
id: user.id,
name: user.email,
value: user.username || user.email,
prefix: accountIsCurrent ? chars.tick : ' ',
current: accountIsCurrent ? chars.tick : '',
});
}
@@ -77,22 +76,14 @@ export default async function list(client: Client): Promise<number> {
output.stopSpinner();
client.stdout.write('\n'); // empty line
const teamTable = table(
[
['id', 'email / name'].map(str => gray(str)),
...teamList.map(team => [team.value, team.name]),
],
{ hsep: 5 }
table(
['', 'id', 'email / name'],
teamList.map(team => [team.current, team.value, team.name]),
[1, 5],
(str: string) => {
client.stdout.write(str);
}
);
client.stderr.write(
currentTeam
? teamTable
.split('\n')
.map((line, i) => `${i > 0 ? teamList[i - 1].prefix : ' '} ${line}`)
.join('\n')
: teamTable
);
client.stderr.write('\n');
if (pagination?.count === 20) {
const flags = getCommandFlags(argv, ['_', '--next', '-N', '-d']);

View File

@@ -1,10 +1,11 @@
import { frameworkList } from '@vercel/frameworks';
import frameworkList from '@vercel/frameworks';
export function sortBuilders<B extends { use: string }>(builds: B[]): B[] {
const frontendRuntimeSet = new Set(
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
);
const toNumber = (build: B) => (frontendRuntimeSet.has(build.use) ? 0 : 1);
return builds.sort((build1, build2) => {
return toNumber(build1) - toNumber(build2);
});

View File

@@ -1,9 +1,5 @@
import { bold, gray } from 'chalk';
import checkbox from '@inquirer/checkbox';
import confirm from '@inquirer/confirm';
import expand from '@inquirer/expand';
import input from '@inquirer/input';
import select from '@inquirer/select';
import { bold } from 'chalk';
import inquirer from 'inquirer';
import { EventEmitter } from 'events';
import { URL } from 'url';
import { VercelConfig } from '@vercel/client';
@@ -70,8 +66,8 @@ export default class Client extends EventEmitter implements Stdio {
agent?: Agent;
localConfig?: VercelConfig;
localConfigPath?: string;
prompt!: inquirer.PromptModule;
requestIdCounter: number;
input;
constructor(opts: ClientOptions) {
super();
@@ -87,29 +83,7 @@ export default class Client extends EventEmitter implements Stdio {
this.localConfig = opts.localConfig;
this.localConfigPath = opts.localConfigPath;
this.requestIdCounter = 1;
const theme = {
prefix: gray('?'),
style: { answer: gray },
};
this.input = {
text: (opts: Parameters<typeof input>[0]) =>
input({ theme, ...opts }, { input: this.stdin, output: this.stderr }),
checkbox: <T>(opts: Parameters<typeof checkbox<T>>[0]) =>
checkbox<T>(
{ theme, ...opts },
{ input: this.stdin, output: this.stderr }
),
expand: (opts: Parameters<typeof expand>[0]) =>
expand({ theme, ...opts }, { input: this.stdin, output: this.stderr }),
confirm: (opts: Parameters<typeof confirm>[0]) =>
confirm({ theme, ...opts }, { input: this.stdin, output: this.stderr }),
select: <T>(opts: Parameters<typeof select<T>>[0]) =>
select<T>(
{ theme, ...opts },
{ input: this.stdin, output: this.stderr }
),
};
this._createPromptModule();
}
retry<T>(fn: RetryFunction<T>, { retries = 3, maxTimeout = Infinity } = {}) {
@@ -255,6 +229,13 @@ export default class Client extends EventEmitter implements Stdio {
this.output.debug(`Retrying: ${error}\n${error.stack}`);
};
_createPromptModule() {
this.prompt = inquirer.createPromptModule({
input: this.stdin as NodeJS.ReadStream,
output: this.stderr as NodeJS.WriteStream,
});
}
get cwd(): string {
return process.cwd();
}

View File

@@ -30,7 +30,7 @@ const getGlobalPathConfig = (): string => {
];
// The customPath flag is the preferred location,
// followed by the vercel directory,
// followed by the the vercel directory,
// followed by the now directory.
// If none of those exist, use the vercel directory.
return (

View File

@@ -6,7 +6,7 @@ export default async function getPrebuiltJson(
directory: string
): Promise<BuildsManifest | null> {
try {
return await fs.readJSON(join(directory, 'builds.json'));
return await fs.readJSON(join(directory, '.vercel/output/builds.json'));
} catch (error) {
// ignoring error
}

View File

@@ -53,7 +53,6 @@ export default async function processDeployment({
withCache?: boolean;
org: Org;
prebuilt: boolean;
vercelOutputDir?: string;
projectName: string;
isSettingUpProject: boolean;
archive?: ArchiveFormat;
@@ -72,7 +71,6 @@ export default async function processDeployment({
withCache,
quiet,
prebuilt,
vercelOutputDir,
rootDirectory,
} = args;
@@ -94,7 +92,6 @@ export default async function processDeployment({
force,
withCache,
prebuilt,
vercelOutputDir,
rootDirectory,
skipAutoDetectionConfirmation,
archive,

View File

@@ -367,7 +367,7 @@ export async function executeBuild(
Code: { ZipFile },
Handler: asset.handler,
Runtime: asset.runtime,
MemorySize: asset.memory || 3009,
MemorySize: asset.memory || 3008,
Environment: {
Variables: {
...vercelConfig.env,

View File

@@ -45,7 +45,7 @@ import {
detectApiExtensions,
isOfficialRuntime,
} from '@vercel/fs-detectors';
import { frameworkList } from '@vercel/frameworks';
import frameworkList from '@vercel/frameworks';
import cmd from '../output/cmd';
import link from '../output/link';

View File

@@ -1,7 +1,7 @@
import chalk from 'chalk';
import type { DNSRecordData } from '@vercel-internals/types';
import textInput from '../input/text';
import confirm from '../input/confirm';
import promptBool from '../input/prompt-bool';
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 confirm(client, 'Is this correct?', false);
return promptBool('Is this correct?', client);
}
async function getRecordName(type: string) {

View File

@@ -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 confirm from '../input/confirm';
import promptBool from '../input/prompt-bool';
import purchaseDomain from './purchase-domain';
import stamp from '../output/stamp';
import * as ERRORS from '../errors-ts';
@@ -51,12 +51,11 @@ export default async function purchaseDomainIfAvailable(
);
if (
!(await confirm(
client,
!(await promptBool(
`Buy ${chalk.underline(domain)} for ${chalk.bold(
`$${price}`
)} (${plural('yr', period, true)})?`,
false
client
))
) {
output.print(eraseLines(1));

View File

@@ -10,16 +10,14 @@ export default async function addEnvRecord(
output: Output,
client: Client,
projectId: string,
upsert: string,
type: ProjectEnvType,
key: string,
value: string,
targets: ProjectEnvTarget[],
gitBranch: string
): Promise<void> {
const actionWord = upsert ? 'Overriding' : 'Adding';
output.debug(
`${actionWord} ${type} Environment Variable ${key} to ${targets.length} targets`
`Adding ${type} Environment Variable ${key} to ${targets.length} targets`
);
const body: Omit<ProjectEnvVariable, 'id'> = {
type,
@@ -28,8 +26,7 @@ export default async function addEnvRecord(
target: targets,
gitBranch: gitBranch || undefined,
};
const args = upsert ? `?upsert=${upsert}` : '';
const url = `/v10/projects/${projectId}/env${args}`;
const url = `/v8/projects/${projectId}/env`;
await client.fetch(url, {
method: 'POST',
body,

View File

@@ -48,7 +48,7 @@ export default async function getEnvRecords(
query.set('source', source);
}
const url = `/v10/projects/${projectId}/env?${query}`;
const url = `/v8/projects/${projectId}/env?${query}`;
return client.fetch<{ envs: ProjectEnvVariable[] }>(url);
}

View File

@@ -1,34 +1,12 @@
import { isErrnoException } from '@vercel/error-utils';
const knownErrorsCodes = new Set([
'PAYMENT_REQUIRED',
'BAD_REQUEST',
'ENV_ALREADY_EXISTS',
'ENV_CONFLICT',
'ENV_SHOULD_BE_A_SECRET',
'EXISTING_KEY_AND_TARGET',
'FORBIDDEN',
'ID_NOT_FOUND',
'INVALID_KEY',
'INVALID_VALUE',
'KEY_INVALID_CHARACTERS',
'KEY_INVALID_LENGTH',
'KEY_RESERVED',
'RESERVED_ENV_VARIABLE',
'MAX_ENVS_EXCEEDED',
'MISSING_ID',
'MISSING_KEY',
'MISSING_TARGET',
'MISSING_VALUE',
'NOT_AUTHORIZED',
'NOT_DECRYPTABLE',
'SECRET_MISSING',
'SYSTEM_ENV_WITH_VALUE',
'TEAM_NOT_FOUND',
'TOO_MANY_IDS',
'TOO_MANY_KEYS',
'UNKNOWN_ERROR',
'VALUE_INVALID_LENGTH',
'VALUE_INVALID_TYPE',
'RESERVED_ENV_VARIABLE',
'ENV_ALREADY_EXISTS',
'ENV_SHOULD_BE_A_SECRET',
]);
export function isKnownError(error: unknown) {

View File

@@ -10,9 +10,9 @@ export default async function removeEnvRecord(
): Promise<void> {
output.debug(`Removing Environment Variable ${env.key}`);
const url = `/v10/projects/${projectId}/env/${env.id}`;
const urlProject = `/v8/projects/${projectId}/env/${env.id}`;
await client.fetch<ProjectEnvVariable>(url, {
await client.fetch<ProjectEnvVariable>(urlProject, {
method: 'DELETE',
});
}

View File

@@ -1,8 +1,16 @@
import table from './output/table';
import { gray } from 'chalk';
import chalk from 'chalk';
import table from 'text-table';
import strlen from './strlen';
const HEADER = ['name', 'type', 'value'].map(v => gray(v));
const HEADER = ['name', 'type', 'value'].map(v => chalk.gray(v));
export default function formatDNSTable(rows: string[][]) {
return table([HEADER, ...rows], { hsep: 8 });
export default function formatDNSTable(
rows: string[][],
{ extraSpace = '' } = {}
) {
return table([HEADER, ...rows], {
align: ['l', 'l', 'l'],
hsep: ' '.repeat(8),
stringLength: strlen,
}).replace(/^(.*)/gm, `${extraSpace}$1`);
}

View File

@@ -1,5 +1,6 @@
import chalk from 'chalk';
import table from './output/table';
import table from 'text-table';
import strlen from './strlen';
import chars from './output/chars';
export default function formatNSTable(
@@ -34,6 +35,10 @@ export default function formatNSTable(
],
...rows,
],
{ hsep: 4 }
{
align: ['l', 'l', 'l', 'l'],
hsep: ' '.repeat(4),
stringLength: strlen,
}
).replace(/^(.*)/gm, `${extraSpace}$1`);
}

View File

@@ -1,5 +1,5 @@
import chalk from 'chalk';
import table from './output/table';
import table from 'text-table';
import strlen from './strlen';
// header:
@@ -19,8 +19,9 @@ import strlen from './strlen';
// ]
export default function formatTable(
header: string[],
align: Array<'l' | 'r' | 'c'>,
blocks: { name?: string; rows: string[][] }[]
align: Array<'l' | 'r' | 'c' | '.'>,
blocks: { name?: string; rows: string[][] }[],
hsep = ' '
) {
const nrCols = header.length;
const padding = [];
@@ -56,7 +57,7 @@ export default function formatTable(
rows[i][j] = al === 'l' ? col + pad : pad + col;
}
}
out += table(rows, { align, hsep: 4 });
out += table(rows, { align, hsep, stringLength: strlen });
}
out += '\n\n';
}

Some files were not shown because too many files have changed in this diff Show More