Compare commits

...

48 Commits

Author SHA1 Message Date
Vercel Release Bot
82231058da Version Packages (#10400)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-08 11:41:32 -05:00
Steven
61227bf7e3 fix .changeset/nice-lies-sip.md (#10474)
I think we need to remove `api` since its private so its not published to npm and therefore isn't versioned.
2023-09-08 02:09:11 +00:00
Zack Tanner
6aa0aa4e65 [next] fix ENOENT on /404.html when fallback: false w/ basePath (#10473)
The following error occurs during build when `basePath` is present in conjunction with `fallback: false` in `getStaticPaths`:

> Error: ENOENT: no such file or directory, open '/vercel/path0/.next/server/pages/404.html'

`localePrefixed404` was incorrectly being set to `false` because it was looking for `/<basePath>/<locale>/404.html` (when it's actually `/<locale>/404.html`)

This meant that inside `onPrerenderRoute`, `htmlFsRef` was pointing to `/404.html` rather than `/en/404.html`.
2023-09-08 00:17:08 +00:00
JJ Kasper
caaba0d685 [next] fix app dir edge functions with basePath (#10465)
x-ref: https://github.com/vercel/vercel/pull/10394
2023-09-07 22:03:12 +00:00
Steven
335fd70a68 [ci] Update codeowners (#10467)
Update codeowners for Next.js
2023-09-07 14:20:20 +00:00
Zack Tanner
c3c54d6e69 [next]: Fix RSC rewrite behavior (#10415)
- Removes some of the hacks from #10388 that were attempting to resolve an issue with RSC prefetches to `pages` routes in favor of adding rsc rewrites for all dynamic paths, and letting it fall through to a 404 if there's no match
- Fixes an issue where RSC requests were matching the wrong path (filesystem rather than RSC variant) introduced in above mentioned change
  - Closes https://github.com/vercel/next.js/issues/54698
2023-09-07 14:03:14 +00:00
Shu Uesugi
43048a0dd8 [CLI] Fix team URL on vercel help switch (#10466)
In `vercel help switch`, it suggests that team URL is of the format `vercel.com/teams/name`, but this will be 404. It should be `vercel.com/name`.
2023-09-07 13:12:54 +00:00
Sean Massa
60c75fd76c [CLI] show instant preview url on vc deploy and vc redeploy (#10458)
Show Instant Preview URLs immediately during `vc deploy`.

This does mean that we'll no longer show the nicer aliased URLs, but that's probably fine.

https://github.com/vercel/vercel/assets/41545/5d6d5695-60c3-49ca-a54d-a16828583070

---

- [Card](https://linear.app/vercel/issue/VCCLI-897/show-instant-preview-url-on-vc-deploy)
2023-09-06 23:46:44 +00:00
Trek Glowacki
bd1319d7a3 [cli] Update secrets.js to more current styles (#10461)
Updates the `secrets` command to be a bit more modern. Initially I was going to covert this to typescript but that change was quite large, so going stepwise for easier review.

1. Moves the command implementation into a directory like other commands
2. Shifts the command data structure into its own file
3. Adds a test.

Other relevant comments inline.
2023-09-06 20:58:57 +00:00
Nathan Rajlich
1138f7e3d1 Use esbuild for non-ncc'd packages (#10430)
The intention is for this to be a drop-in replacement for compiling TypeScript to JavaScript, but using `esbuild` instead of `tsc`. `tsc` is still needed, but only for the cases where we want to generate type definitions.
2023-09-06 19:49:50 +00:00
Ethan Arrowood
bb95cb9225 [cli] migrate teams command (#10434)
Before:
<img width="661" alt="Screenshot 2023-08-31 at 13 59 35" src="https://github.com/vercel/vercel/assets/16144158/7d16367a-662e-4ef1-8561-c197f4badf48">

After:
<img width="1036" alt="Screenshot 2023-08-31 at 14 00 23" src="https://github.com/vercel/vercel/assets/16144158/64431bdb-48ce-4bc1-8ed0-c719bdfbb350">
2023-09-06 16:15:35 +00:00
Trek Glowacki
0048eb999e [cli] N, not n. (#10460)
Followup to https://github.com/vercel/vercel/pull/10432#discussion_r1315482954
2023-09-06 15:42:37 +00:00
Espen Hovlandsdal
1b4de4a986 chore(deps): upgrade semver dependency (#10411)
Addresses ReDoS vulnerability: https://security.snyk.io/vuln/SNYK-JS-SEMVER-3247795
Uses the latest unaffected versions in the respective major versions, to prevent having to deal with any other breaking changes.
2023-09-06 13:37:37 +00:00
JJ Kasper
c9ad4084ee [next] Update page config test (#10456)
Updates failing test in https://github.com/vercel/vercel/actions/runs/6090040294/job/16525842631?pr=10430 per changes in https://github.com/vercel/next.js/pull/54786
2023-09-06 00:46:37 +00:00
Trek Glowacki
98ee6e4728 [cli] Migrate domains to new command structure (#10427)
After:
<img width="790" alt="CleanShot 2023-08-31 at 11 39 25@2x" src="https://github.com/vercel/vercel/assets/9736/b2e0e090-8c7c-4659-b1aa-1c59744d2eb1">

Before:
<img width="813" alt="CleanShot 2023-08-31 at 11 40 06@2x" src="https://github.com/vercel/vercel/assets/9736/731626a0-86f0-446d-8f77-436205acac87">
2023-09-05 21:11:03 +00:00
Vercel Release Bot
d7db0c5794 [tests] Upgrade Turbo to version 1.10.13 (#10404)
This auto-generated PR updates Turbo to version 1.10.13
2023-09-05 20:28:17 +00:00
Sean Massa
e90e922ee8 migrate dev command structure for help output (#10433)
Migrates the `vc git` command to the command data structure for use in the help output.

---

<img width="1891" alt="Screenshot 2023-08-31 at 1 35 07 PM" src="https://github.com/vercel/vercel/assets/41545/d3d63faa-9427-49e8-8137-a76d4c208cb3">
2023-09-05 19:51:44 +00:00
Trek Glowacki
adb9ac87ce [cli] Remove mri workaround (#10452)
As of https://github.com/vercel/vercel/pull/10389 the `mri` package is no longer used and this workaround can be removed.
2023-09-05 16:17:18 +00:00
Steven
e43191b186 [next] fix 404 enoent for i18n (#10416)
This PR fixes the following error:

```
Error: ENOENT: no such file or directory, open '/vercel/path0/.next/server/pages/en/404.html'
```


https://github.com/vercel/vercel/actions/runs/6030773334/job/16364078054?pr=10415#step:9:1352
2023-09-01 10:39:52 -04:00
Dan Stowell
a962e84409 migrate env to command structure (#10429)
Migrates the `vc env` command to the command data structure for use in the help output.
2023-08-31 23:10:28 +00:00
Trek Glowacki
7593e219fd [cli] Update project command to new structure (#10432)
Before:
<img width="687" alt="CleanShot 2023-08-31 at 13 29 29@2x" src="https://github.com/vercel/vercel/assets/9736/87e0f445-701a-4851-b73f-c787db01abe3">

After:
<img width="868" alt="CleanShot 2023-08-31 at 13 31 50@2x" src="https://github.com/vercel/vercel/assets/9736/b6820654-3254-4a65-820a-30ff7b577a44">
2023-08-31 22:45:44 +00:00
Dan Stowell
ec95066689 migrate vc secrets to help command structure (#10435) 2023-08-31 15:17:51 -07:00
Sean Massa
42a71416b9 migrate init command structure for help output (#10428)
Migrates the `vc init` command to the command data structure for use in the help output.

---

<img width="1891" alt="Screenshot 2023-08-31 at 11 36 37 AM" src="https://github.com/vercel/vercel/assets/41545/1caeb203-470f-49a5-86b2-273b04bc0489">
2023-08-31 21:48:09 +00:00
Sean Massa
80af30ce60 migrate git command structure for help output (#10431) 2023-08-31 16:02:49 -05:00
Sean Massa
74a15b5f32 migrate rollback command structure for help output (#10426)
Migrates the `vc rollback` command to the command data structure for use in the help output.

---

<img width="1891" alt="Screenshot 2023-08-31 at 11 25 49 AM" src="https://github.com/vercel/vercel/assets/41545/a6d802ac-3851-4641-b950-764fc65fa9d2">
2023-08-31 19:09:59 +00:00
Sean Massa
c0416f7e95 migrate promote command structure for help output (#10425)
Migrates the `vc promote` command to the command data structure for use in the help output.

---

<img width="1878" alt="Screenshot 2023-08-31 at 11 04 32 AM" src="https://github.com/vercel/vercel/assets/41545/b79c6aec-af03-4685-8ee4-9c0d89b2f236">
2023-08-31 18:41:55 +00:00
Kiko Beats
fc1e13c099 fix: remove console.log (#10417) 2023-08-31 16:34:27 +02:00
Nathan Rajlich
0e9ec194a3 Keep vercel@canary up to date with vercel@latest (#10410) 2023-08-28 22:50:30 -07:00
Sean Massa
5609a1187b [build-utils] add descriptions to NodeVersion properties (#10403) 2023-08-26 19:49:47 -05:00
Sean Massa
cff72e3129 [examples] fix redwood template and update examples to use at least node@16 (#10395)
The redwood template was broken because it would use node@18, which is not supported for the version of redwood used in the template. This PR updates that version to be node@16, which does work.

While we're at it, I also updated other examples to be at least node@16. I tested deployments of each of these and the all work.
2023-08-25 15:01:55 +00:00
Vercel Release Bot
d3c84e5d2a Version Packages (#10398)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-24 16:04:39 -05:00
Andrew Barba
9e3827c785 [build-utils] Support serverless function architecture (#10392)
# Problem

Framework authors often produce build outputs from platforms like Github
Actions or M1 Macs where the arm64 architecture is being used. They then
deploy these outputs to Vercel using `vercel deploy`, bypassing Vercel's
build system. Today they must cross compile to x86_64 in order to deploy
compatible Serverless functions to Vercel.

# Solution

Allow Framework authors to detect the current architecture and specify
either x86_64 or arm64 when deploying a Serverless function to Vercel.

# Related PRs

https://github.com/vercel/api/pull/21559

https://github.com/vercel/proxy/pull/6901

https://github.com/vercel/front/pull/24924
2023-08-24 16:44:30 -04:00
Trek Glowacki
fb6d77afac [cli] Improve error messages for JSON parse issues (#10396) 2023-08-24 15:09:13 -05:00
Vercel Release Bot
cfc1bb180b Version Packages (#10384)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-24 13:56:29 -05:00
Trek Glowacki
f06776468f [cli] Remove mri package (#10389)
`vc secrets` appears to be mostly deprecated but this was a fairly straightforward change that lets us drop `mri` today. Tested pretty extensively locally.
2023-08-24 18:05:11 +00:00
Kiko Beats
597a8a8176 upgrade edge-runtime (#10385) 2023-08-24 16:52:49 +02:00
Kiko Beats
3f6d99470d [node] use undici instead of node-fetch (#10387) 2023-08-24 10:06:33 +02:00
JJ Kasper
4422326865 Add handling to leverage RSC prefetch outputs (#10390)
Implements handling for the RSC prefetch outputs when available that
were added in https://github.com/vercel/next.js/pull/54403
2023-08-23 22:26:58 -07:00
Zack Tanner
09446a8fe8 [next] fix RSC matching behavior & 404 status code on fallback: false (#10388)
Fixes two separate issues for the Next builder:

- `pages` routes unexpectedly matching to RSC routes when prefetching from `app`. This update will attempt to match the route with the corresponding `pages` entry rather than falling back to a catch-all RSC
  - Fixes https://github.com/vercel/next.js/issues/53776
- `fallback: false` returning a successful status code when underlying page as a param (e.g. `/blog/[slug]` would 200 but `/blog/non-existent` would 404)
  - [slack x-ref](https://vercel.slack.com/archives/C03S8ED1DKM/p1692817762403579)
2023-08-23 22:30:33 +00:00
Vercel Release Bot
37e93a91a8 [remix] Update @remix-run/dev to v1.19.3 (#10381)
This auto-generated PR updates `@remix-run/dev` to version 1.19.3.
2023-08-22 20:49:48 +00:00
Trek Glowacki
eec6e47232 [cli] Update dns commands to new structure (#10379)
Before:
<img width="795" alt="CleanShot 2023-08-22 at 10 46 34@2x" src="https://github.com/vercel/vercel/assets/9736/456faef8-6335-46ac-89ae-5ce13db4568e">


After:
<img width="815" alt="CleanShot 2023-08-22 at 10 48 04@2x" src="https://github.com/vercel/vercel/assets/9736/e78a9cc5-d9e9-4079-bd4a-81cd68917127">
2023-08-22 20:24:19 +00:00
Vercel Release Bot
3a0cfce669 Version Packages (#10375)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-22 14:43:00 -05:00
Maz
ae4a9535c1 [cli] Add --git-branch to pull command help output (#10382)
Improves the help for pull command by adding --git-branch to the output.
2023-08-22 12:27:29 -07:00
Sean Massa
c615423a0b [frameworks] move some devDependencies to dependencies (#10380)
Because `frameworks` isn't bundled with `ncc`, we need the runtime dependencies to exist in the `dependencies` section of `package.json`.
2023-08-22 17:31:19 +00:00
Steven
96f99c7147 [error-utils] fix files in package.json to use dist (#10378)
These packages were publishing unnecessary files to npm so we can reduce to only the `dist` directory.

- Example: https://unpkg.com/browse/@vercel/error-utils@2.0.0/
- Docs: https://docs.npmjs.com/cli/v9/configuring-npm/package-json#files
2023-08-22 17:04:57 +00:00
Trek Glowacki
8f318d44cb Migrate certs to new command structure (#10377)
Co-authored-by: Trek Glowacki <trek.glowacki@vercel.com>
2023-08-22 10:33:36 -05:00
Vercel Release Bot
ade5e4ea0a [examples][tests] Upgrade Next.js to version 13.4.19 (#10373)
This auto-generated PR updates 3 packages to Next.js version 13.4.19
2023-08-21 23:55:07 +00:00
Trek Glowacki
87dee36ef9 [cli] Update new --help structure to support subcommands (#10372)
Before:
<img width="727" alt="CleanShot 2023-08-21 at 11 07 25@2x" src="https://github.com/vercel/vercel/assets/9736/1ff4b5b8-75e3-4fcb-b44a-7172e7612ecc">

After:
<img width="759" alt="CleanShot 2023-08-21 at 11 13 21@2x" src="https://github.com/vercel/vercel/assets/9736/acdd954a-6137-4535-8fbb-db025491156b">

Some notes re: "Before"

* We've dropped wrapping required args in `<>` some time ago.
* The command name for alias is optional (default is `set`) but was incorrectly still listed as required.
2023-08-21 21:31:02 +00:00
167 changed files with 3334 additions and 1671 deletions

4
.github/CODEOWNERS vendored
View File

@@ -5,12 +5,12 @@
* @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek * @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek
/.github/workflows @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek @ijjk /.github/workflows @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek @ijjk
/packages/fs-detectors @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek @agadzik @chloetedder /packages/fs-detectors @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek @agadzik @chloetedder
/packages/next @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek @ijjk /packages/next @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek @ijjk @ztanner
/packages/routing-utils @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek @ijjk /packages/routing-utils @TooTallNate @EndangeredMassa @styfle @cb1kenobi @Ethan-Arrowood @trek @ijjk
/packages/edge @vercel/compute /packages/edge @vercel/compute
/examples @leerob /examples @leerob
/examples/create-react-app @Timer /examples/create-react-app @Timer
/examples/nextjs @timneutkens @ijjk @styfle /examples/nextjs @timneutkens @ijjk @styfle @ztanner
/examples/hugo @styfle /examples/hugo @styfle
/examples/jekyll @styfle /examples/jekyll @styfle
/examples/zola @styfle /examples/zola @styfle

7
api/CHANGELOG.md Normal file
View File

@@ -0,0 +1,7 @@
# api
## 0.0.1
### Patch Changes
- fix RSC matching behavior & 404 status code on `fallback: false` ([#10388](https://github.com/vercel/vercel/pull/10388))

View File

@@ -1,7 +1,7 @@
{ {
"name": "api", "name": "api",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.1",
"description": "API for the vercel/vercel repo", "description": "API for the vercel/vercel repo",
"main": "index.js", "main": "index.js",
"scripts": {}, "scripts": {},

7
examples/CHANGELOG.md vendored Normal file
View File

@@ -0,0 +1,7 @@
# examples
## null
### Patch Changes
- update examples to use at least node@16 ([#10395](https://github.com/vercel/vercel/pull/10395))

View File

@@ -8,13 +8,13 @@
"name": "nextjs", "name": "nextjs",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@types/node": "20.5.0", "@types/node": "20.5.1",
"@types/react": "18.2.20", "@types/react": "18.2.20",
"@types/react-dom": "18.2.7", "@types/react-dom": "18.2.7",
"autoprefixer": "10.4.15", "autoprefixer": "10.4.15",
"eslint": "8.47.0", "eslint": "8.47.0",
"eslint-config-next": "13.4.18", "eslint-config-next": "13.4.19",
"next": "13.4.18", "next": "13.4.19",
"postcss": "8.4.28", "postcss": "8.4.28",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
@@ -178,22 +178,22 @@
} }
}, },
"node_modules/@next/env": { "node_modules/@next/env": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.19.tgz",
"integrity": "sha512-ZUG5Y/KSSerggdeD2LIYgiYziKTuSE9oE2RnW8bhNw6WunA8MrVfrWaCDTYSx/UG8qzPpSF+BiZNiHUiALxCdA==" "integrity": "sha512-FsAT5x0jF2kkhNkKkukhsyYOrRqtSxrEhfliniIq0bwWbuXLgyt3Gv0Ml+b91XwjwArmuP7NxCiGd++GGKdNMQ=="
}, },
"node_modules/@next/eslint-plugin-next": { "node_modules/@next/eslint-plugin-next": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.19.tgz",
"integrity": "sha512-GlOmUjZYYTjKl782mKk5a0bYEmKaouGaxPhi6t9yDILqrppU7JTIyONzLKQPszRXDCVZge0NFd4gwRs1ARZsMg==", "integrity": "sha512-N/O+zGb6wZQdwu6atMZHbR7T9Np5SUFUjZqCbj0sXm+MwQO35M8TazVB4otm87GkXYs2l6OPwARd3/PUWhZBVQ==",
"dependencies": { "dependencies": {
"glob": "7.1.7" "glob": "7.1.7"
} }
}, },
"node_modules/@next/swc-darwin-arm64": { "node_modules/@next/swc-darwin-arm64": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.19.tgz",
"integrity": "sha512-d/73jvZe7dNTjLugDsIIy2AdQrwE2dFC9/QRr7yHmFm8mS5EiIHeDKzaqIsv9+JXKD9ZB1i/c0x7+F0PlKo1vQ==", "integrity": "sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -206,9 +206,9 @@
} }
}, },
"node_modules/@next/swc-darwin-x64": { "node_modules/@next/swc-darwin-x64": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.19.tgz",
"integrity": "sha512-PwfvxgxG5rvUJppF02IdVAVx4HTtbZrS/Nz9qHfYfeFOQ9a+PijL8Xr9BJ21jiIS+dPQjwzvpsOdsC+DOrlzhg==", "integrity": "sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -221,9 +221,9 @@
} }
}, },
"node_modules/@next/swc-linux-arm64-gnu": { "node_modules/@next/swc-linux-arm64-gnu": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.19.tgz",
"integrity": "sha512-Nayn6yFeox9wKaRTLaWRvO3DjB8xEM3BnXu7QnQeZb0AgD484XmdxK13TYZW4jdNy3VJ5OyYIpL4mhkgWEVq/A==", "integrity": "sha512-vdlnIlaAEh6H+G6HrKZB9c2zJKnpPVKnA6LBwjwT2BTjxI7e0Hx30+FoWCgi50e+YO49p6oPOtesP9mXDRiiUg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -236,9 +236,9 @@
} }
}, },
"node_modules/@next/swc-linux-arm64-musl": { "node_modules/@next/swc-linux-arm64-musl": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.19.tgz",
"integrity": "sha512-sQzJ5DFPvGlKjI97R17v2RxKJYYzHw4lJZ4xhK6wvyYJYYcn9JfIMyKCvLtfLgpU1tOUcbkmx7i8XC28sB1BsQ==", "integrity": "sha512-aU0HkH2XPgxqrbNRBFb3si9Ahu/CpaR5RPmN2s9GiM9qJCiBBlZtRTiEca+DC+xRPyCThTtWYgxjWHgU7ZkyvA==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -251,9 +251,9 @@
} }
}, },
"node_modules/@next/swc-linux-x64-gnu": { "node_modules/@next/swc-linux-x64-gnu": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.19.tgz",
"integrity": "sha512-zqCLvGdz+T0V+set8zRHbkl3PQq0quUp5Dtuj1yGw0N9htp3beL1RVyhfSusbgxT82TRTXJe94IREgM8iYq6wg==", "integrity": "sha512-htwOEagMa/CXNykFFeAHHvMJeqZfNQEoQvHfsA4wgg5QqGNqD5soeCer4oGlCol6NGUxknrQO6VEustcv+Md+g==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -266,9 +266,9 @@
} }
}, },
"node_modules/@next/swc-linux-x64-musl": { "node_modules/@next/swc-linux-x64-musl": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.19.tgz",
"integrity": "sha512-V/+dWy32eo3iiWkro+0M4/vNp1anGrVzNp90teVKG5tl5t5qNGc/qWOgmgTG8JhowdJAxj7+fp+WltrcezqsDA==", "integrity": "sha512-4Gj4vvtbK1JH8ApWTT214b3GwUh9EKKQjY41hH/t+u55Knxi/0wesMzwQRhppK6Ddalhu0TEttbiJ+wRcoEj5Q==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -281,9 +281,9 @@
} }
}, },
"node_modules/@next/swc-win32-arm64-msvc": { "node_modules/@next/swc-win32-arm64-msvc": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.19.tgz",
"integrity": "sha512-anytZjyD1tAgfA/crOrVcUlm0yrSNKYKpg53NQ+Y83nAungrghBthZZiA1/QvmIs1Igu0Rqw/O6hqCOH63o8pw==", "integrity": "sha512-bUfDevQK4NsIAHXs3/JNgnvEY+LRyneDN788W2NYiRIIzmILjba7LaQTfihuFawZDhRtkYCv3JDC3B4TwnmRJw==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -296,9 +296,9 @@
} }
}, },
"node_modules/@next/swc-win32-ia32-msvc": { "node_modules/@next/swc-win32-ia32-msvc": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.19.tgz",
"integrity": "sha512-lgsZDjbU0FQQH2pDSYeKIbVX9g8dqA7fUtgcAcwbj4eEuVW/K41rKFQceMM1kt0ktVUZ4uF2qOHsgebOWpDJIw==", "integrity": "sha512-Y5kikILFAr81LYIFaw6j/NrOtmiM4Sf3GtOc0pn50ez2GCkr+oejYuKGcwAwq3jiTKuzF6OF4iT2INPoxRycEA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -311,9 +311,9 @@
} }
}, },
"node_modules/@next/swc-win32-x64-msvc": { "node_modules/@next/swc-win32-x64-msvc": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.18.tgz", "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.19.tgz",
"integrity": "sha512-cS72bVNqICglP/uEzqNy26lfRH30zf4AbqnnhPhe+UxRg6d+OTtRQpFX7C4xtBP09FKA+MSSflNVkrn2ZfaWrA==", "integrity": "sha512-YzA78jBDXMYiINdPdJJwGgPNT3YqBNNGhsthsDoWHL9p24tEJn9ViQf/ZqTbwSpX/RrkPupLfuuTH2sf73JBAw==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -376,9 +376,9 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.5.0", "version": "20.5.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz",
"integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==" "integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg=="
}, },
"node_modules/@types/prop-types": { "node_modules/@types/prop-types": {
"version": "15.7.5", "version": "15.7.5",
@@ -1112,9 +1112,9 @@
} }
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.495", "version": "1.4.496",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.495.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.496.tgz",
"integrity": "sha512-mwknuemBZnoOCths4GtpU/SDuVMp3uQHKa2UNJT9/aVD6WVRjGpXOxRGX7lm6ILIenTdGXPSTCTDaWos5tEU8Q==" "integrity": "sha512-qeXC3Zbykq44RCrBa4kr8v/dWzYJA8rAwpyh9Qd+NKWoJfjG5vvJqy9XOJ9H4P/lqulZBCgUWAYi+FeK5AuJ8g=="
}, },
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "9.2.2", "version": "9.2.2",
@@ -1316,11 +1316,11 @@
} }
}, },
"node_modules/eslint-config-next": { "node_modules/eslint-config-next": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.18.tgz", "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.19.tgz",
"integrity": "sha512-G15CYbsIHwV6Fzoly5SXo/Mj3pNqNkOzbf+wQcPod3LgVNviWVYlb9czjdiREXHq2VF6oV79Kv0Wunguj6RMEw==", "integrity": "sha512-WE8367sqMnjhWHvR5OivmfwENRQ1ixfNE9hZwQqNCsd+iM3KnuMc1V8Pt6ytgjxjf23D+xbesADv9x3xaKfT3g==",
"dependencies": { "dependencies": {
"@next/eslint-plugin-next": "13.4.18", "@next/eslint-plugin-next": "13.4.19",
"@rushstack/eslint-patch": "^1.1.3", "@rushstack/eslint-patch": "^1.1.3",
"@typescript-eslint/parser": "^5.4.2 || ^6.0.0", "@typescript-eslint/parser": "^5.4.2 || ^6.0.0",
"eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-node": "^0.3.6",
@@ -1407,9 +1407,9 @@
} }
}, },
"node_modules/eslint-plugin-import": { "node_modules/eslint-plugin-import": {
"version": "2.28.0", "version": "2.28.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz",
"integrity": "sha512-B8s/n+ZluN7sxj9eUf7/pRFERX0r5bnFA2dCaLHy2ZeaQEAz0k+ZZkFWRFHJAqxfxQDx6KLv9LeIki7cFdwW+Q==", "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==",
"dependencies": { "dependencies": {
"array-includes": "^3.1.6", "array-includes": "^3.1.6",
"array.prototype.findlastindex": "^1.2.2", "array.prototype.findlastindex": "^1.2.2",
@@ -1420,13 +1420,12 @@
"eslint-import-resolver-node": "^0.3.7", "eslint-import-resolver-node": "^0.3.7",
"eslint-module-utils": "^2.8.0", "eslint-module-utils": "^2.8.0",
"has": "^1.0.3", "has": "^1.0.3",
"is-core-module": "^2.12.1", "is-core-module": "^2.13.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
"minimatch": "^3.1.2", "minimatch": "^3.1.2",
"object.fromentries": "^2.0.6", "object.fromentries": "^2.0.6",
"object.groupby": "^1.0.0", "object.groupby": "^1.0.0",
"object.values": "^1.1.6", "object.values": "^1.1.6",
"resolve": "^1.22.3",
"semver": "^6.3.1", "semver": "^6.3.1",
"tsconfig-paths": "^3.14.2" "tsconfig-paths": "^3.14.2"
}, },
@@ -2425,9 +2424,9 @@
} }
}, },
"node_modules/jiti": { "node_modules/jiti": {
"version": "1.19.1", "version": "1.19.3",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.3.tgz",
"integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", "integrity": "sha512-5eEbBDQT/jF1xg6l36P+mWGGoH9Spuy0PCdSr2dtWRDGC6ph/w9ZCL4lmESW8f8F7MwT3XKescfP0wnZWAKL9w==",
"bin": { "bin": {
"jiti": "bin/jiti.js" "jiti": "bin/jiti.js"
} }
@@ -2639,11 +2638,11 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="
}, },
"node_modules/next": { "node_modules/next": {
"version": "13.4.18", "version": "13.4.19",
"resolved": "https://registry.npmjs.org/next/-/next-13.4.18.tgz", "resolved": "https://registry.npmjs.org/next/-/next-13.4.19.tgz",
"integrity": "sha512-V/IIFA/znYYnOFlZQegrlhlWRpyIuCLXLGuH6pzCjwyxThNBZl4ItqoE3ffUyYY9f0X6XIQ2dX6UUBpNVSKZ8A==", "integrity": "sha512-HuPSzzAbJ1T4BD8e0bs6B9C1kWQ6gv8ykZoRWs5AQoiIuqbGHHdQO7Ljuvg05Q0Z24E2ABozHe6FxDvI6HfyAw==",
"dependencies": { "dependencies": {
"@next/env": "13.4.18", "@next/env": "13.4.19",
"@swc/helpers": "0.5.1", "@swc/helpers": "0.5.1",
"busboy": "1.6.0", "busboy": "1.6.0",
"caniuse-lite": "^1.0.30001406", "caniuse-lite": "^1.0.30001406",
@@ -2659,15 +2658,15 @@
"node": ">=16.8.0" "node": ">=16.8.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"@next/swc-darwin-arm64": "13.4.18", "@next/swc-darwin-arm64": "13.4.19",
"@next/swc-darwin-x64": "13.4.18", "@next/swc-darwin-x64": "13.4.19",
"@next/swc-linux-arm64-gnu": "13.4.18", "@next/swc-linux-arm64-gnu": "13.4.19",
"@next/swc-linux-arm64-musl": "13.4.18", "@next/swc-linux-arm64-musl": "13.4.19",
"@next/swc-linux-x64-gnu": "13.4.18", "@next/swc-linux-x64-gnu": "13.4.19",
"@next/swc-linux-x64-musl": "13.4.18", "@next/swc-linux-x64-musl": "13.4.19",
"@next/swc-win32-arm64-msvc": "13.4.18", "@next/swc-win32-arm64-msvc": "13.4.19",
"@next/swc-win32-ia32-msvc": "13.4.18", "@next/swc-win32-ia32-msvc": "13.4.19",
"@next/swc-win32-x64-msvc": "13.4.18" "@next/swc-win32-x64-msvc": "13.4.19"
}, },
"peerDependencies": { "peerDependencies": {
"@opentelemetry/api": "^1.1.0", "@opentelemetry/api": "^1.1.0",
@@ -3672,9 +3671,9 @@
} }
}, },
"node_modules/ts-api-utils": { "node_modules/ts-api-utils": {
"version": "1.0.1", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.2.tgz",
"integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==",
"engines": { "engines": {
"node": ">=16.13.0" "node": ">=16.13.0"
}, },
@@ -3699,9 +3698,9 @@
} }
}, },
"node_modules/tslib": { "node_modules/tslib": {
"version": "2.6.1", "version": "2.6.2",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
"integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
}, },
"node_modules/type-check": { "node_modules/type-check": {
"version": "0.4.0", "version": "0.4.0",

View File

@@ -9,13 +9,13 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@types/node": "20.5.0", "@types/node": "20.5.1",
"@types/react": "18.2.20", "@types/react": "18.2.20",
"@types/react-dom": "18.2.7", "@types/react-dom": "18.2.7",
"autoprefixer": "10.4.15", "autoprefixer": "10.4.15",
"eslint": "8.47.0", "eslint": "8.47.0",
"eslint-config-next": "13.4.18", "eslint-config-next": "13.4.19",
"next": "13.4.18", "next": "13.4.19",
"postcss": "8.4.28", "postcss": "8.4.28",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",

View File

@@ -9,6 +9,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "27.4.1", "@types/jest": "27.4.1",
"@vercel/frameworks": "2.0.0" "@vercel/frameworks": "2.0.1"
} },
"version": null
} }

View File

@@ -30,6 +30,6 @@
"wct-browser-legacy": "^1.0.0" "wct-browser-legacy": "^1.0.0"
}, },
"engines": { "engines": {
"node": ">=8.0" "node": ">=16.0"
} }
} }

View File

@@ -14,7 +14,7 @@
"extends": "@redwoodjs/eslint-config" "extends": "@redwoodjs/eslint-config"
}, },
"engines": { "engines": {
"node": ">=12", "node": "16.x",
"yarn": ">=1.15" "yarn": ">=1.15"
} }
} }

View File

@@ -27,6 +27,6 @@
"typescript": "^5.1.3" "typescript": "^5.1.3"
}, },
"engines": { "engines": {
"node": ">=14" "node": ">=16"
} }
} }

View File

@@ -46,6 +46,6 @@
] ]
}, },
"engines": { "engines": {
"node": ">=8.0.0 <17" "node": "16.x"
} }
} }

View File

@@ -5,7 +5,7 @@
"build": "vuepress build src" "build": "vuepress build src"
}, },
"engines": { "engines": {
"node": ">=14.0.0 <18.0.0" "node": ">=16.0.0 <18.0.0"
}, },
"devDependencies": { "devDependencies": {
"vuepress": "1.9.7" "vuepress": "1.9.7"

View File

@@ -4,6 +4,9 @@
"version": "1.0.4", "version": "1.0.4",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"main": "dist/index.js", "main": "dist/index.js",
"files": [
"dist"
],
"scripts": { "scripts": {
"build": "tsc -p tsconfig.json" "build": "tsc -p tsconfig.json"
}, },

View File

@@ -5,10 +5,10 @@
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"main": "dist/index.js", "main": "dist/index.js",
"files": [ "files": [
"dist/*" "dist"
], ],
"scripts": { "scripts": {
"build": "tsc", "build": "node ../../utils/build.mjs",
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail", "test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail",
"test-unit": "pnpm test tests/unit" "test-unit": "pnpm test tests/unit"
}, },

View File

@@ -1,7 +1,9 @@
{ {
"extends": "@vercel-internals/tsconfig", "extends": "@vercel-internals/tsconfig",
"compilerOptions": { "compilerOptions": {
"outDir": "dist" "outDir": "dist",
"declaration": true,
"emitDeclarationOnly": true
}, },
"include": ["src/**/*"] "include": ["src/**/*"]
} }

View File

@@ -1,5 +1,19 @@
# @vercel-internals/types # @vercel-internals/types
## 1.0.9
### Patch Changes
- Updated dependencies [[`5609a1187`](https://github.com/vercel/vercel/commit/5609a1187be9d6cf8d5f16825690c5ea72f17dc5), [`1b4de4a98`](https://github.com/vercel/vercel/commit/1b4de4a986f7a612aac834ebae3ec7bb9e9b8cf8)]:
- @vercel/build-utils@7.1.1
## 1.0.8
### Patch Changes
- Updated dependencies [[`9e3827c78`](https://github.com/vercel/vercel/commit/9e3827c785e1bc45f2bed421132167381481770f)]:
- @vercel/build-utils@7.1.0
## 1.0.7 ## 1.0.7
### Patch Changes ### Patch Changes

View File

@@ -1,13 +1,16 @@
{ {
"private": true, "private": true,
"name": "@vercel-internals/types", "name": "@vercel-internals/types",
"version": "1.0.7", "version": "1.0.9",
"types": "index.d.ts", "types": "index.d.ts",
"main": "index.d.ts", "main": "index.d.ts",
"files": [
"*.d.ts"
],
"dependencies": { "dependencies": {
"@types/node": "14.14.31", "@types/node": "14.14.31",
"@vercel-internals/constants": "1.0.4", "@vercel-internals/constants": "1.0.4",
"@vercel/build-utils": "7.0.0", "@vercel/build-utils": "7.1.1",
"@vercel/routing-utils": "3.0.0" "@vercel/routing-utils": "3.0.0"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -16,6 +16,7 @@
"buffer-replace": "1.0.0", "buffer-replace": "1.0.0",
"create-svelte": "2.0.1", "create-svelte": "2.0.1",
"dot": "1.1.3", "dot": "1.1.3",
"esbuild": "0.19.2",
"eslint": "8.14.0", "eslint": "8.14.0",
"eslint-config-prettier": "8.5.0", "eslint-config-prettier": "8.5.0",
"eslint-plugin-jest": "26.1.5", "eslint-plugin-jest": "26.1.5",
@@ -32,7 +33,7 @@
"source-map-support": "0.5.12", "source-map-support": "0.5.12",
"ts-eager": "2.0.2", "ts-eager": "2.0.2",
"ts-jest": "29.1.0", "ts-jest": "29.1.0",
"turbo": "1.10.12", "turbo": "1.10.13",
"typescript": "4.9.5" "typescript": "4.9.5"
}, },
"scripts": { "scripts": {
@@ -49,7 +50,7 @@
"prepare": "husky install", "prepare": "husky install",
"pack": "cd utils && node -r ts-eager/register ./pack.ts", "pack": "cd utils && node -r ts-eager/register ./pack.ts",
"ci:version": "changeset version && pnpm install --no-frozen-lockfile", "ci:version": "changeset version && pnpm install --no-frozen-lockfile",
"ci:publish": "pnpm publish -r && changeset tag" "ci:publish": "pnpm publish -r && node utils/update-canary-tags.mjs && changeset tag"
}, },
"lint-staged": { "lint-staged": {
"./{*,{api,packages,test,utils}/**/*}.{js,ts}": [ "./{*,{api,packages,test,utils}/**/*}.{js,ts}": [

View File

@@ -1,5 +1,19 @@
# @vercel/build-utils # @vercel/build-utils
## 7.1.1
### Patch Changes
- add descriptions to NodeVersion properties ([#10403](https://github.com/vercel/vercel/pull/10403))
- Updated semver dependency ([#10411](https://github.com/vercel/vercel/pull/10411))
## 7.1.0
### Minor Changes
- Support serverless function architecture ([#10392](https://github.com/vercel/vercel/pull/10392))
## 7.0.0 ## 7.0.0
### Major Changes ### Major Changes

View File

@@ -1,30 +0,0 @@
#!/usr/bin/env node
const fs = require('fs-extra');
const execa = require('execa');
const { join } = require('path');
async function main() {
const outDir = join(__dirname, 'dist');
// Start fresh
await fs.remove(outDir);
// Compile TypeScript
await execa('tsc', [], { stdio: 'inherit' });
// Run `ncc`
const mainDir = join(outDir, 'main');
await execa('ncc', ['build', 'src/index.ts', '-o', mainDir], {
stdio: 'inherit',
});
// Move compiled ncc file to out dir
await fs.rename(join(mainDir, 'index.js'), join(outDir, 'index.js'));
// Delete leftover "main" dir
await fs.remove(mainDir);
}
main().catch(err => {
console.error(err);
process.exit(1);
});

View File

@@ -0,0 +1,3 @@
import { tsc, esbuild } from '../../utils/build.mjs';
await Promise.all([tsc(), esbuild().then(() => esbuild({ bundle: true }))]);

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/build-utils", "name": "@vercel/build-utils",
"version": "7.0.0", "version": "7.1.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./dist/index.js", "main": "./dist/index.js",
"types": "./dist/index.d.js", "types": "./dist/index.d.js",
@@ -11,7 +11,7 @@
"directory": "packages/now-build-utils" "directory": "packages/now-build-utils"
}, },
"scripts": { "scripts": {
"build": "node build", "build": "node build.mjs",
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail", "test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail",
"test-unit": "pnpm test test/unit.*test.*", "test-unit": "pnpm test test/unit.*test.*",
"test-e2e": "pnpm test test/integration.test.ts" "test-e2e": "pnpm test test/integration.test.ts"
@@ -32,7 +32,7 @@
"@types/node-fetch": "^2.1.6", "@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0", "@types/semver": "6.0.0",
"@types/yazl": "2.4.2", "@types/yazl": "2.4.2",
"@vercel/error-utils": "2.0.0", "@vercel/error-utils": "2.0.1",
"@vercel/ncc": "0.24.0", "@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1", "aggregate-error": "3.0.1",
"async-retry": "1.2.3", "async-retry": "1.2.3",
@@ -49,7 +49,7 @@
"minimatch": "3.1.2", "minimatch": "3.1.2",
"multistream": "2.1.1", "multistream": "2.1.1",
"node-fetch": "2.6.7", "node-fetch": "2.6.7",
"semver": "6.1.1", "semver": "6.3.1",
"typescript": "4.9.5", "typescript": "4.9.5",
"yazl": "2.5.1" "yazl": "2.5.1"
} }

View File

@@ -13,9 +13,12 @@ interface Environment {
export type LambdaOptions = LambdaOptionsWithFiles | LambdaOptionsWithZipBuffer; export type LambdaOptions = LambdaOptionsWithFiles | LambdaOptionsWithZipBuffer;
export type LambdaArchitecture = 'x86_64' | 'arm64';
export interface LambdaOptionsBase { export interface LambdaOptionsBase {
handler: string; handler: string;
runtime: string; runtime: string;
architecture?: LambdaArchitecture;
memory?: number; memory?: number;
maxDuration?: number; maxDuration?: number;
environment?: Environment; environment?: Environment;
@@ -62,6 +65,7 @@ export class Lambda {
files?: Files; files?: Files;
handler: string; handler: string;
runtime: string; runtime: string;
architecture?: LambdaArchitecture;
memory?: number; memory?: number;
maxDuration?: number; maxDuration?: number;
environment: Environment; environment: Environment;
@@ -81,6 +85,7 @@ export class Lambda {
handler, handler,
runtime, runtime,
maxDuration, maxDuration,
architecture,
memory, memory,
environment = {}, environment = {},
allowQuery, allowQuery,
@@ -102,6 +107,13 @@ export class Lambda {
assert(typeof runtime === 'string', '"runtime" is not a string'); assert(typeof runtime === 'string', '"runtime" is not a string');
assert(typeof environment === 'object', '"environment" is not an object'); assert(typeof environment === 'object', '"environment" is not an object');
if (architecture !== undefined) {
assert(
architecture === 'x86_64' || architecture === 'arm64',
'"architecture" must be either "x86_64" or "arm64"'
);
}
if (memory !== undefined) { if (memory !== undefined) {
assert(typeof memory === 'number', '"memory" is not a number'); assert(typeof memory === 'number', '"memory" is not a number');
} }
@@ -159,6 +171,7 @@ export class Lambda {
this.files = 'files' in opts ? opts.files : undefined; this.files = 'files' in opts ? opts.files : undefined;
this.handler = handler; this.handler = handler;
this.runtime = runtime; this.runtime = runtime;
this.architecture = architecture;
this.memory = memory; this.memory = memory;
this.maxDuration = maxDuration; this.maxDuration = maxDuration;
this.environment = environment; this.environment = environment;

View File

@@ -300,9 +300,13 @@ export interface PackageJson {
} }
export interface NodeVersion { export interface NodeVersion {
/** major version number: 18 */
major: number; major: number;
/** major version range: "18.x" */
range: string; range: string;
/** runtime descriptor: "nodejs18.x" */
runtime: string; runtime: string;
/** date beyond which this version is discontinued: 2023-08-17T19:05:45.951Z */
discontinueDate?: Date; discontinueDate?: Date;
} }

View File

@@ -1,6 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["ES2021"], "lib": ["ES2021"],
"module": "commonjs", "module": "commonjs",

View File

@@ -1,5 +1,96 @@
# vercel # vercel
## 32.2.0
### Minor Changes
- show instant preview url on deploy ([#10458](https://github.com/vercel/vercel/pull/10458))
### Patch Changes
- N, not n. ([#10460](https://github.com/vercel/vercel/pull/10460))
- Fix team URL on `vercel help switch` ([#10466](https://github.com/vercel/vercel/pull/10466))
- Migrates the vc env command to the command data structure for use in the help output. ([#10429](https://github.com/vercel/vercel/pull/10429))
- Update domains command to new structure ([#10427](https://github.com/vercel/vercel/pull/10427))
- Updated semver dependency ([#10411](https://github.com/vercel/vercel/pull/10411))
- migrate `rollback` command structure for help output ([#10426](https://github.com/vercel/vercel/pull/10426))
- migrate `inti` command structure for help output ([#10428](https://github.com/vercel/vercel/pull/10428))
- Remove mri workaround ([#10452](https://github.com/vercel/vercel/pull/10452))
- migrate dev command structure for help output ([#10433](https://github.com/vercel/vercel/pull/10433))
- Update secrets to more recent structure ([#10461](https://github.com/vercel/vercel/pull/10461))
- Migrate `vc secrets` to new help command structure ([#10435](https://github.com/vercel/vercel/pull/10435))
- migrate `promote` command structure for help output ([#10425](https://github.com/vercel/vercel/pull/10425))
- migrate `git` command structure for help output ([#10431](https://github.com/vercel/vercel/pull/10431))
- Update project command to new data structure ([#10432](https://github.com/vercel/vercel/pull/10432))
- migrate teams command ([#10434](https://github.com/vercel/vercel/pull/10434))
- Updated dependencies [[`5609a1187`](https://github.com/vercel/vercel/commit/5609a1187be9d6cf8d5f16825690c5ea72f17dc5), [`caaba0d68`](https://github.com/vercel/vercel/commit/caaba0d6855eff4350b6a04acc3ea502025bff8f), [`1b4de4a98`](https://github.com/vercel/vercel/commit/1b4de4a986f7a612aac834ebae3ec7bb9e9b8cf8), [`c3c54d6e6`](https://github.com/vercel/vercel/commit/c3c54d6e695ec078777c4b1f4f23acbeee3c3b09), [`6aa0aa4e6`](https://github.com/vercel/vercel/commit/6aa0aa4e65b81903f4fce677a198dcfaebee744b), [`e43191b18`](https://github.com/vercel/vercel/commit/e43191b1866da70a3dab3815a3f2176942240ef3), [`fc1e13c09`](https://github.com/vercel/vercel/commit/fc1e13c09928c654410b373fc1775c2b63c6ef4a)]:
- @vercel/build-utils@7.1.1
- @vercel/next@4.0.2
- @vercel/static-build@2.0.4
- @vercel/redwood@2.0.1
- @vercel/remix-builder@2.0.3
- @vercel/ruby@2.0.1
- @vercel/node@3.0.4
## 32.1.0
### Minor Changes
- Improve error messages for JSON parse failures ([#10396](https://github.com/vercel/vercel/pull/10396))
### Patch Changes
- Updated dependencies [[`9e3827c78`](https://github.com/vercel/vercel/commit/9e3827c785e1bc45f2bed421132167381481770f)]:
- @vercel/build-utils@7.1.0
- @vercel/node@3.0.3
- @vercel/remix-builder@2.0.2
- @vercel/static-build@2.0.3
## 32.0.2
### Patch Changes
- Remove use of mri preferring use of arg package ([#10389](https://github.com/vercel/vercel/pull/10389))
- upgrade edge-runtime ([#10385](https://github.com/vercel/vercel/pull/10385))
- Update dns commands to new structure ([#10379](https://github.com/vercel/vercel/pull/10379))
- Updated dependencies [[`09446a8fe`](https://github.com/vercel/vercel/commit/09446a8fe8b8201dbe3ead3ca645ef0aa1833b6b), [`597a8a817`](https://github.com/vercel/vercel/commit/597a8a81764c39e70c65b98e78bf4c3827a779a7), [`442232686`](https://github.com/vercel/vercel/commit/44223268651f1bbd5c6f2b0b315239685dd5716e), [`3f6d99470`](https://github.com/vercel/vercel/commit/3f6d99470db86681e006d66507f32afcea086b41), [`37e93a91a`](https://github.com/vercel/vercel/commit/37e93a91a8659934eac7f5cd441b310511bf5646)]:
- @vercel/next@4.0.1
- @vercel/node@3.0.2
- @vercel/remix-builder@2.0.1
- @vercel/static-build@2.0.2
## 32.0.1
### Patch Changes
- Add `--git-branch` to pull command help output ([#10382](https://github.com/vercel/vercel/pull/10382))
- Update new help structure to support subcommands ([#10372](https://github.com/vercel/vercel/pull/10372))
- Migrate certs command to new structure ([#10377](https://github.com/vercel/vercel/pull/10377))
- Updated dependencies []:
- @vercel/static-build@2.0.1
- @vercel/node@3.0.1
## 32.0.0 ## 32.0.0
### Major Changes ### Major Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "vercel", "name": "vercel",
"version": "32.0.0", "version": "32.2.0",
"preferGlobal": true, "preferGlobal": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"description": "The command-line interface for Vercel", "description": "The command-line interface for Vercel",
@@ -31,20 +31,20 @@
"node": ">= 16" "node": ">= 16"
}, },
"dependencies": { "dependencies": {
"@vercel/build-utils": "7.0.0", "@vercel/build-utils": "7.1.1",
"@vercel/go": "3.0.0", "@vercel/go": "3.0.0",
"@vercel/hydrogen": "1.0.0", "@vercel/hydrogen": "1.0.0",
"@vercel/next": "4.0.0", "@vercel/next": "4.0.2",
"@vercel/node": "3.0.0", "@vercel/node": "3.0.4",
"@vercel/python": "4.0.0", "@vercel/python": "4.0.0",
"@vercel/redwood": "2.0.0", "@vercel/redwood": "2.0.1",
"@vercel/remix-builder": "2.0.0", "@vercel/remix-builder": "2.0.3",
"@vercel/ruby": "2.0.0", "@vercel/ruby": "2.0.1",
"@vercel/static-build": "2.0.0" "@vercel/static-build": "2.0.4"
}, },
"devDependencies": { "devDependencies": {
"@alex_neo/jest-expect-message": "1.0.5", "@alex_neo/jest-expect-message": "1.0.5",
"@edge-runtime/node-utils": "2.1.0", "@edge-runtime/node-utils": "2.2.0",
"@next/env": "11.1.2", "@next/env": "11.1.2",
"@sentry/node": "5.5.0", "@sentry/node": "5.5.0",
"@sindresorhus/slugify": "0.11.0", "@sindresorhus/slugify": "0.11.0",
@@ -64,10 +64,10 @@
"@types/inquirer": "7.3.1", "@types/inquirer": "7.3.1",
"@types/jest": "27.4.1", "@types/jest": "27.4.1",
"@types/jest-expect-message": "1.0.3", "@types/jest-expect-message": "1.0.3",
"@types/json-parse-better-errors": "1.0.0",
"@types/load-json-file": "2.0.7", "@types/load-json-file": "2.0.7",
"@types/mime-types": "2.1.0", "@types/mime-types": "2.1.0",
"@types/minimatch": "3.0.3", "@types/minimatch": "3.0.3",
"@types/mri": "1.1.0",
"@types/ms": "0.7.30", "@types/ms": "0.7.30",
"@types/node": "14.18.33", "@types/node": "14.18.33",
"@types/node-fetch": "2.5.10", "@types/node-fetch": "2.5.10",
@@ -86,11 +86,11 @@
"@types/yauzl-promise": "2.1.0", "@types/yauzl-promise": "2.1.0",
"@vercel-internals/constants": "1.0.4", "@vercel-internals/constants": "1.0.4",
"@vercel-internals/get-package-json": "1.0.0", "@vercel-internals/get-package-json": "1.0.0",
"@vercel-internals/types": "1.0.7", "@vercel-internals/types": "1.0.9",
"@vercel/client": "13.0.0", "@vercel/client": "13.0.2",
"@vercel/error-utils": "2.0.0", "@vercel/error-utils": "2.0.1",
"@vercel/frameworks": "2.0.0", "@vercel/frameworks": "2.0.1",
"@vercel/fs-detectors": "5.0.0", "@vercel/fs-detectors": "5.0.2",
"@vercel/fun": "1.0.4", "@vercel/fun": "1.0.4",
"@vercel/ncc": "0.24.0", "@vercel/ncc": "0.24.0",
"@vercel/routing-utils": "3.0.0", "@vercel/routing-utils": "3.0.0",
@@ -136,12 +136,12 @@
"jaro-winkler": "0.2.8", "jaro-winkler": "0.2.8",
"jest-junit": "16.0.0", "jest-junit": "16.0.0",
"jest-matcher-utils": "29.3.1", "jest-matcher-utils": "29.3.1",
"json-parse-better-errors": "1.0.2",
"jsonlines": "0.1.1", "jsonlines": "0.1.1",
"line-async-iterator": "3.0.0", "line-async-iterator": "3.0.0",
"load-json-file": "3.0.0", "load-json-file": "3.0.0",
"mime-types": "2.1.24", "mime-types": "2.1.24",
"minimatch": "3.1.2", "minimatch": "3.1.2",
"mri": "1.1.5",
"ms": "2.1.2", "ms": "2.1.2",
"node-fetch": "2.6.7", "node-fetch": "2.6.7",
"npm-package-arg": "6.1.0", "npm-package-arg": "6.1.0",
@@ -156,7 +156,7 @@
"qr-image": "3.2.0", "qr-image": "3.2.0",
"raw-body": "2.4.1", "raw-body": "2.4.1",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"semver": "5.5.0", "semver": "5.7.2",
"serve-handler": "6.1.1", "serve-handler": "6.1.1",
"strip-ansi": "6.0.1", "strip-ansi": "6.0.1",
"supports-hyperlinks": "3.0.0", "supports-hyperlinks": "3.0.0",

View File

@@ -0,0 +1,93 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const aliasCommand: Command = {
name: 'alias',
description: 'Interact with deployment aliases.',
arguments: [
{
name: 'command',
required: false,
},
],
subcommands: [
{
name: 'ls',
description: 'Show all aliases.',
arguments: [],
options: [],
examples: [],
},
{
name: 'set',
description: 'Create a new alias',
arguments: [
{
name: 'deployment',
required: true,
},
{
name: 'alias',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'rm',
description: 'Remove an alias using its hostname.',
arguments: [
{
name: 'alias',
required: true,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'next',
description: 'Show next page of results',
argument: 'MS',
shorthand: 'n',
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'yes',
description: 'Skip the confirmation prompt when removing an alias',
shorthand: 'y',
type: 'boolean',
deprecated: false,
multi: false,
},
{
name: 'limit',
shorthand: 'n',
description:
'Number of results to return per page (default: 20, max: 100)',
argument: 'NUMBER',
type: 'string',
deprecated: false,
multi: false,
},
],
examples: [
{
name: 'Add a new alias to `my-api.vercel.app`',
value: `${packageName} alias set api-ownv3nc9f8.vercel.app my-api.vercel.app`,
},
{
name: 'Custom domains work as alias targets',
value: `${packageName} alias set api-ownv3nc9f8.vercel.app my-api.com`,
},
{
name: 'The subcommand `set` is the default and can be skipped. Protocols in the URLs are unneeded and ignored',
value: `${packageName} alias api-ownv3nc9f8.vercel.app my-api.com`,
},
],
};

View File

@@ -1,73 +1,12 @@
import chalk from 'chalk';
import { handleError } from '../../util/error'; import { handleError } from '../../util/error';
import Client from '../../util/client'; import Client from '../../util/client';
import getArgs from '../../util/get-args'; import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand'; import getSubcommand from '../../util/get-subcommand';
import { packageName, logo } from '../../util/pkg-name'; import { help } from '../help';
import ls from './ls'; import ls from './ls';
import rm from './rm'; import rm from './rm';
import set from './set'; import set from './set';
import { aliasCommand } from './command';
const help = () => {
console.log(`
${chalk.bold(`${logo} ${packageName} alias`)} [options] <command>
${chalk.dim('Commands:')}
ls Show all aliases
set <deployment> <alias> Create a new alias
rm <alias> Remove an alias using its hostname
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-S, --scope Set a custom scope
-N, --next Show next page of results
-y, --yes Skip the confirmation prompt when removing an alias
--limit=${chalk.bold.underline(
'VALUE'
)} Number of results to return per page (default: 20, max: 100)
${chalk.dim('Examples:')}
${chalk.gray('')} Add a new alias to ${chalk.underline('my-api.vercel.app')}
${chalk.cyan(
`$ ${packageName} alias set ${chalk.underline(
'api-ownv3nc9f8.vercel.app'
)} ${chalk.underline('my-api.vercel.app')}`
)}
Custom domains work as alias targets
${chalk.cyan(
`$ ${packageName} alias set ${chalk.underline(
'api-ownv3nc9f8.vercel.app'
)} ${chalk.underline('my-api.com')}`
)}
${chalk.dim('')} The subcommand ${chalk.dim(
'`set`'
)} is the default and can be skipped.
${chalk.dim('')} ${chalk.dim(
'Protocols'
)} in the URLs are unneeded and ignored.
`);
};
const COMMAND_CONFIG = { const COMMAND_CONFIG = {
default: ['set'], default: ['set'],
@@ -76,7 +15,7 @@ const COMMAND_CONFIG = {
set: ['set'], set: ['set'],
}; };
export default async function main(client: Client) { export default async function alias(client: Client) {
let argv; let argv;
try { try {
@@ -94,7 +33,7 @@ export default async function main(client: Client) {
} }
if (argv['--help']) { if (argv['--help']) {
help(); client.output.print(help(aliasCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }

View File

@@ -0,0 +1,116 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const certsCommand: Command = {
name: 'certs',
description:
'Interact with SSL certificates. This command is intended for advanced use only. By default, Vercel manages your certificates automatically.',
arguments: [
{
name: 'command',
required: false,
},
],
subcommands: [
{
name: 'ls',
description: 'Show all available certificates',
arguments: [],
options: [],
examples: [],
},
{
name: 'issue',
description: ' Issue a new certificate for a domain',
arguments: [
{
name: 'cn',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'rm',
description: 'Remove a certificate by id',
arguments: [
{
name: 'id',
required: true,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'challenge-only',
description: 'Only show challenges needed to issue a cert',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'crt',
description: 'Certificate file',
argument: 'FILE',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'key',
description: 'Certificate key file',
argument: 'FILE',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'ca',
description: 'CA certificate chain file',
argument: 'FILE',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'limit',
description:
'Number of results to return per page (default: 20, max: 100)',
argument: 'VALUE',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'next',
description: 'Show next page of results',
shorthand: 'n',
type: 'string',
deprecated: false,
multi: false,
},
],
examples: [
{
name: 'Generate a certificate with the cnames "acme.com" and "www.acme.com"`',
value: `${packageName} certs issue acme.com www.acme.com`,
},
{
name: 'Remove a certificate',
value: `${packageName} certs rm id`,
},
{
name: 'Paginate results, where `1584722256178` is the time in milliseconds since the UNIX epoch.',
value: `${packageName} certs ls --next 1584722256178`,
},
],
};

View File

@@ -1,5 +1,3 @@
import chalk from 'chalk';
// @ts-ignore // @ts-ignore
import { handleError } from '../../util/error'; import { handleError } from '../../util/error';
@@ -10,69 +8,9 @@ import add from './add';
import issue from './issue'; import issue from './issue';
import ls from './ls'; import ls from './ls';
import rm from './rm'; import rm from './rm';
import { certsCommand } from './command';
import { help } from '../help';
import Client from '../../util/client'; import Client from '../../util/client';
import { packageName, logo } from '../../util/pkg-name';
const help = () => {
console.log(`
${chalk.bold(`${logo} ${packageName} certs`)} [options] <command>
${chalk.yellow('NOTE:')} This command is intended for advanced use only.
By default, Vercel manages your certificates automatically.
${chalk.dim('Commands:')}
ls Show all available certificates
issue <cn> [<cn>] Issue a new certificate for a domain
rm <id> Remove a certificate by id
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-S, --scope Set a custom scope
--challenge-only Only show challenges needed to issue a cert
--crt ${chalk.bold.underline('FILE')} Certificate file
--key ${chalk.bold.underline(
'FILE'
)} Certificate key file
--ca ${chalk.bold.underline(
'FILE'
)} CA certificate chain file
-N, --next Show next page of results
--limit=${chalk.bold.underline(
'VALUE'
)} Number of results to return per page (default: 20, max: 100)
${chalk.dim('Examples:')}
${chalk.gray(
''
)} Generate a certificate with the cnames "acme.com" and "www.acme.com"
${chalk.cyan(`$ ${packageName} certs issue acme.com www.acme.com`)}
${chalk.gray('')} Remove a certificate
${chalk.cyan(`$ ${packageName} certs rm id`)}
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ ${packageName} certs ls --next 1584722256178`)}
`);
};
const COMMAND_CONFIG = { const COMMAND_CONFIG = {
add: ['add'], add: ['add'],
@@ -103,7 +41,7 @@ export default async function main(client: Client) {
} }
if (argv['--help']) { if (argv['--help']) {
help(); client.output.print(help(certsCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }
@@ -123,7 +61,9 @@ export default async function main(client: Client) {
return 1; return 1;
default: default:
output.error('Please specify a valid subcommand: ls | issue | rm'); output.error('Please specify a valid subcommand: ls | issue | rm');
help(); client.output.print(
help(certsCommand, { columns: client.stderr.columns })
);
return 2; return 2;
} }
} }

View File

@@ -0,0 +1,34 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const devCommand: Command = {
name: 'dev',
description: `Starts the \`${packageName} dev\` server.`,
arguments: [
{
name: 'dir',
required: false,
},
],
options: [
{
name: 'listen',
description: 'Specify a URI endpoint on which to listen [0.0.0.0:3000]',
argument: 'uri',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
],
examples: [
{
name: `Start the \`${packageName} dev\` server on port 8080`,
value: `${packageName} dev --listen 8080`,
},
{
name: 'Make the `vercel dev` server bind to localhost on port 5000',
value: `${packageName} dev --listen 127.0.0.1:5000 `,
},
],
};

View File

@@ -12,43 +12,16 @@ import highlight from '../../util/output/highlight';
import dev from './dev'; import dev from './dev';
import readConfig from '../../util/config/read-config'; import readConfig from '../../util/config/read-config';
import readJSONFile from '../../util/read-json-file'; import readJSONFile from '../../util/read-json-file';
import { packageName, getCommandName, logo } from '../../util/pkg-name'; import { packageName, getCommandName } from '../../util/pkg-name';
import { CantParseJSONFile } from '../../util/errors-ts'; import { CantParseJSONFile } from '../../util/errors-ts';
import { isErrnoException } from '@vercel/error-utils'; import { isErrnoException } from '@vercel/error-utils';
import { help } from '../help';
import { devCommand } from './command';
const COMMAND_CONFIG = { const COMMAND_CONFIG = {
dev: ['dev'], dev: ['dev'],
}; };
const help = () => {
console.log(`
${chalk.bold(`${logo} ${packageName} dev`)} [options] <dir>
Starts the \`${packageName} dev\` server.
${chalk.dim('Options:')}
-h, --help Output usage information
-d, --debug Debug mode [off]
--no-color No color mode [off]
-l, --listen [uri] Specify a URI endpoint on which to listen [0.0.0.0:3000]
-t, --token [token] Specify an Authorization Token
-y, --yes Skip questions when setting up new project using default scope and settings
${chalk.dim('Examples:')}
${chalk.gray('')} Start the \`${packageName} dev\` server on port 8080
${chalk.cyan(`$ ${packageName} dev --listen 8080`)}
${chalk.gray(
''
)} Make the \`vercel dev\` server bind to localhost on port 5000
${chalk.cyan(`$ ${packageName} dev --listen 127.0.0.1:5000`)}
`);
};
export default async function main(client: Client) { export default async function main(client: Client) {
if (process.env.__VERCEL_DEV_RUNNING) { if (process.env.__VERCEL_DEV_RUNNING) {
client.output.error( client.output.error(
@@ -100,7 +73,7 @@ export default async function main(client: Client) {
} }
if (argv['--help']) { if (argv['--help']) {
help(); client.output.print(help(devCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }
@@ -118,7 +91,7 @@ export default async function main(client: Client) {
const pkg = await readJSONFile<PackageJson>(path.join(dir, 'package.json')); const pkg = await readJSONFile<PackageJson>(path.join(dir, 'package.json'));
if (pkg instanceof CantParseJSONFile) { if (pkg instanceof CantParseJSONFile) {
client.output.error('Could not parse package.json'); client.output.error(pkg.message);
return 1; return 1;
} }

View File

@@ -0,0 +1,136 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const dnsCommand: Command = {
name: 'dns',
description: 'Interact with DNS entries for a project.',
arguments: [
{
name: 'command',
required: true,
},
],
subcommands: [
{
name: 'import',
description: 'Import a DNS zone file (see below for examples)',
arguments: [
{
name: 'domain',
required: true,
},
{
name: 'zonefile',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'ls',
description: 'List all DNS entries for a domain',
arguments: [
{
name: 'domain',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'add',
description: 'Add a new DNS entry (see below for examples)',
arguments: [
{
name: 'details',
required: true,
},
{
name: 'alias',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'rm',
description: 'Remove a DNS entry using its ID',
arguments: [
{
name: 'id',
required: true,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'next',
description: 'Show next page of results',
argument: 'MS',
shorthand: 'n',
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'limit',
shorthand: 'n',
description:
'Number of results to return per page (default: 20, max: 100)',
argument: 'NUMBER',
type: 'string',
deprecated: false,
multi: false,
},
],
examples: [
{
name: 'Add an A record for a subdomain',
value: [
`${packageName} dns add <DOMAIN> <SUBDOMAIN> <A | AAAA | ALIAS | CNAME | TXT> <VALUE>`,
`${packageName} dns add zeit.rocks api A 198.51.100.100`,
],
},
{
name: 'Add an MX record (@ as a name refers to the domain)',
value: [
`${packageName} dns add <DOMAIN> '@' MX <RECORD VALUE> <PRIORITY>`,
`${packageName} dns add zeit.rocks '@' MX mail.zeit.rocks 10`,
],
},
{
name: 'Add an SRV record',
value: [
`${packageName} dns add <DOMAIN> <NAME> SRV <PRIORITY> <WEIGHT> <PORT> <TARGET>`,
`${packageName} dns add zeit.rocks '@' SRV 10 0 389 zeit.party`,
],
},
{
name: 'Add a CAA record',
value: [
`${packageName} dns add <DOMAIN> <NAME> CAA '<FLAGS> <TAG> "<VALUE>"'`,
`${packageName} dns add zeit.rocks '@' CAA '0 issue "example.com"'`,
],
},
{
name: 'Import a Zone file',
value: [
`${packageName} dns import <DOMAIN> <FILE>`,
`${packageName} dns import zeit.rocks ./zonefile.txt`,
],
},
{
name: 'Paginate results, where `1584722256178` is the time in milliseconds since the UNIX epoch.',
value: [
`${packageName} dns ls --next 1584722256178`,
`${packageName} dns ls zeit.rocks --next 1584722256178`,
],
},
],
};

View File

@@ -1,96 +1,14 @@
import chalk from 'chalk';
import Client from '../../util/client'; import Client from '../../util/client';
import getArgs from '../../util/get-args'; import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand'; import getSubcommand from '../../util/get-subcommand';
import handleError from '../../util/handle-error'; import handleError from '../../util/handle-error';
import { packageName, logo } from '../../util/pkg-name';
import add from './add'; import add from './add';
import importZone from './import'; import importZone from './import';
import ls from './ls'; import ls from './ls';
import rm from './rm'; import rm from './rm';
import { dnsCommand } from './command';
const help = () => { import { help } from '../help';
console.log(`
${chalk.bold(`${logo} ${packageName} dns`)} [options] <command>
${chalk.dim('Commands:')}
add [details] Add a new DNS entry (see below for examples)
import [domain] [zonefile] Import a DNS zone file (see below for examples)
rm [id] Remove a DNS entry using its ID
ls [domain] List all DNS entries for a domain
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-S, --scope Set a custom scope
-N, --next Show next page of results
--limit=${chalk.bold.underline(
'VALUE'
)} Number of results to return per page (default: 20, max: 100)
${chalk.dim('Examples:')}
${chalk.gray('')} Add an A record for a subdomain
${chalk.cyan(
`$ ${packageName} dns add <DOMAIN> <SUBDOMAIN> <A | AAAA | ALIAS | CNAME | TXT> <VALUE>`
)}
${chalk.cyan(`$ ${packageName} dns add zeit.rocks api A 198.51.100.100`)}
${chalk.gray('')} Add an MX record (@ as a name refers to the domain)
${chalk.cyan(
`$ ${packageName} dns add <DOMAIN> '@' MX <RECORD VALUE> <PRIORITY>`
)}
${chalk.cyan(
`$ ${packageName} dns add zeit.rocks '@' MX mail.zeit.rocks 10`
)}
${chalk.gray('')} Add an SRV record
${chalk.cyan(
`$ ${packageName} dns add <DOMAIN> <NAME> SRV <PRIORITY> <WEIGHT> <PORT> <TARGET>`
)}
${chalk.cyan(
`$ ${packageName} dns add zeit.rocks '@' SRV 10 0 389 zeit.party`
)}
${chalk.gray('')} Add a CAA record
${chalk.cyan(
`$ ${packageName} dns add <DOMAIN> <NAME> CAA '<FLAGS> <TAG> "<VALUE>"'`
)}
${chalk.cyan(
`$ ${packageName} dns add zeit.rocks '@' CAA '0 issue "example.com"'`
)}
${chalk.gray('')} Import a Zone file
${chalk.cyan(`$ ${packageName} dns import <DOMAIN> <FILE>`)}
${chalk.cyan(`$ ${packageName} dns import zeit.rocks ./zonefile.txt`)}
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ ${packageName} dns ls --next 1584722256178`)}
${chalk.cyan(`$ ${packageName} dns ls zeit.rocks --next 1584722256178`)}
`);
};
const COMMAND_CONFIG = { const COMMAND_CONFIG = {
add: ['add'], add: ['add'],
@@ -99,7 +17,7 @@ const COMMAND_CONFIG = {
rm: ['rm', 'remove'], rm: ['rm', 'remove'],
}; };
export default async function main(client: Client) { export default async function dns(client: Client) {
let argv; let argv;
try { try {
@@ -114,7 +32,7 @@ export default async function main(client: Client) {
} }
if (argv['--help']) { if (argv['--help']) {
help(); client.output.print(help(dnsCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }

View File

@@ -0,0 +1,153 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const domainsCommand: Command = {
name: 'domains',
description: 'Manage domains',
arguments: [
{
name: 'command',
required: true,
},
],
subcommands: [
{
name: 'ls',
description: 'Show all domains in a list',
arguments: [],
options: [],
examples: [],
},
{
name: 'inspect',
description: 'Displays information related to a domain',
arguments: [
{
name: 'name',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'add',
description: 'Add a new domain that you already own',
arguments: [
{
name: 'name',
required: true,
},
{
name: 'project',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'rm',
description: 'Remove a domain',
arguments: [
{
name: 'name',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'buy',
description: "Buy a domain that you don't yet own",
arguments: [
{
name: 'name',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'move',
description: 'Move a domain to another user or team',
arguments: [
{
name: 'name',
required: true,
},
{
name: 'destination',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'transfer-in',
description: 'Transfer in a domain to Vercel',
arguments: [
{
name: 'name',
required: true,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'next',
description: 'Show next page of results',
shorthand: 'N',
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'yes',
description: 'Skip the confirmation prompt when removing a domain',
shorthand: 'y',
type: 'boolean',
deprecated: false,
multi: false,
},
{
name: 'limit',
shorthand: 'n',
description:
'Number of results to return per page (default: 20, max: 100)',
argument: 'NUMBER',
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'force',
shorthand: 'f',
type: 'boolean',
deprecated: false,
description:
'Force a domain on a project and remove it from an existing one',
multi: false,
},
],
examples: [
{
name: 'Add a domain that you already own',
value: [
`${packageName} domains add domain-name.com`,
"Make sure the domain's DNS nameservers are at least 2 of the ones listed on https://vercel.com/edge-network",
`NOTE: Running ${packageName} alias will automatically register your domain if it's configured with these nameservers (no need to 'domains add')`,
],
},
{
name: 'Paginate results, where `1584722256178` is the time in milliseconds since the UNIX epoch',
value: `${packageName} domains ls--next 1584722256178`,
},
],
};

View File

@@ -1,5 +1,3 @@
import chalk from 'chalk';
import Client from '../../util/client'; import Client from '../../util/client';
import getArgs from '../../util/get-args'; import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand'; import getSubcommand from '../../util/get-subcommand';
@@ -11,69 +9,8 @@ import inspect from './inspect';
import ls from './ls'; import ls from './ls';
import rm from './rm'; import rm from './rm';
import move from './move'; import move from './move';
import { packageName, logo } from '../../util/pkg-name'; import { domainsCommand } from './command';
import { help } from '../help';
const help = () => {
console.log(`
${chalk.bold(`${logo} ${packageName} domains`)} [options] <command>
${chalk.dim('Commands:')}
ls Show all domains in a list
inspect [name] Displays information related to a domain
add [name] [project] Add a new domain that you already own
rm [name] Remove a domain
buy [name] Buy a domain that you don't yet own
move [name] [destination] Move a domain to another user or team.
transfer-in [name] Transfer in a domain to Vercel
${chalk.dim('Options:')}
-h, --help Output usage information
-d, --debug Debug mode [off]
--no-color No color mode [off]
-f, --force Force a domain on a project and remove it from an existing one
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.vercel`'} directory
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-S, --scope Set a custom scope
-N, --next Show next page of results
--limit=${chalk.bold.underline(
'VALUE'
)} Number of results to return per page (default: 20, max: 100)
-y, --yes Skip the confirmation prompt when removing a domain
${chalk.dim('Examples:')}
${chalk.gray('')} Add a domain that you already own
${chalk.cyan(
`$ ${packageName} domains add ${chalk.underline('domain-name.com')}`
)}
Make sure the domain's DNS nameservers are at least 2 of the
ones listed on ${chalk.underline('https://vercel.com/edge-network')}.
${chalk.yellow('NOTE:')} Running ${chalk.dim(
`${packageName} alias`
)} will automatically register your domain
if it's configured with these nameservers (no need to ${chalk.dim(
'`domain add`'
)}).
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ ${packageName} domains ls --next 1584722256178`)}
`);
};
const COMMAND_CONFIG = { const COMMAND_CONFIG = {
add: ['add'], add: ['add'],
@@ -104,7 +41,9 @@ export default async function main(client: Client) {
} }
if (argv['--help']) { if (argv['--help']) {
help(); client.output.print(
help(domainsCommand, { columns: client.stderr.columns })
);
return 2; return 2;
} }

157
packages/cli/src/commands/env/command.ts vendored Normal file
View File

@@ -0,0 +1,157 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
import { getEnvTargetPlaceholder } from '../../util/env/env-target';
const targetPlaceholder = getEnvTargetPlaceholder();
export const envCommand: Command = {
name: 'env',
description: 'Interact with environment variables.',
arguments: [
{
name: 'command',
required: false,
},
],
subcommands: [
{
name: 'ls',
description: 'List all variables for the specified Environment',
arguments: [],
options: [],
examples: [],
},
{
name: 'add',
description: 'Add an Environment Variable (see examples below)',
arguments: [
{
name: 'name',
required: true,
},
{
name: 'environment',
required: false,
},
],
options: [],
examples: [],
},
{
name: 'rm',
description: 'Remove an Environment Variable (see examples below)',
arguments: [
{
name: 'name',
required: true,
},
{
name: 'environment',
required: false,
},
],
options: [],
examples: [],
},
{
name: 'pull',
description:
'Pull all Development Environment Variables from the cloud and write to a file [.env.local]',
arguments: [
{
name: 'filename',
required: false,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'environment',
description:
'Set the Environment (development, preview, production) when pulling Environment Variables',
shorthand: null,
type: 'boolean',
deprecated: false,
multi: false,
},
{
name: 'git-branch',
description:
'Specify the Git branch to pull specific Environment Variables for',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
{
name: 'yes',
description: 'Skip the confirmation prompt when removing an alias',
shorthand: 'y',
type: 'boolean',
deprecated: false,
multi: false,
},
],
examples: [
{
name: 'Pull all Development Environment Variables down from the cloud',
value: [
`${packageName} env pull <file>`,
`${packageName} env pull .env.development.local`,
],
},
{
name: 'Add a new variable to multiple Environments',
value: [
`${packageName} env add <name>`,
`${packageName} env add API_TOKEN`,
],
},
{
name: 'Add a new variable for a specific Environment',
value: [
`${packageName} env add <name> ${targetPlaceholder}`,
`${packageName} env add DB_PASS production`,
],
},
{
name: 'Add a new variable for a specific Environment and Git Branch',
value: [
`${packageName} env add <name> ${targetPlaceholder} <gitbranch>`,
`${packageName} env add DB_PASS preview feat1`,
],
},
{
name: 'Add a new Environment Variable from stdin',
value: [
`cat <file> | ${packageName} env add <name> ${targetPlaceholder}`,
`cat ~/.npmrc | ${packageName} env add NPM_RC preview`,
`${packageName} env add API_URL production < url.txt`,
],
},
{
name: 'Remove a variable from multiple Environments',
value: [
`${packageName} env rm <name>`,
`${packageName} env rm API_TOKEN`,
],
},
{
name: 'Remove a variable from a specific Environment',
value: [
`${packageName} env rm <name> ${targetPlaceholder}`,
`${packageName} env rm NPM_RC preview`,
],
},
{
name: 'Remove a variable from a specific Environment and Git Branch',
value: [
`${packageName} env rm <name> ${targetPlaceholder} <gitbranch>`,
`${packageName} env rm NPM_RC preview feat1`,
],
},
],
};

View File

@@ -8,99 +8,15 @@ import getArgs from '../../util/get-args';
import getInvalidSubcommand from '../../util/get-invalid-subcommand'; import getInvalidSubcommand from '../../util/get-invalid-subcommand';
import getSubcommand from '../../util/get-subcommand'; import getSubcommand from '../../util/get-subcommand';
import handleError from '../../util/handle-error'; import handleError from '../../util/handle-error';
import { getCommandName, packageName, logo } from '../../util/pkg-name'; import { help } from '../help';
import { getCommandName } from '../../util/pkg-name';
import { getLinkedProject } from '../../util/projects/link'; import { getLinkedProject } from '../../util/projects/link';
import add from './add'; import add from './add';
import ls from './ls'; import ls from './ls';
import pull from './pull'; import pull from './pull';
import rm from './rm'; import rm from './rm';
import { envCommand } from './command';
const help = () => {
const targetPlaceholder = getEnvTargetPlaceholder();
console.log(`
${chalk.bold(`${logo} ${packageName} env`)} [options] <command>
${chalk.dim('Commands:')}
ls [environment] [gitbranch] List all variables for the specified Environment
add [name] [environment] [gitbranch] Add an Environment Variable (see examples below)
rm [name] [environment] [gitbranch] Remove an Environment Variable (see examples below)
pull [filename] Pull all Development Environment Variables from the cloud and write to a file [.env.local]
${chalk.dim('Options:')}
-h, --help Output usage information
--environment Set the Environment (development, preview, production) when pulling Environment Variables
--git-branch Specify the Git branch to pull specific Environment Variables for
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-y, --yes Skip the confirmation prompt when overwriting env file on pull or removing an env variable
${chalk.dim('Examples:')}
${chalk.gray(
''
)} Pull all Development Environment Variables down from the cloud
${chalk.cyan(`$ ${packageName} env pull <file>`)}
${chalk.cyan(`$ ${packageName} env pull .env.development.local`)}
${chalk.gray('')} Add a new variable to multiple Environments
${chalk.cyan(`$ ${packageName} env add <name>`)}
${chalk.cyan(`$ ${packageName} env add API_TOKEN`)}
${chalk.gray('')} Add a new variable for a specific Environment
${chalk.cyan(`$ ${packageName} env add <name> ${targetPlaceholder}`)}
${chalk.cyan(`$ ${packageName} env add DB_PASS production`)}
${chalk.gray(
''
)} Add a new variable for a specific Environment and Git Branch
${chalk.cyan(
`$ ${packageName} env add <name> ${targetPlaceholder} <gitbranch>`
)}
${chalk.cyan(`$ ${packageName} env add DB_PASS preview feat1`)}
${chalk.gray('')} Add a new Environment Variable from stdin
${chalk.cyan(
`$ cat <file> | ${packageName} env add <name> ${targetPlaceholder}`
)}
${chalk.cyan(`$ cat ~/.npmrc | ${packageName} env add NPM_RC preview`)}
${chalk.cyan(`$ ${packageName} env add API_URL production < url.txt`)}
${chalk.gray('')} Remove a variable from multiple Environments
${chalk.cyan(`$ ${packageName} env rm <name>`)}
${chalk.cyan(`$ ${packageName} env rm API_TOKEN`)}
${chalk.gray('')} Remove a variable from a specific Environment
${chalk.cyan(`$ ${packageName} env rm <name> ${targetPlaceholder}`)}
${chalk.cyan(`$ ${packageName} env rm NPM_RC preview`)}
${chalk.gray(
''
)} Remove a variable from a specific Environment and Git Branch
${chalk.cyan(
`$ ${packageName} env rm <name> ${targetPlaceholder} <gitbranch>`
)}
${chalk.cyan(`$ ${packageName} env rm NPM_RC preview feat1`)}
`);
};
const COMMAND_CONFIG = { const COMMAND_CONFIG = {
ls: ['ls', 'list'], ls: ['ls', 'list'],
@@ -125,7 +41,7 @@ export default async function main(client: Client) {
} }
if (argv['--help']) { if (argv['--help']) {
help(); client.output.print(help(envCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }
@@ -177,7 +93,9 @@ export default async function main(client: Client) {
); );
default: default:
output.error(getInvalidSubcommand(COMMAND_CONFIG)); output.error(getInvalidSubcommand(COMMAND_CONFIG));
help(); client.output.print(
help(envCommand, { columns: client.stderr.columns })
);
return 2; return 2;
} }
} }

View File

@@ -24,6 +24,7 @@ import {
} from '../../util/env/diff-env-files'; } from '../../util/env/diff-env-files';
import { isErrnoException } from '@vercel/error-utils'; import { isErrnoException } from '@vercel/error-utils';
import { addToGitIgnore } from '../../util/link/add-to-gitignore'; import { addToGitIgnore } from '../../util/link/add-to-gitignore';
import JSONparse from 'json-parse-better-errors';
const CONTENTS_PREFIX = '# Created by Vercel CLI\n'; const CONTENTS_PREFIX = '# Created by Vercel CLI\n';
@@ -121,7 +122,7 @@ export default async function pull(
// We need this because double quotes are stripped from the local .env file, // We need this because double quotes are stripped from the local .env file,
// but `records` is already in the form of a JSON object that doesn't filter // but `records` is already in the form of a JSON object that doesn't filter
// double quotes. // double quotes.
const newEnv = JSON.parse(JSON.stringify(records).replace(/\\"/g, '')); const newEnv = JSONparse(JSON.stringify(records).replace(/\\"/g, ''));
deltaString = buildDeltaString(oldEnv, newEnv); deltaString = buildDeltaString(oldEnv, newEnv);
} }
} }

View File

@@ -0,0 +1,50 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const gitCommand: Command = {
name: 'git',
description: 'Manage your Git provider connections.',
arguments: [
{
name: 'command',
required: true,
},
],
subcommands: [
{
name: 'connect',
description:
'Connect your Vercel Project to your Git repository or provide the remote URL to your Git repository',
arguments: [
{
name: 'git url',
required: false,
},
],
options: [],
examples: [],
},
{
name: 'disconnect',
description: 'Disconnect the Git provider repository from your project',
arguments: [],
options: [],
examples: [],
},
],
options: [],
examples: [
{
name: 'Connect your Vercel Project to your Git repository defined in your local .git config',
value: `${packageName} git connect`,
},
{
name: 'Connect your Vercel Project to a Git repository using the remote URL',
value: `${packageName} git connect https://github.com/user/repo.git`,
},
{
name: 'Disconnect the Git provider repository',
value: `${packageName} git disconnect`,
},
],
};

View File

@@ -1,51 +1,12 @@
import chalk from 'chalk';
import Client from '../../util/client'; import Client from '../../util/client';
import { ensureLink } from '../../util/link/ensure-link'; import { ensureLink } from '../../util/link/ensure-link';
import getArgs from '../../util/get-args'; import getArgs from '../../util/get-args';
import getInvalidSubcommand from '../../util/get-invalid-subcommand'; import getInvalidSubcommand from '../../util/get-invalid-subcommand';
import handleError from '../../util/handle-error'; import handleError from '../../util/handle-error';
import { packageName, logo } from '../../util/pkg-name';
import connect from './connect'; import connect from './connect';
import disconnect from './disconnect'; import disconnect from './disconnect';
import { help } from '../help';
const help = () => { import { gitCommand } from './command';
console.log(`
${chalk.bold(`${logo} ${packageName} git`)} <command>
${chalk.dim('Commands:')}
connect [url] Connect your Vercel Project to your Git repository or provide the remote URL to your Git repository
disconnect Disconnect the Git provider repository from your project
${chalk.dim('Options:')}
-h, --help Output usage information
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-y, --yes Skip confirmation when connecting a Git provider
${chalk.dim('Examples:')}
${chalk.gray(
''
)} Connect your Vercel Project to your Git repository defined in your local .git config
${chalk.cyan(`$ ${packageName} git connect`)}
${chalk.gray(
''
)} Connect your Vercel Project to a Git repository using the remote URL
${chalk.cyan(
`$ ${packageName} git connect https://github.com/user/repo.git`
)}
${chalk.gray('')} Disconnect the Git provider repository
${chalk.cyan(`$ ${packageName} git disconnect`)}
`);
};
const COMMAND_CONFIG = { const COMMAND_CONFIG = {
connect: ['connect'], connect: ['connect'],
@@ -71,7 +32,7 @@ export default async function main(client: Client) {
} }
if (argv['--help']) { if (argv['--help']) {
help(); client.output.print(help(gitCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }
@@ -96,7 +57,7 @@ export default async function main(client: Client) {
return await disconnect(client, args, project, org); return await disconnect(client, args, project, org);
default: default:
output.error(getInvalidSubcommand(COMMAND_CONFIG)); output.error(getInvalidSubcommand(COMMAND_CONFIG));
help(); client.output.print(help(gitCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }
} }

View File

@@ -12,6 +12,7 @@ export interface CommandOption {
argument?: string; argument?: string;
deprecated: boolean; deprecated: boolean;
description?: string; description?: string;
/** supports multiple entries */
multi: boolean; multi: boolean;
} }
export interface CommandArgument { export interface CommandArgument {
@@ -26,6 +27,7 @@ export interface Command {
name: string; name: string;
description: string; description: string;
arguments: CommandArgument[]; arguments: CommandArgument[];
subcommands?: Command[];
options: CommandOption[]; options: CommandOption[];
examples: CommandExample[]; examples: CommandExample[];
} }
@@ -280,6 +282,69 @@ export function buildCommandOptionLines(
].join(''); ].join('');
} }
export function buildSubcommandLines(
subcommands: Command[] | undefined,
options: BuildHelpOutputOptions
) {
if (!subcommands) {
return null;
}
// word wrapping requires the wrapped cell to have a fixed width.
// We need to track cell sizes to ensure the final column of cells is
// equal to the remainder of unused horizontal space.
let maxWidthOfUnwrappedColumns = 0;
const rows: (string | undefined | _CellOptions)[][] = [];
for (const command of subcommands) {
const nameCell = `${INDENT}${command.name}`;
let argsCell = INDENT;
argsCell += command.arguments
.map(arg => {
return arg.required ? arg.name : `[${arg.name}]`;
})
.join(' ');
argsCell += INDENT;
const widthOfUnwrappedColumns = nameCell.length + argsCell.length;
maxWidthOfUnwrappedColumns = Math.max(
widthOfUnwrappedColumns,
maxWidthOfUnwrappedColumns
);
rows.push([
nameCell,
argsCell,
{
content: command.description,
wordWrap: true,
},
]);
}
// Really long descriptions go RIGHT up to the edge, which looks unpleasant.
const rightMargin = INDENT.repeat(4).length;
const finalColumnWidth =
options.columns - maxWidthOfUnwrappedColumns - rightMargin;
const table = new Table(
Object.assign({}, tableOptions, {
colWidths: [null, null, finalColumnWidth],
})
);
table.push(...rows);
return [
`${INDENT}${chalk.dim('Commands')}:`,
NEWLINE,
NEWLINE,
table.toString(),
NEWLINE,
NEWLINE,
].join('');
}
export function buildCommandExampleLines(command: Command) { export function buildCommandExampleLines(command: Command) {
const outputArray: string[] = [`${INDENT}${chalk.dim('Examples:')}`, '']; const outputArray: string[] = [`${INDENT}${chalk.dim('Examples:')}`, ''];
for (const example of command.examples) { for (const example of command.examples) {
@@ -324,6 +389,7 @@ export function buildHelpOutput(
'', '',
buildCommandSynopsisLine(command), buildCommandSynopsisLine(command),
buildDescriptionLine(command, options), buildDescriptionLine(command, options),
buildSubcommandLines(command.subcommands, options),
buildCommandOptionLines(command.options, options, 'Options'), buildCommandOptionLines(command.options, options, 'Options'),
buildCommandOptionLines(globalCommandOptions, options, 'Global Options'), buildCommandOptionLines(globalCommandOptions, options, 'Global Options'),
buildCommandExampleLines(command), buildCommandExampleLines(command),

View File

@@ -0,0 +1,47 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const initCommand: Command = {
name: 'init',
description: 'Initialize example Vercel Projects',
arguments: [
{
name: 'example',
required: false,
},
{
name: 'dir',
required: false,
},
],
subcommands: undefined,
options: [
{
name: 'force',
description: 'Overwrite destination directory if exists [off]',
argument: undefined,
shorthand: 'f',
type: 'boolean',
deprecated: false,
multi: false,
},
],
examples: [
{
name: 'Choose from all available examples',
value: `${packageName} init`,
},
{
name: 'Initialize example project into a new directory',
value: `${packageName} init <example>`,
},
{
name: 'Initialize example project into specified directory',
value: `${packageName} <example> <dir>`,
},
{
name: 'Initialize example project without checking',
value: `${packageName} init <example> --force`,
},
],
};

View File

@@ -1,48 +1,16 @@
import chalk from 'chalk';
import getArgs from '../../util/get-args'; import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand'; import getSubcommand from '../../util/get-subcommand';
import Client from '../../util/client'; import Client from '../../util/client';
import handleError from '../../util/handle-error'; import handleError from '../../util/handle-error';
import init from './init'; import init from './init';
import { packageName, logo } from '../../util/pkg-name';
import { isError } from '@vercel/error-utils'; import { isError } from '@vercel/error-utils';
import { help } from '../help';
import { initCommand } from './command';
const COMMAND_CONFIG = { const COMMAND_CONFIG = {
init: ['init'], init: ['init'],
}; };
const help = () => {
console.log(`
${chalk.bold(`${logo} ${packageName} init`)} [example] [dir] [-f | --force]
${chalk.dim('Options:')}
-h, --help Output usage information
-d, --debug Debug mode [off]
--no-color No color mode [off]
-f, --force Overwrite destination directory if exists [off]
${chalk.dim('Examples:')}
${chalk.gray('')} Choose from all available examples
${chalk.cyan(`$ ${packageName} init`)}
${chalk.gray('')} Initialize example project into a new directory
${chalk.cyan(`$ ${packageName} init <example>`)}
${chalk.gray('')} Initialize example project into specified directory
${chalk.cyan(`$ ${packageName} init <example> <dir>`)}
${chalk.gray('')} Initialize example project without checking
${chalk.cyan(`$ ${packageName} init <example> --force`)}
`);
};
export default async function main(client: Client) { export default async function main(client: Client) {
const { output } = client; const { output } = client;
let argv; let argv;
@@ -60,7 +28,7 @@ export default async function main(client: Client) {
} }
if (argv['--help']) { if (argv['--help']) {
help(); client.output.print(help(initCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }

View File

@@ -0,0 +1,67 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const projectCommand: Command = {
name: 'project',
description: 'Manage your Vercel Projects.',
arguments: [
{
name: 'command',
required: true,
},
],
subcommands: [
{
name: 'ls',
description: 'Show all projects in the selected team/user',
arguments: [],
options: [],
examples: [],
},
{
name: 'add',
description: 'Add a new project',
arguments: [
{
name: 'name',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'rm',
description: 'Remove a project',
arguments: [
{
name: 'name',
required: true,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'next',
description: 'Show next page of results',
argument: 'MS',
shorthand: 'N',
type: 'string',
deprecated: false,
multi: false,
},
],
examples: [
{
name: 'Add a new project',
value: `${packageName} project add my-project`,
},
{
name: 'Paginate projects, where `1584722256178` is the time in milliseconds since the UNIX epoch',
value: `${packageName} project ls --next 1584722256178`,
},
],
};

View File

@@ -1,46 +1,13 @@
import chalk from 'chalk';
import Client from '../../util/client'; import Client from '../../util/client';
import getArgs from '../../util/get-args'; import getArgs from '../../util/get-args';
import getInvalidSubcommand from '../../util/get-invalid-subcommand'; import getInvalidSubcommand from '../../util/get-invalid-subcommand';
import getScope from '../../util/get-scope'; import getScope from '../../util/get-scope';
import handleError from '../../util/handle-error'; import handleError from '../../util/handle-error';
import { packageName, logo } from '../../util/pkg-name'; import { help } from '../help';
import add from './add'; import add from './add';
import list from './list'; import list from './list';
import rm from './rm'; import rm from './rm';
import { projectCommand } from './command';
const help = () => {
console.log(`
${chalk.bold(`${logo} ${packageName} project`)} [options] <command>
${chalk.dim('Commands:')}
ls Show all projects in the selected team/user
add [name] Add a new project
rm [name] Remove a project
${chalk.dim('Options:')}
-h, --help Output usage information
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-S, --scope Set a custom scope
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Add a new project
${chalk.cyan(`$ ${packageName} project add my-project`)}
${chalk.gray('')} Paginate projects, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ ${packageName} project ls --next 1584722256178`)}
`);
};
const COMMAND_CONFIG = { const COMMAND_CONFIG = {
ls: ['ls', 'list'], ls: ['ls', 'list'],
@@ -63,7 +30,9 @@ export default async function main(client: Client) {
} }
if (argv['--help']) { if (argv['--help']) {
help(); client.output.print(
help(projectCommand, { columns: client.stderr.columns })
);
return 2; return 2;
} }
@@ -84,7 +53,9 @@ export default async function main(client: Client) {
return await rm(client, args); return await rm(client, args);
default: default:
output.error(getInvalidSubcommand(COMMAND_CONFIG)); output.error(getInvalidSubcommand(COMMAND_CONFIG));
help(); client.output.print(
help(projectCommand, { columns: client.stderr.columns })
);
return 2; return 2;
} }
} }

View File

@@ -0,0 +1,53 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const promoteCommand: Command = {
name: 'promote',
description: 'Promote an existing deployment to current.',
arguments: [
{
name: 'deployment id/url',
required: true,
},
],
subcommands: [
{
name: 'status',
description: 'Show the status of any current pending promotions',
arguments: [
{
name: 'project',
required: false,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'timeout',
description: 'Time to wait for promotion completion [3m]',
argument: 'timeout',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
],
examples: [
{
name: 'Show the status of any current pending promotions',
value: [
`${packageName} promote`,
`${packageName} promote status`,
`${packageName} promote status <project>`,
`${packageName} promote status --timeout 30s`,
],
},
{
name: 'Promote a deployment using id or url',
value: `${packageName} promote <deployment id/url>`,
},
],
};

View File

@@ -1,53 +1,13 @@
import chalk from 'chalk';
import type Client from '../../util/client'; import type Client from '../../util/client';
import getArgs from '../../util/get-args'; import getArgs from '../../util/get-args';
import getProjectByCwdOrLink from '../../util/projects/get-project-by-cwd-or-link'; import getProjectByCwdOrLink from '../../util/projects/get-project-by-cwd-or-link';
import { packageName, logo } from '../../util/pkg-name';
import handleError from '../../util/handle-error'; import handleError from '../../util/handle-error';
import { isErrnoException } from '@vercel/error-utils'; import { isErrnoException } from '@vercel/error-utils';
import ms from 'ms'; import ms from 'ms';
import requestPromote from './request-promote'; import requestPromote from './request-promote';
import promoteStatus from './status'; import promoteStatus from './status';
import { promoteCommand } from './command';
const help = () => { import { help } from '../help';
console.log(`
${chalk.bold(`${logo} ${packageName} promote`)} [deployment id/url]
Promote an existing deployment to current.
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
--timeout=${chalk.bold.underline(
'TIME'
)} Time to wait for promotion completion [3m]
-y, --yes Skip questions when setting up new project using default scope and settings
${chalk.dim('Examples:')}
${chalk.gray('')} Show the status of any current pending promotions
${chalk.cyan(`$ ${packageName} promote`)}
${chalk.cyan(`$ ${packageName} promote status`)}
${chalk.cyan(`$ ${packageName} promote status <project>`)}
${chalk.cyan(`$ ${packageName} promote status --timeout 30s`)}
${chalk.gray('')} Promote a deployment using id or url
${chalk.cyan(`$ ${packageName} promote <deployment id/url>`)}
`);
};
/** /**
* `vc promote` command * `vc promote` command
@@ -68,7 +28,9 @@ export default async (client: Client): Promise<number> => {
} }
if (argv['--help'] || argv._[0] === 'help') { if (argv['--help'] || argv._[0] === 'help') {
help(); client.output.print(
help(promoteCommand, { columns: client.stderr.columns })
);
return 2; return 2;
} }

View File

@@ -22,6 +22,16 @@ export const pullCommand: Command = {
deprecated: false, deprecated: false,
multi: false, multi: false,
}, },
{
name: 'git-branch',
description:
'Specify the Git branch to pull specific Environment Variables for',
argument: 'branch',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
{ {
name: 'yes', name: 'yes',
description: description:
@@ -45,6 +55,10 @@ export const pullCommand: Command = {
name: 'Pull for a specific environment', name: 'Pull for a specific environment',
value: `${packageName} pull --environment=${getEnvTargetPlaceholder()}`, value: `${packageName} pull --environment=${getEnvTargetPlaceholder()}`,
}, },
{
name: 'Pull for a preview feature branch',
value: `${packageName} pull --environment=preview --git-branch=feature-branch`,
},
{ {
name: 'If you want to download environment variables to a specific file, use `vercel env pull` instead', name: 'If you want to download environment variables to a specific file, use `vercel env pull` instead',
value: `${packageName} env pull`, value: `${packageName} env pull`,

View File

@@ -76,12 +76,23 @@ export default async function redeploy(client: Client): Promise<number> {
}); });
output.stopSpinner(); output.stopSpinner();
const isProdDeployment = deployment.target === 'production';
const previewUrl = `https://${deployment.url}`;
output.print( output.print(
`${prependEmoji( `${prependEmoji(
`Inspect: ${chalk.bold(deployment.inspectorUrl)} ${deployStamp()}`, `Inspect: ${chalk.bold(deployment.inspectorUrl)} ${deployStamp()}`,
emoji('inspect') emoji('inspect')
)}\n` )}\n`
); );
output.print(
prependEmoji(
`${isProdDeployment ? 'Production' : 'Preview'}: ${chalk.bold(
previewUrl
)} ${deployStamp()}`,
emoji('success')
) + `\n`
);
if (!client.stdout.isTTY) { if (!client.stdout.isTTY) {
client.stdout.write(`https://${deployment.url}`); client.stdout.write(`https://${deployment.url}`);

View File

@@ -0,0 +1,53 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const rollbackCommand: Command = {
name: 'rollback',
description: 'Quickly revert back to a previous deployment.',
arguments: [
{
name: 'deployment id/url',
required: true,
},
],
subcommands: [
{
name: 'status',
description: 'Show the status of any current pending rollbacks',
arguments: [
{
name: 'project',
required: false,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'timeout',
description: 'Time to wait for rollback completion [3m]',
argument: 'timeout',
shorthand: null,
type: 'string',
deprecated: false,
multi: false,
},
],
examples: [
{
name: 'Show the status of any current pending rollbacks',
value: [
`${packageName} rollback`,
`${packageName} rollback status`,
`${packageName} rollback status <project>`,
`${packageName} rollback status --timeout 30s`,
],
},
{
name: 'Rollback a deployment using id or url',
value: `${packageName} rollback <deployment id/url>`,
},
],
};

View File

@@ -1,53 +1,13 @@
import chalk from 'chalk';
import type Client from '../../util/client'; import type Client from '../../util/client';
import getArgs from '../../util/get-args'; import getArgs from '../../util/get-args';
import getProjectByCwdOrLink from '../../util/projects/get-project-by-cwd-or-link'; import getProjectByCwdOrLink from '../../util/projects/get-project-by-cwd-or-link';
import { packageName, logo } from '../../util/pkg-name';
import handleError from '../../util/handle-error'; import handleError from '../../util/handle-error';
import { isErrnoException } from '@vercel/error-utils'; import { isErrnoException } from '@vercel/error-utils';
import ms from 'ms'; import ms from 'ms';
import requestRollback from './request-rollback'; import requestRollback from './request-rollback';
import rollbackStatus from './status'; import rollbackStatus from './status';
import { help } from '../help';
const help = () => { import { rollbackCommand } from './command';
console.log(`
${chalk.bold(`${logo} ${packageName} rollback`)} [deployment id/url]
Quickly revert back to a previous deployment.
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
--timeout=${chalk.bold.underline(
'TIME'
)} Time to wait for rollback completion [3m]
-y, --yes Skip questions when setting up new project using default scope and settings
${chalk.dim('Examples:')}
${chalk.gray('')} Show the status of any current pending rollbacks
${chalk.cyan(`$ ${packageName} rollback`)}
${chalk.cyan(`$ ${packageName} rollback status`)}
${chalk.cyan(`$ ${packageName} rollback status <project>`)}
${chalk.cyan(`$ ${packageName} rollback status --timeout 30s`)}
${chalk.gray('')} Rollback a deployment using id or url
${chalk.cyan(`$ ${packageName} rollback <deployment id/url>`)}
`);
};
/** /**
* `vc rollback` command * `vc rollback` command
@@ -68,7 +28,9 @@ export default async (client: Client): Promise<number> => {
} }
if (argv['--help'] || argv._[0] === 'help') { if (argv['--help'] || argv._[0] === 'help') {
help(); client.output.print(
help(rollbackCommand, { columns: client.stderr.columns })
);
return 2; return 2;
} }

View File

@@ -0,0 +1,96 @@
import { packageName, getCommandName } from '../../util/pkg-name';
export const secretsCommand = {
name: 'secrets',
description: `NOTE: The ${getCommandName(
'env'
)} command is recommended instead of ${getCommandName('secrets')}`,
arguments: [
{
name: 'command',
required: false,
},
],
subcommands: [
{
name: 'ls',
description: 'Show all secrets in a list',
arguments: [],
options: [],
examples: [],
},
{
name: 'add',
description: 'Add a new secret',
arguments: [
{
name: 'name',
required: true,
},
{
name: 'value',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'rename',
description: 'Change the name of a secret',
arguments: [
{
name: 'old-name',
required: true,
},
{
name: 'new-name',
required: true,
},
],
options: [],
examples: [],
},
{
name: 'rm',
description: 'Remove a secret',
arguments: [
{
name: 'name',
required: true,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'next',
description: 'Show next page of results',
argument: 'MS',
shorthand: 'n',
type: 'string',
deprecated: false,
multi: false,
},
],
examples: [
{
name: 'Add a new secret',
value: `${packageName} secrets add my-secret "my value"
- Once added, a secret's value can't be retrieved in plain text anymore
- If the secret's value is more than one word, wrap it in quotes
- When in doubt, always wrap your value in quotes`,
},
{
name: 'Expose a secret as an environment variable (notice the `@` symbol)',
value: `${packageName} -e MY_SECRET=@my-secret`,
},
{
name: 'Paginate results, where 1584722256178 is the time in milliseconds since the UNIX epoch',
value: `$ ${packageName} secrets ls --next 1584722256178`,
},
],
};

View File

@@ -1,79 +1,17 @@
import isErrnoException from '@vercel/error-utils';
import chalk from 'chalk'; import chalk from 'chalk';
import table from 'text-table'; import table from 'text-table';
import mri from 'mri';
import ms from 'ms'; import ms from 'ms';
import strlen from '../util/strlen.ts'; import strlen from '../../util/strlen';
import { handleError, error } from '../util/error'; import { handleError, error } from '../../util/error';
import NowSecrets from '../util/secrets'; import NowSecrets from '../../util/secrets';
import exit from '../util/exit'; import getScope from '../../util/get-scope';
import getScope from '../util/get-scope.ts'; import confirm from '../../util/input/confirm';
import confirm from '../util/input/confirm'; import getCommandFlags from '../../util/get-command-flags';
import getCommandFlags from '../util/get-command-flags'; import { getCommandName } from '../../util/pkg-name';
import getPrefixedFlags from '../util/get-prefixed-flags'; import getArgs from '../../util/get-args';
import { packageName, getCommandName, logo } from '../util/pkg-name.ts'; import { help } from '../help';
import { secretsCommand } from './command';
const help = () => {
console.log(`
${chalk.yellow(
`${chalk.bold('NOTE:')} The ${getCommandName(
'env'
)} command is recommended instead of ${getCommandName('secrets')}`
)}
${chalk.bold(`${logo} ${packageName} secrets`)} [options] <command>
${chalk.dim('Commands:')}
ls Show all secrets in a list
add [name] [value] Add a new secret
rename [old-name] [new-name] Change the name of a secret
rm [name] Remove a secret
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
-t ${chalk.bold.underline('TOKEN')}, --token=${chalk.bold.underline(
'TOKEN'
)} Login token
-S, --scope Set a custom scope
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Add a new secret
${chalk.cyan(`$ ${packageName} secrets add my-secret "my value"`)}
${chalk.gray(
''
)} Once added, a secret's value can't be retrieved in plain text anymore
${chalk.gray(
''
)} If the secret's value is more than one word, wrap it in quotes
${chalk.gray('')} When in doubt, always wrap your value in quotes
${chalk.gray(
''
)} Expose a secret as an environment variable (notice the ${chalk.cyan.bold(
'`@`'
)} symbol)
${chalk.cyan(`$ ${packageName} -e MY_SECRET=${chalk.bold('@my-secret')}`)}
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch
${chalk.cyan(`$ ${packageName} secrets ls --next 1584722256178`)}
`);
};
// Options // Options
let argv; let argv;
@@ -81,14 +19,12 @@ let subcommand;
let nextTimestamp; let nextTimestamp;
const main = async client => { const main = async client => {
argv = mri(client.argv.slice(2), { argv = getArgs(client.argv.slice(2), {
boolean: ['help', 'debug', 'yes'], '--yes': Boolean,
alias: { '--next': Number,
help: 'h', '--test-warning': Boolean,
debug: 'd', '-y': '--yes',
yes: 'y', '-N': '--next',
next: 'N',
},
}); });
argv._ = argv._.slice(1); argv._ = argv._.slice(1);
@@ -97,8 +33,10 @@ const main = async client => {
nextTimestamp = argv.next; nextTimestamp = argv.next;
if (argv.help || !subcommand) { if (argv.help || !subcommand) {
help(); client.output.print(
await exit(2); help(secretsCommand, { columns: client.stderr.columns })
);
return 2;
} }
const { const {
@@ -110,9 +48,11 @@ const main = async client => {
try { try {
({ contextName } = await getScope(client)); ({ contextName } = await getScope(client));
} catch (err) { } catch (err) {
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') { if (isErrnoException(err)) {
output.error(err.message); if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
return 1; output.error(err.message);
return 1;
}
} }
throw err; throw err;
@@ -123,7 +63,7 @@ const main = async client => {
export default async client => { export default async client => {
try { try {
await main(client); return await main(client);
} catch (err) { } catch (err) {
handleError(err); handleError(err);
process.exit(1); process.exit(1);
@@ -134,7 +74,8 @@ async function run({ output, contextName, currentTeam, client }) {
const secrets = new NowSecrets({ client, currentTeam }); const secrets = new NowSecrets({ client, currentTeam });
const args = argv._.slice(1); const args = argv._.slice(1);
const start = Date.now(); const start = Date.now();
const { 'test-warning': testWarningFlag } = argv; const { '--test-warning': testWarningFlag } = argv;
const commandName = getCommandName('secret ' + subcommand); const commandName = getCommandName('secret ' + subcommand);
if (subcommand === 'ls' || subcommand === 'list') { if (subcommand === 'ls' || subcommand === 'list') {
@@ -185,19 +126,12 @@ async function run({ output, contextName, currentTeam, client }) {
); );
if (out) { if (out) {
console.log(`\n${out}\n`); client.output.print(`\n${out}\n`);
} }
} }
if (pagination && pagination.count === 20) { if (pagination && pagination.count === 20) {
const prefixedArgs = getPrefixedFlags(argv); const flags = getCommandFlags(argv, ['_', '--next', '-N', '-d', '-y']);
const flags = getCommandFlags(prefixedArgs, [
'_',
'--next',
'-N',
'-d',
'-y',
]);
const nextCmd = `secrets ${subcommand}${flags} --next ${pagination.next}`; const nextCmd = `secrets ${subcommand}${flags} --next ${pagination.next}`;
output.log(`To display the next page run ${getCommandName(nextCmd)}`); output.log(`To display the next page run ${getCommandName(nextCmd)}`);
} }
@@ -225,7 +159,7 @@ async function run({ output, contextName, currentTeam, client }) {
if (theSecret) { if (theSecret) {
const yes = const yes =
argv.yes || argv['--yes'] ||
(await readConfirmation(client, output, theSecret, contextName)); (await readConfirmation(client, output, theSecret, contextName));
if (!yes) { if (!yes) {
output.print(`Canceled. Secret not deleted.\n`); output.print(`Canceled. Secret not deleted.\n`);
@@ -307,19 +241,7 @@ async function run({ output, contextName, currentTeam, client }) {
return 1; return 1;
} }
const [name, parsedValue] = args; const [name, value] = args;
const [originalName, originalValue] = client.argv.slice(-2);
let value = parsedValue;
if (
name === originalName &&
typeof parsedValue === 'boolean' &&
parsedValue !== originalValue
) {
// Corner case where `mri` transforms the secret value into a boolean because
// it starts with a `-` so it thinks its a flag, so we use the original value instead.
value = originalValue;
}
if (typeof value === 'boolean') { if (typeof value === 'boolean') {
const example = chalk.cyan( const example = chalk.cyan(
@@ -349,7 +271,7 @@ async function run({ output, contextName, currentTeam, client }) {
console.error( console.error(
error('Please specify a valid subcommand: ls | add | rename | rm') error('Please specify a valid subcommand: ls | add | rename | rm')
); );
help(); client.output.print(help(secretsCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }

View File

@@ -0,0 +1,77 @@
import { Command } from '../help';
import { packageName } from '../../util/pkg-name';
export const teamsCommand: Command = {
name: 'teams',
description: 'Manage teams under your Vercel account',
arguments: [],
subcommands: [
{
name: 'add',
description: 'Create a new team',
arguments: [],
options: [],
examples: [],
},
{
name: 'ls',
description: "Show all teams you're a part of",
arguments: [],
options: [],
examples: [],
},
{
name: 'switch',
description: 'Switch to a different team',
arguments: [
{
name: 'name',
required: false,
},
],
options: [],
examples: [],
},
{
name: 'invite',
description: 'Invite a new member to a team',
arguments: [
{
name: 'emails',
required: true,
},
],
options: [],
examples: [],
},
],
options: [
{
name: 'next',
shorthand: 'N',
type: 'string',
argument: 'MS',
deprecated: false,
multi: false,
description: 'Show next page of results',
},
],
examples: [
{
name: "Switch to a team. If your team's url is 'vercel.com/name', then 'name' is the slug. If the slug is omitted, you can choose interactively.",
value: `${packageName} teams switch <slug>`,
},
{
name: 'Invite new members (interactively)',
value: `${packageName} teams invite`,
},
{
name: 'Invite multiple members simultaneously',
value: `${packageName} teams invite abc@vercel.com xyz@vercel.com`,
},
{
name: 'Paginate results, where `1584722256178` is the time in milliseconds since the UNIX epoch.',
value: `${packageName} teams ls --next 1584722256178`,
},
],
};

View File

@@ -1,63 +1,12 @@
import chalk from 'chalk';
import error from '../../util/output/error'; import error from '../../util/output/error';
import list from './list'; import list from './list';
import add from './add'; import add from './add';
import change from './switch'; import change from './switch';
import invite from './invite'; import invite from './invite';
import { packageName, logo } from '../../util/pkg-name';
import getArgs from '../../util/get-args'; import getArgs from '../../util/get-args';
import Client from '../../util/client'; import Client from '../../util/client';
import { teamsCommand } from './command';
const help = () => { import { help } from '../help';
console.log(`
${chalk.bold(`${logo} ${packageName} teams`)} [options] <command>
${chalk.dim('Commands:')}
add Create a new team
ls Show all teams you're a part of
switch [name] Switch to a different team
invite [email] Invite a new member to a team
${chalk.dim('Options:')}
-h, --help Output usage information
-A ${chalk.bold.underline('FILE')}, --local-config=${chalk.bold.underline(
'FILE'
)} Path to the local ${'`vercel.json`'} file
-Q ${chalk.bold.underline('DIR')}, --global-config=${chalk.bold.underline(
'DIR'
)} Path to the global ${'`.vercel`'} directory
-d, --debug Debug mode [off]
--no-color No color mode [off]
-N, --next Show next page of results
${chalk.dim('Examples:')}
${chalk.gray('')} Switch to a team
${chalk.cyan(`$ ${packageName} switch <slug>`)}
${chalk.gray(
''
)} If your team's url is 'vercel.com/teams/name', 'name' is the slug
${chalk.gray('')} If the slug is omitted, you can choose interactively
${chalk.yellow(
'NOTE:'
)} When you switch, everything you add, list or remove will be scoped that team!
${chalk.gray('')} Invite new members (interactively)
${chalk.cyan(`$ ${packageName} teams invite`)}
${chalk.gray('')} Paginate results, where ${chalk.dim(
'`1584722256178`'
)} is the time in milliseconds since the UNIX epoch.
${chalk.cyan(`$ ${packageName} teams ls --next 1584722256178`)}
`);
};
export default async (client: Client) => { export default async (client: Client) => {
let subcommand; let subcommand;
@@ -74,7 +23,7 @@ export default async (client: Client) => {
} }
if (argv['--help'] || !subcommand) { if (argv['--help'] || !subcommand) {
help(); client.output.print(help(teamsCommand, { columns: client.stderr.columns }));
return 2; return 2;
} }
@@ -107,7 +56,9 @@ export default async (client: Client) => {
); );
} }
exitCode = 2; exitCode = 2;
help(); client.output.print(
help(teamsCommand, { columns: client.stderr.columns })
);
} }
} }
return exitCode; return exitCode;

View File

@@ -2,7 +2,6 @@ import chars from '../../util/output/chars';
import table from '../../util/output/table'; import table from '../../util/output/table';
import getUser from '../../util/get-user'; import getUser from '../../util/get-user';
import getTeams from '../../util/teams/get-teams'; import getTeams from '../../util/teams/get-teams';
import getPrefixedFlags from '../../util/get-prefixed-flags';
import { packageName } from '../../util/pkg-name'; import { packageName } from '../../util/pkg-name';
import getCommandFlags from '../../util/get-command-flags'; import getCommandFlags from '../../util/get-command-flags';
import cmd from '../../util/output/cmd'; import cmd from '../../util/output/cmd';
@@ -81,8 +80,7 @@ export default async function list(client: Client): Promise<number> {
); );
if (pagination?.count === 20) { if (pagination?.count === 20) {
const prefixedArgs = getPrefixedFlags(argv); const flags = getCommandFlags(argv, ['_', '--next', '-N', '-d']);
const flags = getCommandFlags(prefixedArgs, ['_', '--next', '-N', '-d']);
const nextCmd = `${packageName} teams ls${flags} --next ${pagination.next}`; const nextCmd = `${packageName} teams ls${flags} --next ${pagination.next}`;
console.log(); // empty line console.log(); // empty line
output.log(`To display the next page run ${cmd(nextCmd)}`); output.log(`To display the next page run ${cmd(nextCmd)}`);

View File

@@ -20,7 +20,8 @@ export async function initCorepack({
); );
if (pkg instanceof CantParseJSONFile) { if (pkg instanceof CantParseJSONFile) {
console.warn( console.warn(
'Warning: Could not enable corepack because package.json is invalid JSON' 'Warning: Could not enable corepack because package.json is invalid JSON',
pkg.meta.parseErrorLocation
); );
} else if (!pkg?.packageManager) { } else if (!pkg?.packageManager) {
console.warn( console.warn(

View File

@@ -1,48 +0,0 @@
import isWildcardAlias from '../alias/is-wildcard-alias';
import { getCertsForCn } from '../certs/get-certs-for-cn';
import Client from '../client';
/**
* Tries to find the "best" alias url.
* @param aliasList
*/
export async function getPreferredPreviewURL(
client: Client,
aliasList: string[]
) {
if (aliasList.length === 0) {
return null;
}
/**
* First checks for non public aliases and non wildcard domains.
*/
const preferredAliases = aliasList.filter(
alias =>
!alias.endsWith('.now.sh') &&
!alias.endsWith('.vercel.app') &&
!isWildcardAlias(alias)
);
for (const alias of preferredAliases) {
const certs = await getCertsForCn(client, alias, { limit: 1 }).catch(() => {
return null;
});
if (certs && certs.length > 0) {
return { previewUrl: `https://${alias}`, isWildcard: false };
}
}
/**
* Fallback to first alias
*/
const [firstAlias] = aliasList;
if (isWildcardAlias(firstAlias)) {
return { previewUrl: firstAlias, isWildcard: true };
}
if (firstAlias.endsWith('.vercel.app') || firstAlias.endsWith('.now.sh')) {
return { previewUrl: `https://${firstAlias}`, isWildcard: false };
}
return { previewUrl: `http://${firstAlias}`, isWildcard: false };
}

View File

@@ -1,20 +1,20 @@
import chalk from 'chalk'; import chalk from 'chalk';
import type Client from '../client'; import type Client from '../client';
import type { Deployment } from '@vercel-internals/types'; import type { Deployment } from '@vercel-internals/types';
import { getPreferredPreviewURL } from '../../util/deploy/get-preferred-preview-url';
import { isDeploying } from '../../util/deploy/is-deploying'; import { isDeploying } from '../../util/deploy/is-deploying';
import linkStyle from '../output/link'; import linkStyle from '../output/link';
import { prependEmoji, emoji } from '../../util/emoji'; import { prependEmoji, emoji } from '../../util/emoji';
/**
* Prints (to `client.output`) warnings and errors, if any.
*/
export async function printDeploymentStatus( export async function printDeploymentStatus(
client: Client, client: Client,
{ {
readyState, readyState,
alias: aliasList,
aliasError, aliasError,
target,
indications, indications,
url: deploymentUrl,
aliasWarning, aliasWarning,
}: { }: {
readyState: Deployment['readyState']; readyState: Deployment['readyState'];
@@ -36,7 +36,6 @@ export async function printDeploymentStatus(
const { output } = client; const { output } = client;
indications = indications || []; indications = indications || [];
const isProdDeployment = target === 'production';
let isStillBuilding = false; let isStillBuilding = false;
if (noWait) { if (noWait) {
@@ -64,30 +63,6 @@ export async function printDeploymentStatus(
aliasError.message ? `: ${aliasError.message}` : '' aliasError.message ? `: ${aliasError.message}` : ''
}` }`
); );
} else {
// print preview/production url
let previewUrl: string;
// if `noWait` is true, then use the deployment url, not an alias
if (!noWait && Array.isArray(aliasList) && aliasList.length > 0) {
const previewUrlInfo = await getPreferredPreviewURL(client, aliasList);
if (previewUrlInfo) {
previewUrl = previewUrlInfo.previewUrl;
} else {
previewUrl = `https://${deploymentUrl}`;
}
} else {
// fallback to deployment url
previewUrl = `https://${deploymentUrl}`;
}
output.print(
prependEmoji(
`${isProdDeployment ? 'Production' : 'Preview'}: ${chalk.bold(
previewUrl
)} ${deployStamp()}`,
emoji('success')
) + `\n`
);
} }
if (aliasWarning?.message) { if (aliasWarning?.message) {

View File

@@ -9,7 +9,7 @@ import {
import { Output } from '../output'; import { Output } from '../output';
import { progress } from '../output/progress'; import { progress } from '../output/progress';
import Now from '../../util'; import Now from '../../util';
import type { Org } from '@vercel-internals/types'; import type { Deployment, Org } from '@vercel-internals/types';
import ua from '../ua'; import ua from '../ua';
import { linkFolderToProject } from '../projects/link'; import { linkFolderToProject } from '../projects/link';
import { prependEmoji, emoji } from '../emoji'; import { prependEmoji, emoji } from '../emoji';
@@ -17,9 +17,13 @@ import type { Agent } from 'http';
function printInspectUrl( function printInspectUrl(
output: Output, output: Output,
inspectorUrl: string, inspectorUrl: string | null | undefined,
deployStamp: () => string deployStamp: () => string
) { ) {
if (!inspectorUrl) {
return;
}
output.print( output.print(
prependEmoji( prependEmoji(
`Inspect: ${chalk.bold(inspectorUrl)} ${deployStamp()}`, `Inspect: ${chalk.bold(inspectorUrl)} ${deployStamp()}`,
@@ -162,33 +166,47 @@ export default async function processDeployment({
} }
if (event.type === 'created') { if (event.type === 'created') {
const deployment: Deployment = event.payload;
await linkFolderToProject( await linkFolderToProject(
client, client,
cwd, cwd,
{ {
orgId: org.id, orgId: org.id,
projectId: event.payload.projectId, projectId: deployment.projectId!,
}, },
projectName, projectName,
org.slug org.slug
); );
now.url = event.payload.url; now.url = deployment.url;
output.stopSpinner(); output.stopSpinner();
printInspectUrl(output, event.payload.inspectorUrl, deployStamp); printInspectUrl(output, deployment.inspectorUrl, deployStamp);
const isProdDeployment = requestBody.target === 'production';
const previewUrl = `https://${deployment.url}`;
output.print(
prependEmoji(
`${isProdDeployment ? 'Production' : 'Preview'}: ${chalk.bold(
previewUrl
)} ${deployStamp()}`,
emoji('success')
) + `\n`
);
if (quiet) { if (quiet) {
process.stdout.write(`https://${event.payload.url}`); process.stdout.write(`https://${event.payload.url}`);
} }
if (noWait) { if (noWait) {
return event.payload; return deployment;
} }
output.spinner( output.spinner(
event.payload.readyState === 'QUEUED' ? 'Queued' : 'Building', deployment.readyState === 'QUEUED' ? 'Queued' : 'Building',
0 0
); );
} }
@@ -243,6 +261,7 @@ export default async function processDeployment({
// Handle alias-assigned event // Handle alias-assigned event
if (event.type === 'alias-assigned') { if (event.type === 'alias-assigned') {
output.stopSpinner();
event.payload.indications = indications; event.payload.indications = indications;
return event.payload; return event.payload;
} }

View File

@@ -20,6 +20,7 @@ import isPortReachable from 'is-port-reachable';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import npa from 'npm-package-arg'; import npa from 'npm-package-arg';
import type { ChildProcess } from 'child_process'; import type { ChildProcess } from 'child_process';
import JSONparse from 'json-parse-better-errors';
import { getVercelIgnore, fileNameSymbol } from '@vercel/client'; import { getVercelIgnore, fileNameSymbol } from '@vercel/client';
import { import {
@@ -726,7 +727,7 @@ export default class DevServer {
try { try {
const raw = await fs.readFile(abs, 'utf8'); const raw = await fs.readFile(abs, 'utf8');
const parsed: WithFileNameSymbol<T> = JSON.parse(raw); const parsed: WithFileNameSymbol<T> = JSONparse(raw);
parsed[fileNameSymbol] = rel; parsed[fileNameSymbol] = rel;
return parsed; return parsed;
} catch (err: unknown) { } catch (err: unknown) {

View File

@@ -668,13 +668,14 @@ export class CertMissing extends NowError<'ALIAS_IN_USE', { domain: string }> {
export class CantParseJSONFile extends NowError< export class CantParseJSONFile extends NowError<
'CANT_PARSE_JSON_FILE', 'CANT_PARSE_JSON_FILE',
{ file: string } { file: string; parseErrorLocation: string }
> { > {
constructor(file: string) { constructor(file: string, parseErrorLocation: string) {
const message = `Can't parse json file ${file}: ${parseErrorLocation}`;
super({ super({
code: 'CANT_PARSE_JSON_FILE', code: 'CANT_PARSE_JSON_FILE',
meta: { file }, meta: { file, parseErrorLocation },
message: `Can't parse json file`, message,
}); });
} }
} }

View File

@@ -1,8 +0,0 @@
export default (code?: number) =>
new Promise(() => {
// We give stdout some time to flush out
// because there's a node bug where
// stdout writes are asynchronous
// https://github.com/nodejs/node/issues/6456
setTimeout(() => process.exit(code || 0), 100);
});

View File

@@ -1,26 +0,0 @@
/**
* This function adds a prefix `-` or `--` to the flags
* passed from the command line, because the package `mri`
* used to extract the args removes them for some reason.
*/
export default function getPrefixedFlags(args: { [key in string]: any }) {
const prefixedArgs: {
[key in string]: any;
} = {};
for (const arg in args) {
if (arg === '_') {
prefixedArgs[arg] = args[arg];
} else {
let prefix = '-';
// Full form flags need two dashes, whereas one letter
// flags need only one.
if (arg.length > 1) {
prefix = '--';
}
prefixedArgs[`${prefix}${arg}`] = args[arg];
}
}
return prefixedArgs;
}

View File

@@ -1,5 +1,7 @@
import fs from 'fs-extra'; import fs from 'fs-extra';
import { CantParseJSONFile } from './errors-ts'; import { CantParseJSONFile } from './errors-ts';
import JSONparse from 'json-parse-better-errors';
import { errorToString } from '@vercel/error-utils';
export default async function readJSONFile<T>( export default async function readJSONFile<T>(
file: string file: string
@@ -10,10 +12,10 @@ export default async function readJSONFile<T>(
} }
try { try {
const json = JSON.parse(content); const json = JSONparse(content);
return json; return json;
} catch (error) { } catch (error) {
return new CantParseJSONFile(file); return new CantParseJSONFile(file, errorToString(error));
} }
} }

View File

@@ -292,7 +292,7 @@ test('[vc dev] should print help from `vc develop --help`', async () => {
); );
expect(exitCode, formatOutput({ stdout, stderr })).toBe(2); expect(exitCode, formatOutput({ stdout, stderr })).toBe(2);
expect(stdout).toMatch(/▲ vercel dev/gm); expect(stderr).toMatch(/▲ vercel dev/gm);
}); });
test('default command should deploy directory', async () => { test('default command should deploy directory', async () => {

View File

@@ -735,6 +735,12 @@ test('deploys with only vercel.json and README.md', async () => {
}); });
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0); expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
// assert timing order of showing URLs vs status updates
expect(stderr).toMatch(
/Inspect.*\nPreview.*\nQueued.*\nBuilding.*\nCompleting/
);
const { host } = new URL(stdout); const { host } = new URL(stdout);
const res = await fetch(`https://${host}/README.md`); const res = await fetch(`https://${host}/README.md`);
const text = await res.text(); const text = await res.text();

View File

@@ -0,0 +1,29 @@
import chance from 'chance';
import { client } from './client';
export function useSecrets({
name,
created,
}: {
name: string;
created: number;
}) {
const secret = {
uid: chance().guid(),
name: name || chance().name(),
created: created || chance().timestamp(),
};
client.scenario.get('/v3/now/secrets', (_req, res) => {
res.json({
secrets: [secret],
pagination: {
count: 1,
next: 0,
prev: 0,
},
});
});
return secret;
}

View File

@@ -0,0 +1,37 @@
import { client } from '../../mocks/client';
import secrets from '../../../src/commands/secrets';
import { useSecrets } from '../../mocks/secrets';
import { useUser } from '../../mocks/user';
import { useTeams } from '../../mocks/team';
import ms from 'ms';
describe('secrets', () => {
it('errors when no subcommand is provided', async () => {
client.setArgv('secrets');
const exitCode = await secrets(client);
expect(exitCode).toEqual(2);
});
it('lists secrets with ls subcommand', async () => {
useUser();
useTeams('team_dummy');
const name = 'secret-api-password';
const created = 1519555701;
useSecrets({ name, created });
client.setArgv('secrets', 'ls');
await secrets(client);
const timeAgo = `${ms(
new Date().getTime() - new Date(created).getTime()
)} ago`;
await expect(client.stderr).toOutput(
'> NOTE: The `vercel env ls` command is recommended instead of `vercel secret ls`'
);
const output = client.stderr.read();
await expect(output).toMatch(name);
await expect(output).toMatch(timeAgo);
});
});

View File

@@ -1,5 +1,19 @@
# @vercel/client # @vercel/client
## 13.0.2
### Patch Changes
- Updated dependencies [[`5609a1187`](https://github.com/vercel/vercel/commit/5609a1187be9d6cf8d5f16825690c5ea72f17dc5), [`1b4de4a98`](https://github.com/vercel/vercel/commit/1b4de4a986f7a612aac834ebae3ec7bb9e9b8cf8)]:
- @vercel/build-utils@7.1.1
## 13.0.1
### Patch Changes
- Updated dependencies [[`9e3827c78`](https://github.com/vercel/vercel/commit/9e3827c785e1bc45f2bed421132167381481770f)]:
- @vercel/build-utils@7.1.0
## 13.0.0 ## 13.0.0
### Major Changes ### Major Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/client", "name": "@vercel/client",
"version": "13.0.0", "version": "13.0.2",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "dist/index.d.ts", "typings": "dist/index.d.ts",
"homepage": "https://vercel.com", "homepage": "https://vercel.com",
@@ -14,7 +14,7 @@
"directory": "packages/client" "directory": "packages/client"
}, },
"scripts": { "scripts": {
"build": "tsc", "build": "node ../../utils/build.mjs",
"test-e2e": "pnpm test tests/create-deployment.test.ts tests/create-legacy-deployment.test.ts tests/paths.test.ts", "test-e2e": "pnpm test tests/create-deployment.test.ts tests/create-legacy-deployment.test.ts tests/paths.test.ts",
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail", "test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail",
"test-unit": "pnpm test tests/unit.*test.*" "test-unit": "pnpm test tests/unit.*test.*"
@@ -36,7 +36,7 @@
"typescript": "4.9.5" "typescript": "4.9.5"
}, },
"dependencies": { "dependencies": {
"@vercel/build-utils": "7.0.0", "@vercel/build-utils": "7.1.1",
"@vercel/routing-utils": "3.0.0", "@vercel/routing-utils": "3.0.0",
"@zeit/fetch": "5.2.0", "@zeit/fetch": "5.2.0",
"async-retry": "1.2.3", "async-retry": "1.2.3",

View File

@@ -1,6 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["ES2021"], "lib": ["ES2021"],
"module": "commonjs", "module": "commonjs",

View File

@@ -1,5 +1,11 @@
# @vercel/edge # @vercel/edge
## 1.0.1
### Patch Changes
- upgrade edge-runtime ([#10385](https://github.com/vercel/vercel/pull/10385))
## 1.0.0 ## 1.0.0
### Major Changes ### Major Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/edge", "name": "@vercel/edge",
"version": "1.0.0", "version": "1.0.1",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "dist/index.js", "main": "dist/index.js",
"module": "dist/index.mjs", "module": "dist/index.mjs",
@@ -21,7 +21,7 @@
"build:docs": "typedoc && node scripts/fix-links.js && prettier --write docs/**/*.md docs/*.md" "build:docs": "typedoc && node scripts/fix-links.js && prettier --write docs/**/*.md docs/*.md"
}, },
"devDependencies": { "devDependencies": {
"@edge-runtime/jest-environment": "2.2.3", "@edge-runtime/jest-environment": "2.3.0",
"@types/jest": "27.4.1", "@types/jest": "27.4.1",
"jest-junit": "16.0.0", "jest-junit": "16.0.0",
"ts-node": "8.9.1", "ts-node": "8.9.1",

View File

@@ -1,5 +1,11 @@
# @vercel/error-utils # @vercel/error-utils
## 2.0.1
### Patch Changes
- fix `files` in package.json to use `dist` ([#10378](https://github.com/vercel/vercel/pull/10378))
## 2.0.0 ## 2.0.0
### Major Changes ### Major Changes

View File

@@ -1,16 +1,19 @@
{ {
"name": "@vercel/error-utils", "name": "@vercel/error-utils",
"version": "2.0.0", "version": "2.0.1",
"description": "A collection of error utilities for vercel/vercel", "description": "A collection of error utilities for vercel/vercel",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"files": [
"dist"
],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/vercel/vercel.git", "url": "https://github.com/vercel/vercel.git",
"directory": "packages/error-utils" "directory": "packages/error-utils"
}, },
"scripts": { "scripts": {
"build": "tsc", "build": "node ../../utils/build.mjs",
"test": "jest --reporters=default --reporters=jest-junit --coverage --env node --verbose", "test": "jest --reporters=default --reporters=jest-junit --coverage --env node --verbose",
"test-unit": "pnpm test" "test-unit": "pnpm test"
}, },

View File

@@ -1,7 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"declarationMap": true, "emitDeclarationOnly": true,
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["ES2021"], "lib": ["ES2021"],
"module": "commonjs", "module": "commonjs",

View File

@@ -1,5 +1,14 @@
# @vercel/frameworks # @vercel/frameworks
## 2.0.1
### Patch Changes
- move some frameworks deps to dependencies ([#10380](https://github.com/vercel/vercel/pull/10380))
- Updated dependencies [[`96f99c714`](https://github.com/vercel/vercel/commit/96f99c714715651b85eb7a03f58ecc9e1316d156)]:
- @vercel/error-utils@2.0.1
## 2.0.0 ## 2.0.0
### Major Changes ### Major Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/frameworks", "name": "@vercel/frameworks",
"version": "2.0.0", "version": "2.0.1",
"main": "./dist/frameworks.js", "main": "./dist/frameworks.js",
"types": "./dist/frameworks.d.ts", "types": "./dist/frameworks.d.ts",
"files": [ "files": [
@@ -13,20 +13,20 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"scripts": { "scripts": {
"build": "tsc", "build": "node ../../utils/build.mjs",
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail", "test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail",
"test-unit": "pnpm test" "test-unit": "pnpm test"
}, },
"dependencies": { "dependencies": {
"@iarna/toml": "2.2.3", "@iarna/toml": "2.2.3",
"js-yaml": "3.13.1" "js-yaml": "3.13.1",
"@vercel/error-utils": "2.0.1"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "27.4.1", "@types/jest": "27.4.1",
"@types/js-yaml": "3.12.1", "@types/js-yaml": "3.12.1",
"@types/node": "14.18.33", "@types/node": "14.18.33",
"@types/node-fetch": "2.5.8", "@types/node-fetch": "2.5.8",
"@vercel/error-utils": "2.0.0",
"@vercel/routing-utils": "3.0.0", "@vercel/routing-utils": "3.0.0",
"ajv": "6.12.2", "ajv": "6.12.2",
"jest-junit": "16.0.0", "jest-junit": "16.0.0",

View File

@@ -1,6 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["ES2021"], "lib": ["ES2021"],
"module": "commonjs", "module": "commonjs",

View File

@@ -1,5 +1,19 @@
# @vercel/fs-detectors # @vercel/fs-detectors
## 5.0.2
### Patch Changes
- Updated semver dependency ([#10411](https://github.com/vercel/vercel/pull/10411))
## 5.0.1
### Patch Changes
- Updated dependencies [[`c615423a0`](https://github.com/vercel/vercel/commit/c615423a0b60ed64bf5e0e10bbc4ca997c31bd60), [`96f99c714`](https://github.com/vercel/vercel/commit/96f99c714715651b85eb7a03f58ecc9e1316d156)]:
- @vercel/frameworks@2.0.1
- @vercel/error-utils@2.0.1
## 5.0.0 ## 5.0.0
### Major Changes ### Major Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/fs-detectors", "name": "@vercel/fs-detectors",
"version": "5.0.0", "version": "5.0.2",
"description": "Vercel filesystem detectors", "description": "Vercel filesystem detectors",
"main": "./dist/index.js", "main": "./dist/index.js",
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -14,20 +14,20 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"scripts": { "scripts": {
"build": "tsc", "build": "node ../../utils/build.mjs",
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail", "test": "jest --reporters=default --reporters=jest-junit --env node --verbose --runInBand --bail",
"test-unit": "pnpm test test/unit.*test.*", "test-unit": "pnpm test test/unit.*test.*",
"test-e2e": "pnpm test test/integration.test.ts" "test-e2e": "pnpm test test/integration.test.ts"
}, },
"dependencies": { "dependencies": {
"@vercel/error-utils": "2.0.0", "@vercel/error-utils": "2.0.1",
"@vercel/frameworks": "2.0.0", "@vercel/frameworks": "2.0.1",
"@vercel/routing-utils": "3.0.0", "@vercel/routing-utils": "3.0.0",
"glob": "8.0.3", "glob": "8.0.3",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
"json5": "2.2.2", "json5": "2.2.2",
"minimatch": "3.1.2", "minimatch": "3.1.2",
"semver": "6.1.1" "semver": "6.3.1"
}, },
"devDependencies": { "devDependencies": {
"@types/glob": "7.2.0", "@types/glob": "7.2.0",
@@ -36,7 +36,7 @@
"@types/minimatch": "3.0.5", "@types/minimatch": "3.0.5",
"@types/node": "14.18.33", "@types/node": "14.18.33",
"@types/semver": "7.3.10", "@types/semver": "7.3.10",
"@vercel/build-utils": "7.0.0", "@vercel/build-utils": "7.1.1",
"jest-junit": "16.0.0", "jest-junit": "16.0.0",
"typescript": "4.9.5" "typescript": "4.9.5"
} }

View File

@@ -1,6 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["ES2021"], "lib": ["ES2021"],
"module": "commonjs", "module": "commonjs",

View File

@@ -1,5 +1,35 @@
# @vercel/gatsby-plugin-vercel-builder # @vercel/gatsby-plugin-vercel-builder
## 2.0.4
### Patch Changes
- Updated dependencies [[`5609a1187`](https://github.com/vercel/vercel/commit/5609a1187be9d6cf8d5f16825690c5ea72f17dc5), [`1b4de4a98`](https://github.com/vercel/vercel/commit/1b4de4a986f7a612aac834ebae3ec7bb9e9b8cf8), [`fc1e13c09`](https://github.com/vercel/vercel/commit/fc1e13c09928c654410b373fc1775c2b63c6ef4a)]:
- @vercel/build-utils@7.1.1
- @vercel/node@3.0.4
## 2.0.3
### Patch Changes
- Updated dependencies [[`9e3827c78`](https://github.com/vercel/vercel/commit/9e3827c785e1bc45f2bed421132167381481770f)]:
- @vercel/build-utils@7.1.0
- @vercel/node@3.0.3
## 2.0.2
### Patch Changes
- Updated dependencies [[`597a8a817`](https://github.com/vercel/vercel/commit/597a8a81764c39e70c65b98e78bf4c3827a779a7), [`3f6d99470`](https://github.com/vercel/vercel/commit/3f6d99470db86681e006d66507f32afcea086b41)]:
- @vercel/node@3.0.2
## 2.0.1
### Patch Changes
- Updated dependencies []:
- @vercel/node@3.0.1
## 2.0.0 ## 2.0.0
### Major Changes ### Major Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/gatsby-plugin-vercel-builder", "name": "@vercel/gatsby-plugin-vercel-builder",
"version": "2.0.0", "version": "2.0.4",
"main": "dist/index.js", "main": "dist/index.js",
"files": [ "files": [
"dist", "dist",
@@ -20,8 +20,8 @@
}, },
"dependencies": { "dependencies": {
"@sinclair/typebox": "0.25.24", "@sinclair/typebox": "0.25.24",
"@vercel/build-utils": "7.0.0", "@vercel/build-utils": "7.1.1",
"@vercel/node": "3.0.0", "@vercel/node": "3.0.4",
"@vercel/routing-utils": "3.0.0", "@vercel/routing-utils": "3.0.0",
"esbuild": "0.14.47", "esbuild": "0.14.47",
"etag": "1.8.1", "etag": "1.8.1",

View File

@@ -27,7 +27,7 @@
"@types/node-fetch": "^2.3.0", "@types/node-fetch": "^2.3.0",
"@types/tar": "^4.0.0", "@types/tar": "^4.0.0",
"@types/yauzl-promise": "2.1.0", "@types/yauzl-promise": "2.1.0",
"@vercel/build-utils": "7.0.0", "@vercel/build-utils": "7.1.1",
"@vercel/ncc": "0.24.0", "@vercel/ncc": "0.24.0",
"async-retry": "1.3.1", "async-retry": "1.3.1",
"execa": "^1.0.0", "execa": "^1.0.0",

View File

@@ -1,12 +0,0 @@
const execa = require('execa');
const { remove } = require('fs-extra');
async function main() {
await remove('dist');
await execa('tsc', [], { stdio: 'inherit' });
}
main().catch(err => {
console.error(err);
process.exit(1);
});

View File

@@ -10,7 +10,7 @@
"directory": "packages/hydrogen" "directory": "packages/hydrogen"
}, },
"scripts": { "scripts": {
"build": "node build.js", "build": "node ../../utils/build.mjs",
"test-e2e": "pnpm test test/test.js", "test-e2e": "pnpm test test/test.js",
"test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail --runInBand" "test": "jest --reporters=default --reporters=jest-junit --env node --verbose --bail --runInBand"
}, },
@@ -21,7 +21,7 @@
"devDependencies": { "devDependencies": {
"@types/jest": "27.5.1", "@types/jest": "27.5.1",
"@types/node": "14.18.33", "@types/node": "14.18.33",
"@vercel/build-utils": "7.0.0", "@vercel/build-utils": "7.1.1",
"@vercel/static-config": "3.0.0", "@vercel/static-config": "3.0.0",
"execa": "3.2.0", "execa": "3.2.0",
"fs-extra": "11.1.0", "fs-extra": "11.1.0",

View File

@@ -1,6 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"emitDeclarationOnly": true,
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["ES2021"], "lib": ["ES2021"],
"module": "commonjs", "module": "commonjs",

View File

@@ -1,5 +1,27 @@
# @vercel/next # @vercel/next
## 4.0.2
### Patch Changes
- Fix Next.js with `basePath` + Edge runtime + App Router on a top level `page.jsx` ([#10465](https://github.com/vercel/vercel/pull/10465))
- Updated semver dependency ([#10411](https://github.com/vercel/vercel/pull/10411))
- Fix RSC rewrite behavior ([#10415](https://github.com/vercel/vercel/pull/10415))
- fix ENOENT on /404.html when `fallback: false` w/ `basePath` ([#10473](https://github.com/vercel/vercel/pull/10473))
- fix 404 enoent for i18n ([#10416](https://github.com/vercel/vercel/pull/10416))
## 4.0.1
### Patch Changes
- fix RSC matching behavior & 404 status code on `fallback: false` ([#10388](https://github.com/vercel/vercel/pull/10388))
- Add handling to leverage RSC prefetch outputs ([#10390](https://github.com/vercel/vercel/pull/10390))
## 4.0.0 ## 4.0.0
### Major Changes ### Major Changes

View File

@@ -1,6 +1,6 @@
{ {
"name": "@vercel/next", "name": "@vercel/next",
"version": "4.0.0", "version": "4.0.2",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./dist/index", "main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js", "homepage": "https://vercel.com/docs/runtimes#official-runtimes/next-js",
@@ -35,7 +35,7 @@
"@types/semver": "6.0.0", "@types/semver": "6.0.0",
"@types/text-table": "0.2.1", "@types/text-table": "0.2.1",
"@types/webpack-sources": "3.2.0", "@types/webpack-sources": "3.2.0",
"@vercel/build-utils": "7.0.0", "@vercel/build-utils": "7.1.1",
"@vercel/nft": "0.22.5", "@vercel/nft": "0.22.5",
"@vercel/routing-utils": "3.0.0", "@vercel/routing-utils": "3.0.0",
"async-sema": "3.0.1", "async-sema": "3.0.1",
@@ -54,7 +54,7 @@
"ndjson": "2.0.0", "ndjson": "2.0.0",
"pretty-bytes": "5.3.0", "pretty-bytes": "5.3.0",
"resolve-from": "5.0.0", "resolve-from": "5.0.0",
"semver": "6.1.1", "semver": "6.3.1",
"set-cookie-parser": "2.4.6", "set-cookie-parser": "2.4.6",
"source-map": "0.7.3", "source-map": "0.7.3",
"test-listen": "1.1.0", "test-listen": "1.1.0",

View File

@@ -91,6 +91,7 @@ import {
getOperationType, getOperationType,
isApiPage, isApiPage,
getFunctionsConfigManifest, getFunctionsConfigManifest,
normalizeEdgeFunctionPath,
} from './utils'; } from './utils';
export const version = 2; export const version = 2;
@@ -1320,11 +1321,7 @@ export const build: BuildV2 = async ({
const localePrefixed404 = !!( const localePrefixed404 = !!(
routesManifest.i18n && routesManifest.i18n &&
originalStaticPages[ originalStaticPages[
path.posix.join( path.posix.join('.', routesManifest.i18n.defaultLocale, '404.html')
entryDirectory,
routesManifest.i18n.defaultLocale,
'404.html'
)
] ]
); );
@@ -2720,7 +2717,15 @@ async function getServerlessPages(params: {
for (const edgeFunctionFile of Object.keys( for (const edgeFunctionFile of Object.keys(
middlewareManifest?.functions ?? {} middlewareManifest?.functions ?? {}
)) { )) {
const edgePath = (edgeFunctionFile.slice(1) || 'index') + '.js'; let edgePath =
middlewareManifest?.functions?.[edgeFunctionFile].name ||
edgeFunctionFile;
edgePath = normalizeEdgeFunctionPath(
edgePath,
params.appPathRoutesManifest || {}
);
edgePath = (edgePath || 'index') + '.js';
delete normalizedAppPaths[edgePath]; delete normalizedAppPaths[edgePath];
delete pages[edgePath]; delete pages[edgePath];
} }

View File

@@ -168,12 +168,15 @@ export async function serverBuild({
} }
} }
const APP_PREFETCH_SUFFIX = '.prefetch.rsc';
let appRscPrefetches: UnwrapPromise<ReturnType<typeof glob>> = {};
let appBuildTraces: UnwrapPromise<ReturnType<typeof glob>> = {}; let appBuildTraces: UnwrapPromise<ReturnType<typeof glob>> = {};
let appDir: string | null = null; let appDir: string | null = null;
if (appPathRoutesManifest) { if (appPathRoutesManifest) {
appDir = path.join(pagesDir, '../app'); appDir = path.join(pagesDir, '../app');
appBuildTraces = await glob('**/*.js.nft.json', appDir); appBuildTraces = await glob('**/*.js.nft.json', appDir);
appRscPrefetches = await glob(`**/*${APP_PREFETCH_SUFFIX}`, appDir);
} }
const isCorrectNotFoundRoutes = semver.gte( const isCorrectNotFoundRoutes = semver.gte(
@@ -434,11 +437,19 @@ export async function serverBuild({
if (i18n) { if (i18n) {
for (const locale of i18n.locales) { for (const locale of i18n.locales) {
const static404File = let static404File =
staticPages[path.posix.join(entryDirectory, locale, '/404')] || staticPages[path.posix.join(entryDirectory, locale, '/404')];
new FileFsRef({
if (!static404File) {
static404File = new FileFsRef({
fsPath: path.join(pagesDir, locale, '/404.html'), fsPath: path.join(pagesDir, locale, '/404.html'),
}); });
if (!fs.existsSync(static404File.fsPath)) {
static404File = new FileFsRef({
fsPath: path.join(pagesDir, '/404.html'),
});
}
}
requiredFiles[path.relative(baseDir, static404File.fsPath)] = requiredFiles[path.relative(baseDir, static404File.fsPath)] =
static404File; static404File;
} }
@@ -1063,8 +1074,7 @@ export async function serverBuild({
canUsePreviewMode, canUsePreviewMode,
prerenderManifest.bypassToken || '', prerenderManifest.bypassToken || '',
true, true,
middleware.dynamicRouteMap, middleware.dynamicRouteMap
inversedAppPathManifest
).then(arr => ).then(arr =>
localizeDynamicRoutes( localizeDynamicRoutes(
arr, arr,
@@ -1079,6 +1089,32 @@ export async function serverBuild({
) )
); );
const pagesPlaceholderRscEntries: Record<string, FileBlob> = {};
if (appDir) {
// since we attempt to rewrite all paths to an .rsc variant,
// we need to create dummy rsc outputs for all pages entries
// this is so that an RSC request to a `pages` entry will match
// rather than falling back to a catchall `app` entry
// on the nextjs side, invalid RSC response payloads will correctly trigger an mpa navigation
const pagesManifest = path.join(
entryPath,
outputDirectory,
`server/pages-manifest.json`
);
const pagesData = await fs.readJSON(pagesManifest);
const pagesEntries = Object.keys(pagesData);
for (const page of pagesEntries) {
const pathName = page.startsWith('/') ? page.slice(1) : page;
pagesPlaceholderRscEntries[`${pathName}.rsc`] = new FileBlob({
data: '{}',
contentType: 'application/json',
});
}
}
const { staticFiles, publicDirectoryFiles, staticDirectoryFiles } = const { staticFiles, publicDirectoryFiles, staticDirectoryFiles } =
await getStaticFiles(entryPath, entryDirectory, outputDirectory); await getStaticFiles(entryPath, entryDirectory, outputDirectory);
@@ -1209,10 +1245,9 @@ export async function serverBuild({
if (ogRoute.endsWith('/route')) { if (ogRoute.endsWith('/route')) {
continue; continue;
} }
route = path.posix.join( route = normalizeIndexOutput(
'./', path.posix.join('./', entryDirectory, route === '/' ? '/index' : route),
entryDirectory, true
route === '/' ? '/index' : route
); );
if (lambdas[route]) { if (lambdas[route]) {
@@ -1225,6 +1260,7 @@ export async function serverBuild({
} }
const rscHeader = routesManifest.rsc?.header?.toLowerCase() || '__rsc__'; const rscHeader = routesManifest.rsc?.header?.toLowerCase() || '__rsc__';
const rscPrefetchHeader = routesManifest.rsc?.prefetchHeader?.toLowerCase();
const rscVaryHeader = const rscVaryHeader =
routesManifest?.rsc?.varyHeader || routesManifest?.rsc?.varyHeader ||
'RSC, Next-Router-State-Tree, Next-Router-Prefetch'; 'RSC, Next-Router-State-Tree, Next-Router-Prefetch';
@@ -1236,6 +1272,8 @@ export async function serverBuild({
output: { output: {
...publicDirectoryFiles, ...publicDirectoryFiles,
...lambdas, ...lambdas,
...appRscPrefetches,
...pagesPlaceholderRscEntries,
// Prerenders may override Lambdas -- this is an intentional behavior. // Prerenders may override Lambdas -- this is an intentional behavior.
...prerenders, ...prerenders,
...staticPages, ...staticPages,
@@ -1475,6 +1513,49 @@ export async function serverBuild({
...(appDir ...(appDir
? [ ? [
...(rscPrefetchHeader
? [
{
src: `^${path.posix.join('/', entryDirectory, '/')}`,
has: [
{
type: 'header',
key: rscPrefetchHeader,
},
],
dest: path.posix.join(
'/',
entryDirectory,
'/index.prefetch.rsc'
),
headers: { vary: rscVaryHeader },
continue: true,
override: true,
},
{
src: `^${path.posix.join(
'/',
entryDirectory,
'/((?!.+\\.rsc).+?)(?:/)?$'
)}`,
has: [
{
type: 'header',
key: rscPrefetchHeader,
},
],
dest: path.posix.join(
'/',
entryDirectory,
`/$1${APP_PREFETCH_SUFFIX}`
),
headers: { vary: rscVaryHeader },
continue: true,
override: true,
},
]
: []),
{ {
src: `^${path.posix.join('/', entryDirectory, '/')}`, src: `^${path.posix.join('/', entryDirectory, '/')}`,
has: [ has: [
@@ -1539,21 +1620,59 @@ export async function serverBuild({
] ]
: []), : []),
...(rscPrefetchHeader
? [
{
src: path.posix.join(
'/',
entryDirectory,
`/index${APP_PREFETCH_SUFFIX}`
),
dest: path.posix.join('/', entryDirectory, '/index.rsc'),
has: [
{
type: 'header',
key: rscPrefetchHeader,
},
],
continue: true,
override: true,
},
{
src: `^${path.posix.join(
'/',
entryDirectory,
`/(.+?)${APP_PREFETCH_SUFFIX}(?:/)?$`
)}`,
dest: path.posix.join('/', entryDirectory, '/$1.rsc'),
has: [
{
type: 'header',
key: rscPrefetchHeader,
},
],
continue: true,
override: true,
},
]
: []),
// These need to come before handle: miss or else they are grouped // These need to come before handle: miss or else they are grouped
// with that routing section // with that routing section
...afterFilesRewrites, ...afterFilesRewrites,
// make sure 404 page is used when a directory is matched without
// an index page
{ handle: 'resource' }, { handle: 'resource' },
...fallbackRewrites, ...fallbackRewrites,
// make sure 404 page is used when a directory is matched without
// an index page
{ src: path.posix.join('/', entryDirectory, '.*'), status: 404 }, { src: path.posix.join('/', entryDirectory, '.*'), status: 404 },
{ handle: 'miss' },
// We need to make sure to 404 for /_next after handle: miss since // We need to make sure to 404 for /_next after handle: miss since
// handle: miss is called before rewrites and to prevent rewriting /_next // handle: miss is called before rewrites and to prevent rewriting /_next
{ handle: 'miss' },
{ {
src: path.posix.join( src: path.posix.join(
'/', '/',

View File

@@ -236,6 +236,7 @@ type RoutesManifestOld = {
rsc?: { rsc?: {
header: string; header: string;
varyHeader: string; varyHeader: string;
prefetchHeader?: string;
contentTypeHeader: string; contentTypeHeader: string;
}; };
skipMiddlewareUrlNormalize?: boolean; skipMiddlewareUrlNormalize?: boolean;
@@ -304,8 +305,7 @@ export async function getDynamicRoutes(
canUsePreviewMode?: boolean, canUsePreviewMode?: boolean,
bypassToken?: string, bypassToken?: string,
isServerMode?: boolean, isServerMode?: boolean,
dynamicMiddlewareRouteMap?: Map<string, RouteWithSrc>, dynamicMiddlewareRouteMap?: Map<string, RouteWithSrc>
appPathRoutesManifest?: Record<string, string>
): Promise<RouteWithSrc[]> { ): Promise<RouteWithSrc[]> {
if (routesManifest) { if (routesManifest) {
switch (routesManifest.version) { switch (routesManifest.version) {
@@ -378,17 +378,15 @@ export async function getDynamicRoutes(
}, },
]; ];
} }
routes.push({
...route,
src: route.src.replace(
new RegExp(escapeStringRegexp('(?:/)?$')),
'(?:\\.rsc)(?:/)?$'
),
dest: route.dest?.replace(/($|\?)/, '.rsc$1'),
});
if (appPathRoutesManifest?.[page]) {
routes.push({
...route,
src: route.src.replace(
new RegExp(escapeStringRegexp('(?:/)?$')),
'(?:\\.rsc)(?:/)?$'
),
dest: route.dest?.replace(/($|\?)/, '.rsc$1'),
});
}
routes.push(route); routes.push(route);
continue; continue;
} }
@@ -2002,6 +2000,10 @@ export const onPrerenderRoute =
), ),
}); });
if (isOmittedOrNotFound) {
initialStatus = 404;
}
if (isAppPathRoute) { if (isAppPathRoute) {
// for literal index routes we need to append an additional /index // for literal index routes we need to append an additional /index
// due to the proxy's normalizing for /index routes // due to the proxy's normalizing for /index routes
@@ -2342,7 +2344,7 @@ export function normalizeIndexOutput(
outputName: string, outputName: string,
isServerMode: boolean isServerMode: boolean
) { ) {
if (outputName !== '/index' && isServerMode) { if (outputName !== 'index' && outputName !== '/index' && isServerMode) {
return outputName.replace(/\/index$/, ''); return outputName.replace(/\/index$/, '');
} }
return outputName; return outputName;
@@ -2519,6 +2521,29 @@ function normalizeRegions(regions: Regions): undefined | string | string[] {
return newRegions; return newRegions;
} }
export function normalizeEdgeFunctionPath(
shortPath: string,
appPathRoutesManifest: Record<string, string>
) {
if (
shortPath.startsWith('app/') &&
(shortPath.endsWith('/page') ||
shortPath.endsWith('/route') ||
shortPath === 'app/_not-found')
) {
const ogRoute = shortPath.replace(/^app\//, '/');
shortPath = (
appPathRoutesManifest[ogRoute] ||
shortPath.replace(/(^|\/)(page|route)$/, '')
).replace(/^\//, '');
if (!shortPath || shortPath === '/') {
shortPath = 'index';
}
}
return shortPath;
}
export async function getMiddlewareBundle({ export async function getMiddlewareBundle({
entryPath, entryPath,
outputDirectory, outputDirectory,
@@ -2697,27 +2722,19 @@ export async function getMiddlewareBundle({
// app/index/page -> index/index // app/index/page -> index/index
if (shortPath.startsWith('pages/')) { if (shortPath.startsWith('pages/')) {
shortPath = shortPath.replace(/^pages\//, ''); shortPath = shortPath.replace(/^pages\//, '');
} else if ( } else {
shortPath.startsWith('app/') && shortPath = normalizeEdgeFunctionPath(shortPath, appPathRoutesManifest);
(shortPath.endsWith('/page') ||
shortPath.endsWith('/route') ||
shortPath === 'app/_not-found')
) {
const ogRoute = shortPath.replace(/^app\//, '/');
shortPath = (
appPathRoutesManifest[ogRoute] ||
shortPath.replace(/(^|\/)(page|route)$/, '')
).replace(/^\//, '');
if (!shortPath || shortPath === '/') {
shortPath = 'index';
}
} }
if (routesManifest?.basePath) { if (routesManifest?.basePath) {
shortPath = path.posix shortPath = normalizeIndexOutput(
.join(routesManifest.basePath, shortPath) path.posix.join(
.replace(/^\//, ''); './',
routesManifest?.basePath,
shortPath.replace(/^\//, '')
),
true
);
} }
worker.edgeFunction.name = shortPath; worker.edgeFunction.name = shortPath;

View File

@@ -0,0 +1,7 @@
export default function CatchAllPage() {
return (
<div>
<h1>CatchAllPage</h1>
</div>
);
}

View File

@@ -0,0 +1,8 @@
export default function RootLayout({ children }) {
return (
<html>
<head />
<body>{children}</body>
</html>
)
}

View File

@@ -0,0 +1,10 @@
import Link from 'next/link';
export default function Home() {
return (
<div>
<h1>Home</h1>
<Link href="/en/about">About</Link>
</div>
);
}

View File

@@ -0,0 +1,12 @@
/* eslint-env jest */
const path = require('path');
const { deployAndTest } = require('../../utils');
const ctx = {};
describe(`${__dirname.split(path.sep).pop()}`, () => {
it('should deploy and pass probe checks', async () => {
const info = await deployAndTest(__dirname);
Object.assign(ctx, info);
});
});

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