Compare commits

...

103 Commits

Author SHA1 Message Date
Vercel Release Bot
6d312d85b2 Version Packages (#10542)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## vercel@32.3.0

### Minor Changes

- [cli] Support northstar users
([#10535](https://github.com/vercel/vercel/pull/10535))

### Patch Changes

- Internal variants
([#10549](https://github.com/vercel/vercel/pull/10549))

- [speed insights] Prepare for migration to new speed insights package
([#10500](https://github.com/vercel/vercel/pull/10500))

- Updated dependencies
\[[`b0898a665`](b0898a6659),
[`10d4e51ac`](10d4e51ac5),
[`decdf27fb`](decdf27fb5),
[`f5ca497b7`](f5ca497b75),
[`ab329f0fe`](ab329f0fe8),
[`d0d052011`](d0d0520111),
[`9bb3067de`](9bb3067de2)]:
    -   @vercel/static-build@2.0.7
    -   @vercel/node@3.0.6
    -   @vercel/build-utils@7.2.1
    -   @vercel/next@4.0.7
    -   @vercel/python@4.0.2
    -   @vercel/redwood@2.0.3
    -   @vercel/remix-builder@2.0.7
    -   @vercel/go@3.0.2

## @vercel/edge@1.1.0

### Minor Changes

- Add flag to geolocation
([#10443](https://github.com/vercel/vercel/pull/10443))

    Usage

        const { flag } = geolocation(req)

## @vercel/build-utils@7.2.1

### Patch Changes

- Internal variants
([#10549](https://github.com/vercel/vercel/pull/10549))

## @vercel/client@13.0.4

### Patch Changes

- Updated dependencies
\[[`decdf27fb`](decdf27fb5)]:
    -   @vercel/build-utils@7.2.1

## @vercel/gatsby-plugin-vercel-analytics@1.0.11

### Patch Changes

- Remove "babel" compilation
([#10546](https://github.com/vercel/vercel/pull/10546))

## @vercel/gatsby-plugin-vercel-builder@2.0.6

### Patch Changes

- Use "esbuild" to build package
([#10508](https://github.com/vercel/vercel/pull/10508))

- Updated dependencies
\[[`decdf27fb`](decdf27fb5)]:
    -   @vercel/build-utils@7.2.1

## @vercel/go@3.0.2

### Patch Changes

- Add support for Go v1.21.0
([#10552](https://github.com/vercel/vercel/pull/10552))

## @vercel/next@4.0.7

### Patch Changes

- Internal variants
([#10549](https://github.com/vercel/vercel/pull/10549))

- Update `@vercel/nft` to v0.24.1.
([#10540](https://github.com/vercel/vercel/pull/10540))

- Build package using "esbuild"
([#10482](https://github.com/vercel/vercel/pull/10482))

## @vercel/node@3.0.6

### Patch Changes

- Use "esbuild" to build package
([#10553](https://github.com/vercel/vercel/pull/10553))

- Update `@vercel/nft` to v0.24.1.
([#10540](https://github.com/vercel/vercel/pull/10540))

- Updated dependencies
\[[`decdf27fb`](decdf27fb5)]:
    -   @vercel/build-utils@7.2.1

## @vercel/python@4.0.2

### Patch Changes

- Fix docs URL in error message
([#10544](https://github.com/vercel/vercel/pull/10544))

## @vercel/redwood@2.0.3

### Patch Changes

- Update `@vercel/nft` to v0.24.1.
([#10540](https://github.com/vercel/vercel/pull/10540))

## @vercel/remix-builder@2.0.7

### Patch Changes

- Update `@vercel/nft` to v0.24.1.
([#10540](https://github.com/vercel/vercel/pull/10540))

## @vercel/static-build@2.0.7

### Patch Changes

- Mark `@vercel/static-config` and `ts-morph` as externals
([#10543](https://github.com/vercel/vercel/pull/10543))

- Updated dependencies
\[[`4b376a564`](4b376a564a),
[`b8bc682d3`](b8bc682d3e)]:
    -   @vercel/gatsby-plugin-vercel-builder@2.0.6
    -   @vercel/gatsby-plugin-vercel-analytics@1.0.11

## @vercel-internals/types@1.0.11

### Patch Changes

- Updated dependencies
\[[`decdf27fb`](decdf27fb5)]:
    -   @vercel/build-utils@7.2.1

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-21 11:59:12 -06:00
Nathan Rajlich
10d4e51ac5 [node] Use "esbuild" to build package (#10553) 2023-09-20 18:35:57 -03:00
Tobias Lins
57231a0d60 [speed insights] Prepare for migration to new speed insights package (#10500)
During `vc build` do following when `@vercel/speed-insights` package is in dependencies:
- Show a warning when `VERCEL_ANALYTICS_ID` is set in environment variables
- Unset it in process.env to prevent auto-injecting old speed insights in Next.js

Durning `vc env pull` prevent pulling internal environment variables `VERCEL_ANALYTICS_ID`, `VERCEL_SPEED_INSIGHTS_ID` & `VERCEL_WEB_ANALYTICS_ID`. They are never required in the frontend
2023-09-20 21:06:12 +00:00
Vercel Release Bot
e0e9cffc8d [examples][tests] Upgrade Next.js to version 13.5.2 (#10554)
This auto-generated PR updates 4 packages to Next.js version 13.5.2
2023-09-20 20:19:36 +00:00
Nathan Rajlich
d0d0520111 [next] Use "esbuild" to build package (#10482)
### Before

```
$ time pnpm run build

> @vercel/next@4.0.6 build /Users/nrajlich/Code/vercel/vercel/packages/next
> node build.js

ncc: Version 0.24.0
ncc: Compiling file index.js
ncc: Using typescript@4.9.5 (local user-provided)
1506kB  dist/main/index.js
1506kB  [3345ms] - ncc 0.24.0

real    0m5.210s
user    0m9.083s
sys     0m0.506s

$ ls -l dist/
total 1700
-rw-r--r-- 1 nrajlich staff    2176 Sep 20 15:18 ___get-nextjs-edge-function.js
-rw-r--r-- 1 nrajlich staff    3283 Sep 20 15:18 create-serverless-config.js
drwxr-xr-x 6 nrajlich staff     192 Sep 20 15:18 edge-function-source/
-rw-r--r-- 1 nrajlich staff 1542314 Sep 20 15:18 index.js
-rw-r--r-- 1 nrajlich staff     728 Sep 20 15:18 legacy-launcher.js
-rw-r--r-- 1 nrajlich staff    6807 Sep 20 15:18 legacy-versions.js
-rw-r--r-- 1 nrajlich staff   66662 Sep 20 15:18 server-build.js
-rw-r--r-- 1 nrajlich staff    1583 Sep 20 15:18 server-launcher.js
-rw-r--r-- 1 nrajlich staff    5167 Sep 20 15:18 sourcemapped.js
-rw-r--r-- 1 nrajlich staff    1003 Sep 20 15:18 templated-launcher-shared.js
-rw-r--r-- 1 nrajlich staff     799 Sep 20 15:18 templated-launcher.js
-rw-r--r-- 1 nrajlich staff   83876 Sep 20 15:18 utils.js

$ pnpm pack && ls -lh vercel-next-4.0.6.tgz 
-rw-r--r-- 1 nrajlich staff 373K Sep 20 15:19 vercel-next-4.0.6.tgz
```

### After

```
$ time pnpm run build

> @vercel/next@4.0.6 build /Users/nrajlich/Code/vercel/vercel/packages/next
> node build.mjs

real    0m1.144s
user    0m0.550s
sys     0m0.171s

$ ls -l dist/
total 540
-rw-r--r-- 1 nrajlich staff   2176 Sep 20 15:15 ___get-nextjs-edge-function.js
-rw-r--r-- 1 nrajlich staff 528575 Sep 20 15:15 index.js
-rw-r--r-- 1 nrajlich staff   1680 Sep 20 15:15 legacy-launcher.js
-rw-r--r-- 1 nrajlich staff    901 Sep 20 15:15 server-launcher.js
-rw-r--r-- 1 nrajlich staff    532 Sep 20 15:15 templated-launcher-shared.js
-rw-r--r-- 1 nrajlich staff    316 Sep 20 15:15 templated-launcher.js

$ pnpm pack && ls -lh vercel-next-4.0.6.tgz 
-rw-r--r-- 1 nrajlich staff 104K Sep 20 15:15 vercel-next-4.0.6.tgz
```
2023-09-20 20:01:03 +00:00
Ethan Arrowood
9bb3067de2 [go] add support for Go 1.21.0 (#10552)
as titled

updates a test to check for runtime version

---------

Co-authored-by: Nathan Rajlich <n@n8.io>
2023-09-20 12:30:38 -06:00
Andy
decdf27fb5 [cli][next][build-utils] Variants (#10549)
Co-authored-by: Ethan Arrowood <ethan.arrowood@vercel.com>
2023-09-20 19:42:20 +02:00
Nathan Rajlich
4b376a564a [gatsby-plugin-vercel-builder] Use "esbuild" to build package (#10508)
Removes the two-staged `tsc` build into a single `esbuild` bundle. The `ssr-handler.ts` template file is moved to the root of the package and converted to JavaScript.
2023-09-20 13:26:31 +00:00
Shu Uesugi
b7e93524e3 [cli] Support northstar users (#10535)
Supports users who have `version === 'northstar'` and `defaultTeamId`.
2023-09-19 21:45:42 +00:00
Paul Scanlon
62283356b8 feat: add flag to geolocation (#10443)
Co-authored-by: Chris Barber <chris.barber@vercel.com>
2023-09-19 16:25:46 -05:00
Vercel Release Bot
3305f5e832 [examples][tests] Upgrade Next.js to version 13.5.1 (#10545)
This auto-generated PR updates 4 packages to Next.js version 13.5.1
2023-09-19 21:06:40 +00:00
Jiachi Liu
a938706916 update code owners for nextjs example (#10548)
Add @huozhi to nextjs example code owners

---------

Co-authored-by: Steven <steven@ceriously.com>
2023-09-19 17:01:13 -04:00
Nathan Rajlich
b8bc682d3e [gatsby-plugin-vercel-analytics] Remove "babel" compilation (#10546)
The "babel" build for this package essentially does nothing. The output is still using ESM and no transformation is done. Let's just remove the "build" script entirely.
2023-09-19 20:45:26 +00:00
Nathan Rajlich
f5ca497b75 [python] Fix docs URL in error message (#10544) 2023-09-19 18:07:43 +00:00
Nathan Rajlich
b0898a6659 [static-build] Mark @vercel/static-config and ts-morph as externals (#10543)
To be consistent with the other packages that use `@vercel/static-config`/`ts-morph`, move these packages to "dependencies" so that they will be excluded from the bundle, and de-duped at the `node_modules` level when installing CLI.
2023-09-19 17:47:05 +00:00
Chris Barber
ab329f0fe8 [next][node][redwood][remix] Update @vercel/nft (#10540)
Updating `nft` to fix a bug. We're a couple version behind. Here's all cumulative changes:

- 0.24.1
  - resolve cjs deps as cjs instead of esm
- 0.24.0
  - drop node@14 
- 0.23.1
  - use builtinModules from module
- 0.23.0
  - resolve: export resolve() function
- 0.22.6
  - Make caching work correctly in async context
2023-09-19 14:27:54 +00:00
Nathan Rajlich
8b35333446 [examples] Update "remix" template to v2 (#10532) 2023-09-18 16:32:30 -03:00
Vercel Release Bot
a92467719b Version Packages (#10528)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## vercel@32.2.5

### Patch Changes

- Updated dependencies
\[[`849eedf0f`](849eedf0f2),
[`f6f16b034`](f6f16b0347),
[`3035e18fb`](3035e18fb6),
[`cb784aeb9`](cb784aeb9c)]:
    -   @vercel/next@4.0.6
    -   @vercel/remix-builder@2.0.6

## @vercel/next@4.0.6

### Patch Changes

- Fix feature flag detection
([#10531](https://github.com/vercel/vercel/pull/10531))

## @vercel/remix-builder@2.0.6

### Patch Changes

- Fix ESM mode for Edge runtime
([#10530](https://github.com/vercel/vercel/pull/10530))

- Update `@remix-run/dev` fork to v2.0.0
([#10526](https://github.com/vercel/vercel/pull/10526))

- Fixes for Remix v2
([#10525](https://github.com/vercel/vercel/pull/10525))
2023-09-18 15:44:07 -03:00
Nathan Rajlich
f6f16b0347 [remix] Fix ESM mode for Edge runtime, add Remix v2 E2E test (#10530)
Similar to the default import fix from #10525 which was for Node runtime, but this one fixes Edge runtime.

Also adds an E2E test for Remix v2, including both a Node route and Edge route.
2023-09-18 18:26:53 +00:00
Trek Glowacki
92ad73b8f3 Restore datadog checking with logs not exit codes (#10527)
Restores DataDog flakey test detection. Briefly disabled because the old method of using exit codes would bail the entire workflow.

Taking the Turbo team's suggestion of looking at `runData.execution` values to avoid an extra loop. Now with unit tests!
2023-09-18 16:43:16 +00:00
Steven
849eedf0f2 [next] fix feature flag detection (#10531)
For feature flags, we use the string `1` for enabled and the string `0` for disabled.

So we need to check the value of the env var, not the presence of the env var.
2023-09-18 16:17:55 +00:00
Vercel Release Bot
848a62e4a5 [tests] Upgrade Turbo to version 1.10.14 (#10529)
This auto-generated PR updates Turbo to version 1.10.14
2023-09-18 15:31:52 +00:00
Nathan Rajlich
cb784aeb9c [remix] Fixes for Remix v2 (#10525)
The Remix v2 template now uses `"type": "module"` by default, so adjust our bundling logic to account for that possibility.
2023-09-18 14:32:08 +00:00
Vercel Release Bot
3035e18fb6 [remix] Update @remix-run/dev to v2.0.0 (#10526)
This auto-generated PR updates `@remix-run/dev` to version 2.0.0.
2023-09-18 14:05:42 +00:00
Vercel Release Bot
eb40c4c4a0 Version Packages (#10514)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @vercel/fs-detectors@5.1.0

### Minor Changes

- Add support for bun detection in monorepo
([#10511](https://github.com/vercel/vercel/pull/10511))

## vercel@32.2.4

### Patch Changes

- Add support for bun detection in monorepo
([#10511](https://github.com/vercel/vercel/pull/10511))

- Updated dependencies
\[[`1b6f3a0f6`](1b6f3a0f65)]:
    -   @vercel/static-build@2.0.6

## @vercel/static-build@2.0.6

### Patch Changes

- Add support for bun detection in monorepo
([#10511](https://github.com/vercel/vercel/pull/10511))

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-15 15:13:54 -04:00
Nathan Rajlich
c90ee12b17 Update bun changeset to bump static-build + CLI (#10516)
Also reverts https://github.com/vercel/vercel/pull/10515 since it didn't
work the way we were hoping.
2023-09-15 16:06:32 -03:00
Nathan Rajlich
78be0200b4 Enable changesets experimental updateInternalDependents: 'always' config (#10515)
From the [sounds of
it](https://github.com/changesets/changesets/blob/main/docs/experimental-options.md#updateinternaldependents-type-out-of-range--always),
setting this config value to "always" will make it so that a patch
release will happen for a package that depends on another package which
is being bumped. This would normally happen anyways, but does not happen
when a dependency is a `devDependency` rather than a `dependency` (which
happens for the Builders and CLI, since those packages get bundled and
thus have their deps listed as devDependencies).
2023-09-15 15:54:47 -03:00
Steven
1b6f3a0f65 [fs-detectors] Add support for bun detection in monorepo (#10511)
E2E test looks like:

```sh
bunx create-turbo@canary
cd my-turborepo
gh repo create
vc link --repo
vc deploy
```
2023-09-15 14:13:26 -04:00
Trek Glowacki
eceb15ace9 Revert skipping datadog reports (#10513)
Revert
[.github/workflows/test.yml](https://github.com/vercel/vercel/pull/10513/files#diff-faff1af3d8ff408964a57b2e475f69a6b7c7b71c9978cccc8f471798caac2c88)
to an earlier version.
2023-09-15 13:49:24 -04:00
Vercel Release Bot
fa3f701e05 Version Packages (#10505)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-14 16:06:33 -05:00
Trek Glowacki
9953fc765f Complete the error message (#10509) 2023-09-14 11:39:53 -05:00
Trek Glowacki
29ea1af971 Skip DataDog reporting if Turbo cache indicates the uploaded files would be identical (#10501) 2023-09-14 10:47:20 -05:00
Zack Tanner
083aad448e [next] missed a prerender for experimentalBypassFor (#10504)
Missed this in https://github.com/vercel/vercel/pull/10497
2023-09-14 01:19:13 +00:00
Vercel Release Bot
314a105ba1 Version Packages (#10493)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-13 17:15:29 -05:00
Ikko Eltociear Ashimine
1abda9ca87 [cli] Fix typo in corepack.ts (#10499)
Co-authored-by: Sean Massa <EndangeredMassa@gmail.com>
2023-09-13 08:26:51 -05:00
Zack Tanner
7a0fed970c [next] provide experimentalBypassFor to prerender from manifest (#10497) 2023-09-12 17:40:49 -05:00
Jimmy Lai
2f461a8b0b next.js: add option to use bundled runtime (#10485)
This PR adds an environment variable that should allow us to test the bundled version for Next.js on Vercel, see https://github.com/vercel/next.js/pull/52997 for reference.

The changes include:
- a new environment variable `VERCEL_NEXT_BUNDLED_SERVER`
- some logic changes that will put app route handlers into their own lambda groups
- extra logic to require early the rendering runtimes (see PR above for details)
2023-09-12 19:45:23 +00:00
Steven
ec894bdf7f [frameworks] Add bun install placeholder (#10492)
<img width="899" alt="image"
src="https://github.com/vercel/vercel/assets/229881/f37a3cfd-bbb9-4c33-88dc-cd19b9855a47">
2023-09-12 11:29:24 -04:00
Andy
009cea6d30 [examples] Use placeholder for API Key (#10490)
The Ionic example has an actual Google Maps API key by default and we'd
like to not have it displayed, so we'll replace it with a placeholder
instead. Considering it's commented out anyways, this will be a no-op.

---------

Co-authored-by: Steven <steven@ceriously.com>
2023-09-12 11:25:02 -04:00
Nathan Rajlich
1bab21026e [remix] Fix usage with bun install (#10489) 2023-09-12 09:55:16 -05:00
Vercel Release Bot
bcebab7517 Version Packages (#10478)
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @vercel/build-utils@7.2.0

### Minor Changes

- Add new optional prerender field: experimentalStreamingLambdaPath
([#10476](https://github.com/vercel/vercel/pull/10476))

- [build-utils] Add zero config detection for bun package manager
([#10486](https://github.com/vercel/vercel/pull/10486))

### Patch Changes

- add `experimentalBypassFor` field to Prerender
([#10481](https://github.com/vercel/vercel/pull/10481))

## vercel@32.2.1

### Patch Changes

- Update @vercel/fun@1.1.0
([#10477](https://github.com/vercel/vercel/pull/10477))

- [node] upgrade edge-runtime
([#10451](https://github.com/vercel/vercel/pull/10451))

- Updated dependencies
\[[`6784e7751`](6784e77516),
[`a8ad17626`](a8ad176262),
[`0ee089a50`](0ee089a501),
[`f15cba614`](f15cba6148),
[`b265e13d4`](b265e13d40),
[`50e04dd85`](50e04dd858),
[`45b73c7e8`](45b73c7e86),
[`a732d30c8`](a732d30c84),
[`9d64312aa`](9d64312aaa),
[`6baefc825`](6baefc825a),
[`989f0d813`](989f0d8139),
[`d8bc570f6`](d8bc570f60)]:
    -   @vercel/go@3.0.1
    -   @vercel/redwood@2.0.2
    -   @vercel/remix-builder@2.0.4
    -   @vercel/hydrogen@1.0.1
    -   @vercel/static-build@2.0.5
    -   @vercel/build-utils@7.2.0
    -   @vercel/next@4.0.3
    -   @vercel/node@3.0.5
    -   @vercel/python@4.0.1
    -   @vercel/ruby@2.0.2

## @vercel/client@13.0.3

### Patch Changes

- Updated dependencies
\[[`50e04dd85`](50e04dd858),
[`45b73c7e8`](45b73c7e86),
[`d8bc570f6`](d8bc570f60)]:
    -   @vercel/build-utils@7.2.0

## @vercel/edge@1.0.2

### Patch Changes

- [node] upgrade edge-runtime
([#10451](https://github.com/vercel/vercel/pull/10451))

## @vercel/gatsby-plugin-vercel-builder@2.0.5

### Patch Changes

- Updated dependencies
\[[`50e04dd85`](50e04dd858),
[`45b73c7e8`](45b73c7e86),
[`9d64312aa`](9d64312aaa),
[`d8bc570f6`](d8bc570f60)]:
    -   @vercel/build-utils@7.2.0
    -   @vercel/node@3.0.5

## @vercel/go@3.0.1

### Patch Changes

- Update to esbuild script
([#10468](https://github.com/vercel/vercel/pull/10468))

## @vercel/hydrogen@1.0.1

### Patch Changes

- Use `build-builder.mjs` script to bundle, and remove types and source
maps ([#10480](https://github.com/vercel/vercel/pull/10480))

## @vercel/next@4.0.3

### Patch Changes

- fix content-type for RSC prefetches
([#10487](https://github.com/vercel/vercel/pull/10487))

## @vercel/node@3.0.5

### Patch Changes

- [node] upgrade edge-runtime
([#10451](https://github.com/vercel/vercel/pull/10451))

- Updated dependencies
\[[`50e04dd85`](50e04dd858),
[`45b73c7e8`](45b73c7e86),
[`d8bc570f6`](d8bc570f60)]:
    -   @vercel/build-utils@7.2.0

## @vercel/python@4.0.1

### Patch Changes

- Update to esbuild script
([#10470](https://github.com/vercel/vercel/pull/10470))

## @vercel/redwood@2.0.2

### Patch Changes

- Update to esbuild script
([#10471](https://github.com/vercel/vercel/pull/10471))

## @vercel/remix-builder@2.0.4

### Patch Changes

- Use `build-builder.mjs` script to bundle, and remove types and source
maps ([#10479](https://github.com/vercel/vercel/pull/10479))

## @vercel/ruby@2.0.2

### Patch Changes

- Update to esbuild script
([#10472](https://github.com/vercel/vercel/pull/10472))

## @vercel/static-build@2.0.5

### Patch Changes

- Build package using "esbuild"
([#10462](https://github.com/vercel/vercel/pull/10462))

-   Updated dependencies \[]:
    -   @vercel/gatsby-plugin-vercel-builder@2.0.5

## @vercel-internals/types@1.0.10

### Patch Changes

- Updated dependencies
\[[`50e04dd85`](50e04dd858),
[`45b73c7e8`](45b73c7e86),
[`d8bc570f6`](d8bc570f60)]:
    -   @vercel/build-utils@7.2.0

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-09-11 17:30:02 -04:00
Steven
45b73c7e86 [build-utils] Add zero config detection for bun package manager (#10486)
> [!IMPORTANT]  
> This PR will only support Bun as a package manager at build time. 
> Bun will **not** work at runtime with Serverless Functions or Edge
Functions at this time.

- Depends on https://github.com/vercel/api/pull/21869
- Fixes https://github.com/orgs/vercel/discussions/2021
- Closes https://github.com/vercel/vercel/pull/10244
- Related https://github.com/nodejs/corepack/issues/295
- Docs https://bun.sh/docs/install
2023-09-11 17:26:34 -04:00
Zack Tanner
a732d30c84 [next] fix content-type for RSC prefetches (#10487)
This ensures that the `.prefetch.rsc` requests respond with the correct `content-type` since this is used by Next.js to determine if a request is valid or not (and in the case it's invalid, an mpa navigation will occur)

Fixes: https://github.com/vercel/next.js/issues/54934
2023-09-11 19:04:16 +00:00
Lee Robinson
8504735808 [examples] Update Astro starter (#10397)
Deployed https://astro.vercel.app/image.
2023-09-11 16:29:54 +00:00
Kiko Beats
9d64312aaa [node] upgrade edge-runtime (#10451) 2023-09-10 13:14:43 +00:00
Chris Barber
a8ad176262 [redwood] Use new esbuild script (#10471) 2023-09-09 01:48:54 +00:00
Nathan Rajlich
0ee089a501 [remix] Bundle, remove types and source maps (#10479)
For consistency with other Builders.
2023-09-09 00:35:56 +00:00
Zack Tanner
d8bc570f60 [build-utils] add experimentalBypassFor field to Prerender (#10481)
This adds an experimental flag to `Prerender` outputs as a way to programmatically bypass the cache and hit the lambda directly, using a similar interface to `has`. 

(Note: I copied over `HasField` from `@vercel/router-utils` since it wasn't available for import in `build-utils`, but can add it as a dep if that's preferred)

The specific use-case being targeted here relates to https://github.com/vercel/next.js/pull/51534 -- a Next.js page marked static should still be able to initiate server actions.
2023-09-08 23:33:59 +00:00
Nathan Rajlich
f15cba6148 [hydrogen] Bundle, remove types and source maps (#10480)
Similar to #10479, but for `@vercel/hydrogen`.
2023-09-08 22:55:03 +00:00
Chris Barber
989f0d8139 [ruby] Use new esbuild script (#10472) 2023-09-08 17:27:17 -05:00
Chris Barber
6784e77516 [go] Update to esbuild script (#10468)
Co-authored-by: Nathan Rajlich <n@n8.io>
2023-09-08 17:00:40 -05:00
Chris Barber
6baefc825a [python] Update to esbuild script (#10470)
Co-authored-by: Steven <steven@ceriously.com>
2023-09-08 16:23:23 -05:00
Chris Barber
0a08e4b23e [cli] Update @vercel/fun@1.1.0 (#10477) 2023-09-08 15:39:13 -05:00
Nathan Rajlich
b265e13d40 [static-build] Use esbuild (#10462)
Switch to using esbuild to compile + bundle `@vercel/static-build`.
2023-09-08 19:39:12 +00:00
Nabeel Sulieman
50e04dd858 Add optional experimentalStreamingLambda field for prerender (#10476)
This adds a new `experimentalStreamingLambda` field to Prerender
outputs, allowing references to an optional streaming lambda path.
2023-09-08 11:42:06 -07:00
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
319 changed files with 11180 additions and 4072 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 @huozhi
/examples/hugo @styfle /examples/hugo @styfle
/examples/jekyll @styfle /examples/jekyll @styfle
/examples/zola @styfle /examples/zola @styfle

View File

@@ -83,7 +83,7 @@ jobs:
env: env:
FORCE_COLOR: '1' FORCE_COLOR: '1'
- name: Test ${{matrix.packageName}} - name: Test ${{matrix.packageName}}
run: node utils/gen.js && node_modules/.bin/turbo run test --cache-dir=".turbo" --log-order=stream --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }} run: node utils/gen.js && node_modules/.bin/turbo run test --summarize --cache-dir=".turbo" --log-order=stream --scope=${{matrix.packageName}} --no-deps -- ${{ join(matrix.testPaths, ' ') }}
shell: bash shell: bash
env: env:
JEST_JUNIT_OUTPUT_FILE: ${{github.workspace}}/.junit-reports/${{matrix.scriptName}}-${{matrix.packageName}}-${{matrix.chunkNumber}}-${{ matrix.runner }}.xml JEST_JUNIT_OUTPUT_FILE: ${{github.workspace}}/.junit-reports/${{matrix.scriptName}}-${{matrix.packageName}}-${{matrix.chunkNumber}}-${{ matrix.runner }}.xml
@@ -91,13 +91,18 @@ jobs:
VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }} VERCEL_TEST_TOKEN: ${{ secrets.VERCEL_TEST_TOKEN }}
VERCEL_TEST_REGISTRATION_URL: ${{ secrets.VERCEL_TEST_REGISTRATION_URL }} VERCEL_TEST_REGISTRATION_URL: ${{ secrets.VERCEL_TEST_REGISTRATION_URL }}
FORCE_COLOR: '1' FORCE_COLOR: '1'
- name: 'Determing Turbo HIT or MISS'
id: turbo-summary
shell: bash
run: |
TURBO_MISS_COUNT=`node utils/determine-turbo-hit-or-miss.js`
echo "MISS COUNT: $TURBO_MISS_COUNT"
echo "misses=$TURBO_MISS_COUNT" >> $GITHUB_OUTPUT
- name: fetch ssl certificate after tests (linux, os x) - name: fetch ssl certificate after tests (linux, os x)
if: matrix.runner != 'windows-latest' if: matrix.runner != 'windows-latest'
run: echo | openssl s_client -showcerts -servername 'api.vercel.com' -connect 76.76.21.21:443 run: echo | openssl s_client -showcerts -servername 'api.vercel.com' -connect 76.76.21.21:443
- name: 'Upload Test Report to Datadog' - name: 'Upload Test Report to Datadog'
if: always() if: ${{ steps['turbo-summary'].outputs.misses != '0' }}
run: 'npx @datadog/datadog-ci@2.18.1 junit upload --service vercel-cli .junit-reports' run: 'npx @datadog/datadog-ci@2.18.1 junit upload --service vercel-cli .junit-reports'
env: env:
DATADOG_API_KEY: ${{secrets.DATADOG_API_KEY_CLI}} DATADOG_API_KEY: ${{secrets.DATADOG_API_KEY_CLI}}

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

@@ -3,9 +3,10 @@
This directory is a brief example of an [Astro](https://astro.build/) site that can be deployed to Vercel with zero configuration. This demo showcases: This directory is a brief example of an [Astro](https://astro.build/) site that can be deployed to Vercel with zero configuration. This demo showcases:
- `/` - A static page (pre-rendered) - `/` - A static page (pre-rendered)
- `/ssr` - A page that uses server-side rendering (through Vercel Edge Functions) - `/ssr` - A page that uses server-side rendering (through [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions))
- `/ssr-with-swr-caching` - Similar to the previous page, but also caches the response on the Vercel Edge Network using `cache-control` headers - `/ssr-with-swr-caching` - Similar to the previous page, but also caches the response on the [Vercel Edge Network](https://vercel.com/docs/edge-network/overview) using `cache-control` headers
- `/edge.json` - An Astro API Endpoint that returns JSON data using Vercel Edge Functions - `/image` - Astro [Asset](https://docs.astro.build/en/guides/assets/) using Vercel [Image Optimization](https://vercel.com/docs/image-optimization)
- `/edge.json` - An Astro API Endpoint that returns JSON data using [Vercel Edge Functions](https://vercel.com/docs/functions/edge-functions)
Learn more about [Astro on Vercel](https://vercel.com/docs/frameworks/astro). Learn more about [Astro on Vercel](https://vercel.com/docs/frameworks/astro).

View File

@@ -1,7 +1,17 @@
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
// Use Vercel Edge Functions (Recommended)
import vercel from '@astrojs/vercel/edge'; import vercel from '@astrojs/vercel/edge';
// Can also use Serverless Functions
// import vercel from '@astrojs/vercel/serverless';
// Or a completely static build
// import vercel from '@astrojs/vercel/static';
export default defineConfig({ export default defineConfig({
output: 'server', output: 'server',
adapter: vercel(), experimental: {
assets: true
},
adapter: vercel({
imageService: true,
}),
}); });

View File

@@ -8,8 +8,8 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/vercel": "3.2.2", "@astrojs/vercel": "3.8.2",
"astro": "^2.2.1", "astro": "^2.10.14",
"react": "18.2.0", "react": "18.2.0",
"web-vitals": "^3.3.1" "web-vitals": "^3.3.1"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,4 +1,4 @@
/// <reference types="astro/client" /> /// <reference types="astro/client-image" />
interface ImportMetaEnv { interface ImportMetaEnv {
readonly PUBLIC_VERCEL_ANALYTICS_ID: string; readonly PUBLIC_VERCEL_ANALYTICS_ID: string;

View File

@@ -0,0 +1,6 @@
---
import { Image } from 'astro:assets';
import astroLogo from '../assets/logo.png';
---
<Image src={astroLogo} alt="Astro Logo" width={50} quality={75} />

View File

@@ -29,7 +29,7 @@
<!-- Replace the API key with your own, see: <!-- Replace the API key with your own, see:
https://developers.google.com/maps/documentation/javascript/get-api-key --> https://developers.google.com/maps/documentation/javascript/get-api-key -->
<!-- <script async="" defer="" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB8pf6ZdFQj5qw7rc_HSGrhUwQKfIe9ICw"></script> --> <!-- <script async="" defer="" src="https://maps.googleapis.com/maps/api/js?key=<YOUR_GOOGLE_MAPS_API_KEY>"></script> -->
<noscript>Please enable JavaScript to continue using this application.</noscript> <noscript>Please enable JavaScript to continue using this application.</noscript>
</body> </body>

View File

@@ -10,6 +10,8 @@ npm run dev
yarn dev yarn dev
# or # or
pnpm dev pnpm dev
# or
bun dev
``` ```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

File diff suppressed because it is too large Load Diff

View File

@@ -9,17 +9,17 @@
"lint": "next lint" "lint": "next lint"
}, },
"dependencies": { "dependencies": {
"@types/node": "20.5.0", "@types/node": "20.6.3",
"@types/react": "18.2.20", "@types/react": "18.2.22",
"@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.49.0",
"eslint-config-next": "13.4.18", "eslint-config-next": "13.5.2",
"next": "13.4.18", "next": "13.5.2",
"postcss": "8.4.28", "postcss": "8.4.30",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"tailwindcss": "3.3.3", "tailwindcss": "3.3.3",
"typescript": "5.1.6" "typescript": "5.2.2"
} }
} }

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.2"
} },
"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

@@ -4,9 +4,4 @@ node_modules
/build /build
/public/build /public/build
.env .env
.vercel .vercel
.output
/api/index.js
/api/index.js.map

View File

@@ -19,7 +19,7 @@ export default function App() {
<html lang="en"> <html lang="en">
<head> <head>
<meta charSet="utf-8" /> <meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta /> <Meta />
<Links /> <Links />
</head> </head>

View File

@@ -1,10 +1,15 @@
import type { V2_MetaFunction } from "@vercel/remix"; import type { MetaFunction } from "@vercel/remix";
export const meta: V2_MetaFunction = () => [{ title: "New Remix App" }]; export const meta: MetaFunction = () => {
return [
{ title: "New Remix App" },
{ name: "description", content: "Welcome to Remix!" },
];
};
export default function Index() { export default function Index() {
return ( return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}> <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
<h1>Welcome to Remix</h1> <h1>Welcome to Remix</h1>
<ul> <ul>
<li> <li>

View File

@@ -1,8 +1,8 @@
import type { V2_MetaFunction } from "@vercel/remix"; import type { MetaFunction } from "@vercel/remix";
export const config = { runtime: "edge" }; export const config = { runtime: "edge" };
export const meta: V2_MetaFunction = () => [{ title: "Remix@Edge | New Remix App" }]; export const meta: MetaFunction = () => [{ title: "Remix@Edge | New Remix App" }];
export default function Edge() { export default function Edge() {
return ( return (

View File

@@ -1,32 +1,34 @@
{ {
"name": "my-remix-app",
"private": true, "private": true,
"sideEffects": false, "sideEffects": false,
"type": "module",
"scripts": { "scripts": {
"build": "remix build", "build": "remix build",
"dev": "remix dev", "dev": "remix dev --manual",
"start": "remix-serve build", "start": "remix-serve ./build/index.js",
"typecheck": "tsc" "typecheck": "tsc"
}, },
"dependencies": { "dependencies": {
"@remix-run/css-bundle": "^1.18.0", "@remix-run/css-bundle": "^2.0.0",
"@remix-run/node": "^1.18.0", "@remix-run/node": "^2.0.0",
"@remix-run/react": "^1.18.0", "@remix-run/react": "^2.0.0",
"@remix-run/serve": "^1.18.0", "@remix-run/serve": "^2.0.0",
"@vercel/analytics": "^0.1.11", "@vercel/analytics": "^1.0.2",
"@vercel/remix": "^1.18.0", "@vercel/remix": "^2.0.0",
"isbot": "^3.6.8", "isbot": "^3.6.8",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0"
}, },
"devDependencies": { "devDependencies": {
"@remix-run/dev": "^1.18.0", "@remix-run/dev": "^2.0.0",
"@remix-run/eslint-config": "^1.18.0", "@remix-run/eslint-config": "^2.0.0",
"@types/react": "^18.0.25", "@types/react": "^18.2.20",
"@types/react-dom": "^18.0.11", "@types/react-dom": "^18.2.7",
"eslint": "^8.28.0", "eslint": "^8.38.0",
"typescript": "^5.1.3" "typescript": "^5.1.6"
}, },
"engines": { "engines": {
"node": ">=14" "node": ">=18.0.0"
} }
} }

View File

@@ -1,17 +1,8 @@
/** @type {import('@remix-run/dev').AppConfig} */ /** @type {import('@remix-run/dev').AppConfig} */
module.exports = { export default {
future: {
v2_dev: true,
v2_errorBoundary: true,
v2_headers: true,
v2_meta: true,
v2_normalizeFormMethod: true,
v2_routeConvention: true,
},
ignoredRouteFiles: ["**/.*"], ignoredRouteFiles: ["**/.*"],
serverModuleFormat: "cjs",
// appDirectory: "app", // appDirectory: "app",
// assetsBuildDirectory: "public/build", // assetsBuildDirectory: "public/build",
// serverBuildPath: "build/index.js",
// publicPath: "/build/", // publicPath: "/build/",
// serverBuildPath: "build/index.js",
}; };

View File

@@ -1,13 +1,13 @@
{ {
"include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"], "include": ["remix.env.d.ts", "**/*.ts", "**/*.tsx"],
"compilerOptions": { "compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2019"], "lib": ["DOM", "DOM.Iterable", "ES2022"],
"isolatedModules": true, "isolatedModules": true,
"esModuleInterop": true, "esModuleInterop": true,
"jsx": "react-jsx", "jsx": "react-jsx",
"moduleResolution": "node", "moduleResolution": "Bundler",
"resolveJsonModule": true, "resolveJsonModule": true,
"target": "ES2019", "target": "ES2022",
"strict": true, "strict": true,
"allowJs": true, "allowJs": true,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,

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,33 @@
# @vercel-internals/types # @vercel-internals/types
## 1.0.11
### Patch Changes
- Updated dependencies [[`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3)]:
- @vercel/build-utils@7.2.1
## 1.0.10
### Patch Changes
- Updated dependencies [[`50e04dd85`](https://github.com/vercel/vercel/commit/50e04dd8584664c842a86c15d92d654f4ea8dcbb), [`45b73c7e8`](https://github.com/vercel/vercel/commit/45b73c7e86458564dc0bab007f6f6365c4c4ab5d), [`d8bc570f6`](https://github.com/vercel/vercel/commit/d8bc570f604950d97156d4f33c8accecf3b3b28f)]:
- @vercel/build-utils@7.2.0
## 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

@@ -65,6 +65,8 @@ export type User = {
billing: Billing; billing: Billing;
name?: string; name?: string;
limited?: boolean; limited?: boolean;
version?: 'northstar';
defaultTeamId?: string;
}; };
export interface Team { export interface Team {

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.11",
"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.2.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.14",
"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,37 @@
# @vercel/build-utils # @vercel/build-utils
## 7.2.1
### Patch Changes
- Internal variants ([#10549](https://github.com/vercel/vercel/pull/10549))
## 7.2.0
### Minor Changes
- Add new optional prerender field: experimentalStreamingLambdaPath ([#10476](https://github.com/vercel/vercel/pull/10476))
- [build-utils] Add zero config detection for bun package manager ([#10486](https://github.com/vercel/vercel/pull/10486))
### Patch Changes
- add `experimentalBypassFor` field to Prerender ([#10481](https://github.com/vercel/vercel/pull/10481))
## 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.2.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

@@ -16,7 +16,7 @@ import { cloneEnv } from '../clone-env';
// Only allow one `runNpmInstall()` invocation to run concurrently // Only allow one `runNpmInstall()` invocation to run concurrently
const runNpmInstallSema = new Sema(1); const runNpmInstallSema = new Sema(1);
export type CliType = 'yarn' | 'npm' | 'pnpm'; export type CliType = 'yarn' | 'npm' | 'pnpm' | 'bun';
export interface ScanParentDirsResult { export interface ScanParentDirsResult {
/** /**
@@ -284,16 +284,23 @@ export async function scanParentDirs(
readPackageJson && pkgJsonPath readPackageJson && pkgJsonPath
? JSON.parse(await fs.readFile(pkgJsonPath, 'utf8')) ? JSON.parse(await fs.readFile(pkgJsonPath, 'utf8'))
: undefined; : undefined;
const [yarnLockPath, npmLockPath, pnpmLockPath] = await walkParentDirsMulti({ const [yarnLockPath, npmLockPath, pnpmLockPath, bunLockPath] =
await walkParentDirsMulti({
base: '/', base: '/',
start: destPath, start: destPath,
filenames: ['yarn.lock', 'package-lock.json', 'pnpm-lock.yaml'], filenames: [
'yarn.lock',
'package-lock.json',
'pnpm-lock.yaml',
'bun.lockb',
],
}); });
let lockfilePath: string | undefined; let lockfilePath: string | undefined;
let lockfileVersion: number | undefined; let lockfileVersion: number | undefined;
let cliType: CliType = 'yarn'; let cliType: CliType = 'yarn';
const [hasYarnLock, packageLockJson, pnpmLockYaml] = await Promise.all([ const [hasYarnLock, packageLockJson, pnpmLockYaml, bunLockBin] =
await Promise.all([
Boolean(yarnLockPath), Boolean(yarnLockPath),
npmLockPath npmLockPath
? readConfigFile<{ lockfileVersion: number }>(npmLockPath) ? readConfigFile<{ lockfileVersion: number }>(npmLockPath)
@@ -301,9 +308,10 @@ export async function scanParentDirs(
pnpmLockPath pnpmLockPath
? readConfigFile<{ lockfileVersion: number }>(pnpmLockPath) ? readConfigFile<{ lockfileVersion: number }>(pnpmLockPath)
: null, : null,
bunLockPath ? fs.readFile(bunLockPath, 'utf8') : null,
]); ]);
// Priority order is Yarn > pnpm > npm // Priority order is Yarn > pnpm > npm > bun
if (hasYarnLock) { if (hasYarnLock) {
cliType = 'yarn'; cliType = 'yarn';
lockfilePath = yarnLockPath; lockfilePath = yarnLockPath;
@@ -315,6 +323,11 @@ export async function scanParentDirs(
cliType = 'npm'; cliType = 'npm';
lockfilePath = npmLockPath; lockfilePath = npmLockPath;
lockfileVersion = packageLockJson.lockfileVersion; lockfileVersion = packageLockJson.lockfileVersion;
} else if (bunLockBin) {
cliType = 'bun';
lockfilePath = bunLockPath;
// TODO: read "bun-lockfile-format-v0"
lockfileVersion = 0;
} }
const packageJsonPath = pkgJsonPath || undefined; const packageJsonPath = pkgJsonPath || undefined;
@@ -451,6 +464,10 @@ export async function runNpmInstall(
commandArgs = args commandArgs = args
.filter(a => a !== '--prefer-offline') .filter(a => a !== '--prefer-offline')
.concat(['install', '--unsafe-perm']); .concat(['install', '--unsafe-perm']);
} else if (cliType === 'bun') {
// @see options https://bun.sh/docs/cli/install
opts.prettyCommand = 'bun install';
commandArgs = ['install', ...args];
} else { } else {
opts.prettyCommand = 'yarn install'; opts.prettyCommand = 'yarn install';
commandArgs = ['install', ...args]; commandArgs = ['install', ...args];
@@ -505,6 +522,7 @@ export function getEnvForPackageManager({
const npm7 = '/node16/bin-npm7'; const npm7 = '/node16/bin-npm7';
const pnpm7 = '/pnpm7/node_modules/.bin'; const pnpm7 = '/pnpm7/node_modules/.bin';
const pnpm8 = '/pnpm8/node_modules/.bin'; const pnpm8 = '/pnpm8/node_modules/.bin';
const bun1 = '/bun1';
const corepackEnabled = env.ENABLE_EXPERIMENTAL_COREPACK === '1'; const corepackEnabled = env.ENABLE_EXPERIMENTAL_COREPACK === '1';
if (cliType === 'npm') { if (cliType === 'npm') {
if ( if (
@@ -516,7 +534,7 @@ export function getEnvForPackageManager({
) { ) {
// Ensure that npm 7 is at the beginning of the `$PATH` // Ensure that npm 7 is at the beginning of the `$PATH`
newEnv.PATH = `${npm7}${path.delimiter}${oldPath}`; newEnv.PATH = `${npm7}${path.delimiter}${oldPath}`;
console.log('Detected `package-lock.json` generated by npm 7+...'); console.log('Detected `package-lock.json` generated by npm 7+');
} }
} else if (cliType === 'pnpm') { } else if (cliType === 'pnpm') {
if ( if (
@@ -528,7 +546,7 @@ export function getEnvForPackageManager({
// Ensure that pnpm 7 is at the beginning of the `$PATH` // Ensure that pnpm 7 is at the beginning of the `$PATH`
newEnv.PATH = `${pnpm7}${path.delimiter}${oldPath}`; newEnv.PATH = `${pnpm7}${path.delimiter}${oldPath}`;
console.log( console.log(
`Detected \`pnpm-lock.yaml\` version ${lockfileVersion} generated by pnpm 7...` `Detected \`pnpm-lock.yaml\` version ${lockfileVersion} generated by pnpm 7`
); );
} else if ( } else if (
typeof lockfileVersion === 'number' && typeof lockfileVersion === 'number' &&
@@ -539,7 +557,16 @@ export function getEnvForPackageManager({
// Ensure that pnpm 8 is at the beginning of the `$PATH` // Ensure that pnpm 8 is at the beginning of the `$PATH`
newEnv.PATH = `${pnpm8}${path.delimiter}${oldPath}`; newEnv.PATH = `${pnpm8}${path.delimiter}${oldPath}`;
console.log( console.log(
`Detected \`pnpm-lock.yaml\` version ${lockfileVersion} generated by pnpm 8...` `Detected \`pnpm-lock.yaml\` version ${lockfileVersion} generated by pnpm 8`
);
}
} else if (cliType === 'bun') {
if (!oldPath.includes(bun1) && !corepackEnabled) {
// Ensure that Bun 1 is at the beginning of the `$PATH`
newEnv.PATH = `${bun1}${path.delimiter}${oldPath}`;
console.log('Detected `bun.lockb` generated by Bun');
console.warn(
'Warning: Bun is used as a package manager at build time only, not at runtime with Functions'
); );
} }
} else { } else {
@@ -548,7 +575,6 @@ export function getEnvForPackageManager({
newEnv.YARN_NODE_LINKER = 'node-modules'; newEnv.YARN_NODE_LINKER = 'node-modules';
} }
} }
return newEnv; return newEnv;
} }
@@ -614,6 +640,8 @@ export async function runPackageJsonScript(
opts.prettyCommand = `npm run ${scriptName}`; opts.prettyCommand = `npm run ${scriptName}`;
} else if (cliType === 'pnpm') { } else if (cliType === 'pnpm') {
opts.prettyCommand = `pnpm run ${scriptName}`; opts.prettyCommand = `pnpm run ${scriptName}`;
} else if (cliType === 'bun') {
opts.prettyCommand = `bun run ${scriptName}`;
} else { } else {
opts.prettyCommand = `yarn run ${scriptName}`; opts.prettyCommand = `yarn run ${scriptName}`;
} }

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

@@ -1,4 +1,4 @@
import { File } from './types'; import type { File, HasField } from './types';
import { Lambda } from './lambda'; import { Lambda } from './lambda';
interface PrerenderOptions { interface PrerenderOptions {
@@ -12,6 +12,8 @@ interface PrerenderOptions {
initialStatus?: number; initialStatus?: number;
passQuery?: boolean; passQuery?: boolean;
sourcePath?: string; sourcePath?: string;
experimentalBypassFor?: HasField;
experimentalStreamingLambdaPath?: string;
} }
export class Prerender { export class Prerender {
@@ -26,6 +28,8 @@ export class Prerender {
public initialStatus?: number; public initialStatus?: number;
public passQuery?: boolean; public passQuery?: boolean;
public sourcePath?: string; public sourcePath?: string;
public experimentalBypassFor?: HasField;
public experimentalStreamingLambdaPath?: string;
constructor({ constructor({
expiration, expiration,
@@ -38,6 +42,8 @@ export class Prerender {
initialStatus, initialStatus,
passQuery, passQuery,
sourcePath, sourcePath,
experimentalBypassFor,
experimentalStreamingLambdaPath,
}: PrerenderOptions) { }: PrerenderOptions) {
this.type = 'Prerender'; this.type = 'Prerender';
this.expiration = expiration; this.expiration = expiration;
@@ -86,6 +92,26 @@ export class Prerender {
); );
} }
if (experimentalBypassFor !== undefined) {
if (
!Array.isArray(experimentalBypassFor) ||
experimentalBypassFor.some(
field =>
typeof field !== 'object' ||
// host doesn't need a key
(field.type !== 'host' && typeof field.key !== 'string') ||
typeof field.type !== 'string' ||
(field.value !== undefined && typeof field.value !== 'string')
)
) {
throw new Error(
'The `experimentalBypassFor` argument for `Prerender` must be Array of objects with fields `type`, `key` and optionally `value`.'
);
}
this.experimentalBypassFor = experimentalBypassFor;
}
if (typeof fallback === 'undefined') { if (typeof fallback === 'undefined') {
throw new Error( throw new Error(
'The `fallback` argument for `Prerender` needs to be a `FileBlob`, `FileFsRef`, `FileRef`, or null.' 'The `fallback` argument for `Prerender` needs to be a `FileBlob`, `FileFsRef`, `FileRef`, or null.'
@@ -130,5 +156,14 @@ export class Prerender {
} }
this.allowQuery = allowQuery; this.allowQuery = allowQuery;
} }
if (experimentalStreamingLambdaPath !== undefined) {
if (typeof experimentalStreamingLambdaPath !== 'string') {
throw new Error(
'The `experimentalStreamingLambdaPath` argument for `Prerender` must be a string.'
);
}
this.experimentalStreamingLambdaPath = experimentalStreamingLambdaPath;
}
} }
} }

View File

@@ -45,6 +45,18 @@ export interface Config {
[key: string]: unknown; [key: string]: unknown;
} }
export type HasField = Array<
| {
type: 'host';
value: string;
}
| {
type: 'header' | 'cookie' | 'query';
key: string;
value?: string;
}
>;
export interface Meta { export interface Meta {
isDev?: boolean; isDev?: boolean;
devCacheDir?: string; devCacheDir?: string;
@@ -300,9 +312,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;
} }
@@ -418,6 +434,13 @@ export interface Cron {
schedule: string; schedule: string;
} }
// TODO: Proper description once complete
export interface Flag {
key: string;
defaultValue?: unknown;
metadata: Record<string, unknown>;
}
/** The framework which created the function */ /** The framework which created the function */
export interface FunctionFramework { export interface FunctionFramework {
slug: string; slug: string;
@@ -442,6 +465,7 @@ export interface BuildResultV2Typical {
framework?: { framework?: {
version: string; version: string;
}; };
flags?: Flag[];
} }
export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput; export type BuildResultV2 = BuildResultV2Typical | BuildResultBuildOutput;

View File

@@ -0,0 +1,2 @@
.vercel
public

View File

@@ -0,0 +1,8 @@
import { mkdir, rm, writeFile } from 'node:fs/promises'
import { say } from 'cowsay'
const text = say({ text: `bun version: ${process.versions.bun}` })
const content = say({ text })
await rm('./public', { recursive: true, force: true })
await mkdir('./public', { recursive: true })
await writeFile('./public/index.txt', content)

Binary file not shown.

View File

@@ -0,0 +1,9 @@
{
"private": true,
"scripts": {
"build": "bun build.js"
},
"dependencies": {
"cowsay": "1.5.0"
}
}

View File

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

View File

@@ -133,6 +133,22 @@ describe('Test `getEnvForPackageManager()`', () => {
PATH: `/pnpm7/node_modules/.bin${delimiter}foo`, PATH: `/pnpm7/node_modules/.bin${delimiter}foo`,
}, },
}, },
{
name: 'should set path if bun v1 is detected',
args: {
cliType: 'bun',
nodeVersion: { major: 18, range: '18.x', runtime: 'nodejs18.x' },
lockfileVersion: 0,
env: {
FOO: 'bar',
PATH: '/usr/local/bin',
},
},
want: {
FOO: 'bar',
PATH: `/bun1${delimiter}/usr/local/bin`,
},
},
{ {
name: 'should not set pnpm path if corepack is enabled', name: 'should not set pnpm path if corepack is enabled',
args: { args: {

View File

@@ -344,6 +344,70 @@ it('should support initialHeaders and initialStatus correctly', async () => {
}); });
}); });
it('should support experimentalBypassFor correctly', async () => {
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
experimentalBypassFor: [{ type: 'header', key: 'Next-Action' }],
});
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
experimentalBypassFor: [
{ type: 'header', key: 'Next-Action' },
{
type: 'cookie',
key: '__prerender_bypass',
value: 'some-long-bypass-token-to-make-it-work',
},
],
});
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
experimentalBypassFor: [{ type: 'query', key: 'bypass', value: '1' }],
});
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
experimentalBypassFor: [{ type: 'host', value: 'vercel.com' }],
});
expect(() => {
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
// @ts-expect-error: testing invalid args
experimentalBypassFor: 'foo',
});
}).toThrowError(
'The `experimentalBypassFor` argument for `Prerender` must be Array of objects with fields `type`, `key` and optionally `value`.'
);
expect(() => {
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
// @ts-expect-error: testing invalid args
experimentalBypassFor: [{ type: 'header', value: { foo: 'bar' } }],
});
}).toThrowError(
'The `experimentalBypassFor` argument for `Prerender` must be Array of objects with fields `type`, `key` and optionally `value`.'
);
});
it('should support passQuery correctly', async () => { it('should support passQuery correctly', async () => {
new Prerender({ new Prerender({
expiration: 1, expiration: 1,
@@ -387,6 +451,42 @@ it('should support passQuery correctly', async () => {
); );
}); });
it('should support experimentalStreamingLambdaPath correctly', async () => {
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
experimentalStreamingLambdaPath: undefined,
});
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
experimentalStreamingLambdaPath: '/some/path/to/lambda',
});
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
});
expect(() => {
new Prerender({
expiration: 1,
fallback: null,
group: 1,
bypassToken: 'some-long-bypass-token-to-make-it-work',
// @ts-expect-error testing invalid field
experimentalStreamingLambdaPath: 1,
});
}).toThrowError(
`The \`experimentalStreamingLambdaPath\` argument for \`Prerender\` must be a string.`
);
});
it('should support require by path for legacy builders', () => { it('should support require by path for legacy builders', () => {
const index = require('../'); const index = require('../');
@@ -440,6 +540,15 @@ it(
ms('1m') ms('1m')
); );
it('should return cliType bun and correct lock file for bun v1', async () => {
const fixture = path.join(__dirname, 'fixtures', '30-bun-v1');
const result = await scanParentDirs(fixture);
expect(result.cliType).toEqual('bun');
expect(result.lockfileVersion).toEqual(0);
expect(result.lockfilePath).toEqual(path.join(fixture, 'bun.lockb'));
expect(result.packageJsonPath).toEqual(path.join(fixture, 'package.json'));
});
it('should return lockfileVersion 2 with npm7', async () => { it('should return lockfileVersion 2 with npm7', async () => {
const fixture = path.join(__dirname, 'fixtures', '20-npm-7'); const fixture = path.join(__dirname, 'fixtures', '20-npm-7');
const result = await scanParentDirs(fixture); const result = await scanParentDirs(fixture);

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,170 @@
# vercel # vercel
## 32.3.0
### Minor Changes
- [cli] Support northstar users ([#10535](https://github.com/vercel/vercel/pull/10535))
### Patch Changes
- Internal variants ([#10549](https://github.com/vercel/vercel/pull/10549))
- [speed insights] Prepare for migration to new speed insights package ([#10500](https://github.com/vercel/vercel/pull/10500))
- Updated dependencies [[`b0898a665`](https://github.com/vercel/vercel/commit/b0898a66591d5296dc38ffcf0e8345c9338b72f3), [`10d4e51ac`](https://github.com/vercel/vercel/commit/10d4e51ac57b76f05ddc0bf3adf220e2490244fc), [`decdf27fb`](https://github.com/vercel/vercel/commit/decdf27fb5ca914fe50a9320c4fd50ef79d2fbb3), [`f5ca497b7`](https://github.com/vercel/vercel/commit/f5ca497b7522a2dad637cef238da9716ac133057), [`ab329f0fe`](https://github.com/vercel/vercel/commit/ab329f0fe88e9cb72607d0cba41f5e168d77e077), [`d0d052011`](https://github.com/vercel/vercel/commit/d0d0520111264434d57d5920de0f622f6a2588dc), [`9bb3067de`](https://github.com/vercel/vercel/commit/9bb3067de28be77f3ce268a31a7aa6184836dfb1)]:
- @vercel/static-build@2.0.7
- @vercel/node@3.0.6
- @vercel/build-utils@7.2.1
- @vercel/next@4.0.7
- @vercel/python@4.0.2
- @vercel/redwood@2.0.3
- @vercel/remix-builder@2.0.7
- @vercel/go@3.0.2
## 32.2.5
### Patch Changes
- Updated dependencies [[`849eedf0f`](https://github.com/vercel/vercel/commit/849eedf0f2841211e4175d374f1cf01330bf9611), [`f6f16b034`](https://github.com/vercel/vercel/commit/f6f16b0347bac9f5c33c79ccb1fb9fd9d254cae5), [`3035e18fb`](https://github.com/vercel/vercel/commit/3035e18fb67dfe7031e235a74136a41948f86d5a), [`cb784aeb9`](https://github.com/vercel/vercel/commit/cb784aeb9c9e4eddf1c65b61849a87edb1117af1)]:
- @vercel/next@4.0.6
- @vercel/remix-builder@2.0.6
## 32.2.4
### Patch Changes
- Add support for bun detection in monorepo ([#10511](https://github.com/vercel/vercel/pull/10511))
- Updated dependencies [[`1b6f3a0f6`](https://github.com/vercel/vercel/commit/1b6f3a0f6534f71c7486a4e33ac199f1da330626)]:
- @vercel/static-build@2.0.6
## 32.2.3
### Patch Changes
- Updated dependencies [[`083aad448`](https://github.com/vercel/vercel/commit/083aad448e45edae296da3201eec9f890a01d22d)]:
- @vercel/next@4.0.5
## 32.2.2
### Patch Changes
- Updated dependencies [[`7a0fed970`](https://github.com/vercel/vercel/commit/7a0fed970c39cb8f4df70544ded3284d3538b06a), [`2f461a8b0`](https://github.com/vercel/vercel/commit/2f461a8b0bcbdd05da0516395c2905c2d0242682), [`1bab21026`](https://github.com/vercel/vercel/commit/1bab21026ec0bb8a4a8fbeac3d6e4a197f1030fd)]:
- @vercel/next@4.0.4
- @vercel/remix-builder@2.0.5
## 32.2.1
### Patch Changes
- Update @vercel/fun@1.1.0 ([#10477](https://github.com/vercel/vercel/pull/10477))
- [node] upgrade edge-runtime ([#10451](https://github.com/vercel/vercel/pull/10451))
- Updated dependencies [[`6784e7751`](https://github.com/vercel/vercel/commit/6784e77516ba180a691e3c48323b32bb4506d7b6), [`a8ad17626`](https://github.com/vercel/vercel/commit/a8ad176262ef822860ce338927e6f959961d2d32), [`0ee089a50`](https://github.com/vercel/vercel/commit/0ee089a501ebb78901c4afe1658e794917998f8f), [`f15cba614`](https://github.com/vercel/vercel/commit/f15cba6148a0cdb6975db7724775c35ab7d929b2), [`b265e13d4`](https://github.com/vercel/vercel/commit/b265e13d40d541b77148fa79ac60b4c4dd10974c), [`50e04dd85`](https://github.com/vercel/vercel/commit/50e04dd8584664c842a86c15d92d654f4ea8dcbb), [`45b73c7e8`](https://github.com/vercel/vercel/commit/45b73c7e86458564dc0bab007f6f6365c4c4ab5d), [`a732d30c8`](https://github.com/vercel/vercel/commit/a732d30c8409f96f59ea5406e974a6c4186cc130), [`9d64312aa`](https://github.com/vercel/vercel/commit/9d64312aaaa875a4e193b7602c50e5dc68979aad), [`6baefc825`](https://github.com/vercel/vercel/commit/6baefc825ad7cfc3a5edce31cb4244721452f753), [`989f0d813`](https://github.com/vercel/vercel/commit/989f0d813910d8d67ed355de93018f1dcd91b6ba), [`d8bc570f6`](https://github.com/vercel/vercel/commit/d8bc570f604950d97156d4f33c8accecf3b3b28f)]:
- @vercel/go@3.0.1
- @vercel/redwood@2.0.2
- @vercel/remix-builder@2.0.4
- @vercel/hydrogen@1.0.1
- @vercel/static-build@2.0.5
- @vercel/build-utils@7.2.0
- @vercel/next@4.0.3
- @vercel/node@3.0.5
- @vercel/python@4.0.1
- @vercel/ruby@2.0.2
## 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.3.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.2.1",
"@vercel/go": "3.0.0", "@vercel/go": "3.0.2",
"@vercel/hydrogen": "1.0.0", "@vercel/hydrogen": "1.0.1",
"@vercel/next": "4.0.0", "@vercel/next": "4.0.7",
"@vercel/node": "3.0.0", "@vercel/node": "3.0.6",
"@vercel/python": "4.0.0", "@vercel/python": "4.0.2",
"@vercel/redwood": "2.0.0", "@vercel/redwood": "2.0.3",
"@vercel/remix-builder": "2.0.0", "@vercel/remix-builder": "2.0.7",
"@vercel/ruby": "2.0.0", "@vercel/ruby": "2.0.2",
"@vercel/static-build": "2.0.0" "@vercel/static-build": "2.0.7"
}, },
"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.1",
"@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,12 +86,12 @@
"@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.11",
"@vercel/client": "13.0.0", "@vercel/client": "13.0.4",
"@vercel/error-utils": "2.0.0", "@vercel/error-utils": "2.0.1",
"@vercel/frameworks": "2.0.0", "@vercel/frameworks": "2.0.2",
"@vercel/fs-detectors": "5.0.0", "@vercel/fs-detectors": "5.1.0",
"@vercel/fun": "1.0.4", "@vercel/fun": "1.1.0",
"@vercel/ncc": "0.24.0", "@vercel/ncc": "0.24.0",
"@vercel/routing-utils": "3.0.0", "@vercel/routing-utils": "3.0.0",
"@zeit/source-map-support": "0.6.2", "@zeit/source-map-support": "0.6.2",
@@ -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

@@ -27,7 +27,7 @@ export const help = () => `
pull [path] Pull your Project Settings from the cloud pull [path] Pull your Project Settings from the cloud
redeploy [url|id] Rebuild and deploy a previous deployment. redeploy [url|id] Rebuild and deploy a previous deployment.
rollback [url|id] Quickly revert back to a previous deployment rollback [url|id] Quickly revert back to a previous deployment
switch [scope] Switches between teams and your personal account switch [scope] Switches between different scopes
${chalk.dim('Advanced')} ${chalk.dim('Advanced')}

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

@@ -21,6 +21,7 @@ import {
NowBuildError, NowBuildError,
Cron, Cron,
validateNpmrc, validateNpmrc,
Flag,
} from '@vercel/build-utils'; } from '@vercel/build-utils';
import { import {
detectBuilders, detectBuilders,
@@ -93,6 +94,7 @@ interface BuildOutputConfig {
version: string; version: string;
}; };
crons?: Cron[]; crons?: Cron[];
flags?: Flag[];
} }
/** /**
@@ -426,6 +428,23 @@ async function doBuild(
const ops: Promise<Error | void>[] = []; const ops: Promise<Error | void>[] = [];
const dependencies = [
...Object.keys(pkg?.dependencies ?? {}),
...Object.keys(pkg?.devDependencies ?? {}),
];
const isUsingSpeedInsights = dependencies.some(
d => d === '@vercel/speed-insights'
);
if (isUsingSpeedInsights && process.env.VERCEL_ANALYTICS_ID) {
output.warn(
`The \`VERCEL_ANALYTICS_ID\` environment variable is deprecated and will be removed in a future release. Please remove it from your environment variables`
);
delete process.env.VERCEL_ANALYTICS_ID;
}
// Write the `detectedBuilders` result to output dir // Write the `detectedBuilders` result to output dir
const buildsJsonBuilds = new Map<Builder, SerializedBuilder>( const buildsJsonBuilds = new Map<Builder, SerializedBuilder>(
builds.map(build => { builds.map(build => {
@@ -627,6 +646,7 @@ async function doBuild(
const mergedWildcard = mergeWildcard(buildResults.values()); const mergedWildcard = mergeWildcard(buildResults.values());
const mergedOverrides: Record<string, PathOverride> = const mergedOverrides: Record<string, PathOverride> =
overrides.length > 0 ? Object.assign({}, ...overrides) : undefined; overrides.length > 0 ? Object.assign({}, ...overrides) : undefined;
const mergedFlags = mergeFlags(buildResults.values());
const framework = await getFramework(cwd, buildResults); const framework = await getFramework(cwd, buildResults);
@@ -640,6 +660,7 @@ async function doBuild(
overrides: mergedOverrides, overrides: mergedOverrides,
framework, framework,
crons: mergedCrons, crons: mergedCrons,
flags: mergedFlags,
}; };
await fs.writeJSON(join(outputDir, 'config.json'), config, { spaces: 2 }); await fs.writeJSON(join(outputDir, 'config.json'), config, { spaces: 2 });
@@ -774,3 +795,15 @@ function mergeWildcard(
} }
return wildcard; return wildcard;
} }
function mergeFlags(
buildResults: Iterable<BuildResult | BuildOutputConfig>
): BuildResultV2Typical['flags'] {
return Array.from(buildResults).flatMap(result => {
if ('flags' in result) {
return result.flags ?? [];
}
return [];
});
}

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 scope',
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;
} }

View File

@@ -53,6 +53,12 @@ export default async function move(
const teams = await getTeams(client); const teams = await getTeams(client);
const matchId = await findDestinationMatch(destination, user, teams); const matchId = await findDestinationMatch(destination, user, teams);
if (matchId && matchId === user.id && user.version === 'northstar') {
output.error(`You may not move your domain to your user account.`);
return 1;
}
if (!matchId && !opts['--yes']) { if (!matchId && !opts['--yes']) {
output.warn( output.warn(
`You're not a member of ${param(destination)}. ` + `You're not a member of ${param(destination)}. ` +

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';
@@ -54,6 +55,12 @@ function tryReadHeadSync(path: string, length: number) {
} }
} }
const VARIABLES_TO_IGNORE = [
'VERCEL_ANALYTICS_ID',
'VERCEL_SPEED_INSIGHTS_ID',
'VERCEL_WEB_ANALYTICS_ID',
];
export default async function pull( export default async function pull(
client: Client, client: Client,
link: ProjectLinked, link: ProjectLinked,
@@ -121,7 +128,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);
} }
} }
@@ -130,6 +137,7 @@ export default async function pull(
CONTENTS_PREFIX + CONTENTS_PREFIX +
Object.keys(records) Object.keys(records)
.sort() .sort()
.filter(key => !VARIABLES_TO_IGNORE.includes(key))
.map(key => `${key}="${escapeValue(records[key])}"`) .map(key => `${key}="${escapeValue(records[key])}"`)
.join('\n') + .join('\n') +
'\n'; '\n';

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

@@ -19,6 +19,7 @@ import Client from '../../util/client';
import { LoginResult } from '../../util/login/types'; import { LoginResult } from '../../util/login/types';
import { help } from '../help'; import { help } from '../help';
import { loginCommand } from './command'; import { loginCommand } from './command';
import { updateCurrentTeamAfterLogin } from '../../util/login/update-current-team-after-login';
export default async function login(client: Client): Promise<number> { export default async function login(client: Client): Promise<number> {
const { output } = client; const { output } = client;
@@ -67,20 +68,16 @@ export default async function login(client: Client): Promise<number> {
return result; return result;
} }
// If the token was upgraded (not a new login), then don't modify const isNewLogin = !client.authConfig.token;
// the current scope.
if (!client.authConfig.token) {
if (result.teamId) {
// SSO login, so set the current scope to the appropriate Team
client.config.currentTeam = result.teamId;
} else {
delete client.config.currentTeam;
}
}
// Save the user's authentication token to the configuration file. // Save the user's authentication token to the configuration file.
client.authConfig.token = result.token; client.authConfig.token = result.token;
// If we have a new login, update `currentTeam`
if (isNewLogin) {
await updateCurrentTeamAfterLogin(client, output, result.teamId);
}
writeToAuthConfigFile(client.authConfig); writeToAuthConfigFile(client.authConfig);
writeToConfigFile(client.config); writeToConfigFile(client.config);

View File

@@ -3,7 +3,7 @@ import { packageName } from '../../util/pkg-name';
export const logoutCommand: Command = { export const logoutCommand: Command = {
name: 'logout', name: 'logout',
description: 'Logout the current authenticated user or team.', description: 'Logout the current authenticated user.',
arguments: [], arguments: [],
options: [], options: [],
examples: [ examples: [

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 scope',
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,10 +48,12 @@ const main = async client => {
try { try {
({ contextName } = await getScope(client)); ({ contextName } = await getScope(client));
} catch (err) { } catch (err) {
if (isErrnoException(err)) {
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') { if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
output.error(err.message); output.error(err.message);
return 1; 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';
@@ -40,11 +39,12 @@ export default async function list(client: Client): Promise<number> {
apiVersion: 2, apiVersion: 2,
}); });
let { currentTeam } = config; let { currentTeam } = config;
const accountIsCurrent = !currentTeam;
output.spinner('Fetching user information'); output.spinner('Fetching user information');
const user = await getUser(client); const user = await getUser(client);
const accountIsCurrent = !currentTeam && user.version !== 'northstar';
if (accountIsCurrent) { if (accountIsCurrent) {
currentTeam = user.id; currentTeam = user.id;
} }
@@ -56,12 +56,14 @@ export default async function list(client: Client): Promise<number> {
current: id === currentTeam ? chars.tick : '', current: id === currentTeam ? chars.tick : '',
})); }));
if (user.version !== 'northstar') {
teamList.unshift({ teamList.unshift({
id: user.id, id: user.id,
name: user.email, name: user.email,
value: user.username || user.email, value: user.username || user.email,
current: accountIsCurrent ? chars.tick : '', current: accountIsCurrent ? chars.tick : '',
}); });
}
// Bring the current Team to the beginning of the list // Bring the current Team to the beginning of the list
if (!accountIsCurrent) { if (!accountIsCurrent) {
@@ -72,19 +74,21 @@ export default async function list(client: Client): Promise<number> {
// Printing // Printing
output.stopSpinner(); output.stopSpinner();
console.log(); // empty line client.stdout.write('\n'); // empty line
table( table(
['', 'id', 'email / name'], ['', 'id', 'email / name'],
teamList.map(team => [team.current, team.value, team.name]), teamList.map(team => [team.current, team.value, team.name]),
[1, 5] [1, 5],
(str: string) => {
client.stdout.write(str);
}
); );
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 client.stdout.write('\n'); // empty line
output.log(`To display the next page run ${cmd(nextCmd)}`); output.log(`To display the next page run ${cmd(nextCmd)}`);
} }

View File

@@ -70,7 +70,10 @@ export default async function main(client: Client, desiredSlug?: string) {
suffix += ` ${emoji('locked')}`; suffix += ` ${emoji('locked')}`;
} }
const choices = [ const personalAccountChoice =
user.version === 'northstar'
? []
: [
{ separator: 'Personal Account' }, { separator: 'Personal Account' },
{ {
name: `${user.name || user.email} (${user.username})${suffix}`, name: `${user.name || user.email} (${user.username})${suffix}`,
@@ -78,6 +81,10 @@ export default async function main(client: Client, desiredSlug?: string) {
short: user.username, short: user.username,
selected: personalScopeSelected, selected: personalScopeSelected,
}, },
];
const choices = [
...personalAccountChoice,
{ separator: 'Teams' }, { separator: 'Teams' },
...teamChoices, ...teamChoices,
]; ];
@@ -97,6 +104,11 @@ export default async function main(client: Client, desiredSlug?: string) {
} }
if (desiredSlug === user.username || desiredSlug === user.email) { if (desiredSlug === user.username || desiredSlug === user.email) {
if (user.version === 'northstar') {
output.error('You cannot set your Personal Account as the scope.');
return 1;
}
// Switch to user's personal account // Switch to user's personal account
if (personalScopeSelected) { if (personalScopeSelected) {
output.log('No changes made'); output.log('No changes made');

View File

@@ -56,6 +56,7 @@ import { ProxyAgent } from 'proxy-agent';
import box from './util/output/box'; import box from './util/output/box';
import { execExtension } from './util/extension/exec'; import { execExtension } from './util/extension/exec';
import { help } from './args'; import { help } from './args';
import { updateCurrentTeamAfterLogin } from './util/login/update-current-team-after-login';
const VERCEL_DIR = getGlobalPathConfig(); const VERCEL_DIR = getGlobalPathConfig();
const VERCEL_CONFIG_PATH = configFiles.getConfigFilePath(); const VERCEL_CONFIG_PATH = configFiles.getConfigFilePath();
@@ -337,17 +338,12 @@ const main = async () => {
return result; return result;
} }
if (result.teamId) {
// SSO login, so set the current scope to the appropriate Team
client.config.currentTeam = result.teamId;
} else {
delete client.config.currentTeam;
}
// When `result` is a string it's the user's authentication token. // When `result` is a string it's the user's authentication token.
// It needs to be saved to the configuration file. // It needs to be saved to the configuration file.
client.authConfig.token = result.token; client.authConfig.token = result.token;
await updateCurrentTeamAfterLogin(client, output, result.teamId);
configFiles.writeToAuthConfigFile(client.authConfig); configFiles.writeToAuthConfigFile(client.authConfig);
configFiles.writeToConfigFile(client.config); configFiles.writeToConfigFile(client.config);
@@ -447,6 +443,11 @@ const main = async () => {
} }
if (user.id === scope || user.email === scope || user.username === scope) { if (user.id === scope || user.email === scope || user.username === scope) {
if (user.version === 'northstar') {
output.error('You cannot set your Personal Account as the scope.');
return 1;
}
delete client.config.currentTeam; delete client.config.currentTeam;
} else { } else {
let teams = []; let teams = [];

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(
@@ -40,7 +41,7 @@ export async function initCorepack({
const pkgManagerName = pkg.packageManager.split('@')[0]; const pkgManagerName = pkg.packageManager.split('@')[0];
// We must explicitly call `corepack enable npm` since `corepack enable` // We must explicitly call `corepack enable npm` since `corepack enable`
// doesn't work with npm. See https://github.com/nodejs/corepack/pull/24 // doesn't work with npm. See https://github.com/nodejs/corepack/pull/24
// Also, `corepack enable` is too broad and will change the verison of // Also, `corepack enable` is too broad and will change the version of
// yarn & pnpm even though those versions are not specified by the user. // yarn & pnpm even though those versions are not specified by the user.
// See https://github.com/nodejs/corepack#known-good-releases // See https://github.com/nodejs/corepack#known-good-releases
// Finally, we use `--install-directory` so we can cache the result to // Finally, we use `--install-directory` so we can cache the result to

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

@@ -59,7 +59,7 @@ export class TeamDeleted extends NowError<'TEAM_DELETED', {}> {
constructor() { constructor() {
super({ super({
code: 'TEAM_DELETED', code: 'TEAM_DELETED',
message: `Your team was deleted. You can switch to a different one using ${getCommandName( message: `Your team was deleted or you were removed from the team. You can switch to a different one using ${getCommandName(
`switch` `switch`
)}.`, )}.`,
meta: {}, meta: {},
@@ -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

@@ -15,9 +15,12 @@ export default async function getScope(
const user = await getUser(client); const user = await getUser(client);
let contextName = user.username || user.email; let contextName = user.username || user.email;
let team: Team | null = null; let team: Team | null = null;
const defaultTeamId =
user.version === 'northstar' ? user.defaultTeamId : undefined;
const currentTeamOrDefaultTeamId = client.config.currentTeam || defaultTeamId;
if (client.config.currentTeam && opts.getTeam !== false) { if (currentTeamOrDefaultTeamId && opts.getTeam !== false) {
team = await getTeamById(client, client.config.currentTeam); team = await getTeamById(client, currentTeamOrDefaultTeamId);
if (!team) { if (!team) {
throw new TeamDeleted(); throw new TeamDeleted();

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