Compare commits

...

113 Commits

Author SHA1 Message Date
Steven
5cf0c316e9 Publish Stable
- @vercel/python@2.1.0
2021-11-23 08:57:58 -05:00
Steven
f4501433c8 Publish Canary
- vercel@23.1.3-canary.38
 - vercel-plugin-python@1.0.0-canary.6
 - @vercel/python@2.0.6-canary.7
2021-11-22 18:43:37 -05:00
Steven
19831593ce [python] Add warning for deprecated version (#7053)
- Print warning when python 3.6 is selected
- Print warning when invalid python version is selected
2021-11-22 23:36:30 +00:00
Steven
5d85bb1426 [tests] Bump cancel action to 0.9.1 (#7055) 2021-11-22 17:24:35 -05:00
Andy Bitz
f194d54b0c Publish Canary
- vercel@23.1.3-canary.37
2021-11-22 23:14:32 +01:00
Andy
6542086843 Revert "[cli] Switch from hardlinks to symlinks in vc build" (#7054)
* Revert "[cli] Switch from hardlinks to symlinks in vc build (#7026)"

This reverts commit 6dff0875f5.

* Keep copy logic
2021-11-22 23:12:46 +01:00
Andy Bitz
2721b3449d Publish Canary
- @vercel/build-utils@2.12.3-canary.20
 - vercel@23.1.3-canary.36
 - @vercel/client@10.2.3-canary.21
 - @vercel/node@1.12.2-canary.7
 - vercel-plugin-go@1.0.0-canary.5
 - vercel-plugin-node@1.12.2-canary.11
 - vercel-plugin-python@1.0.0-canary.5
 - vercel-plugin-ruby@1.0.0-canary.4
2021-11-22 13:22:56 +01:00
Andy
adb284519a [plugin-node][node] Fix dependency installation, handler path, and build script (#7043)
* [plugin-node][node] Fix dependency installation, handler path, and build script

* Use smaller library for testing

* Make test work on windows

* Remove .output before fixture runs and update routes update

* Apply suggestions from code review

Co-authored-by: Steven <steven@ceriously.com>

Co-authored-by: Steven <steven@ceriously.com>
2021-11-22 13:21:20 +01:00
Steven
b2d91f3121 [cli] Fix metrics crash on some platforms (#7034) 2021-11-20 20:31:39 -05:00
Steven
32664cd13b Publish Canary
- @vercel/build-utils@2.12.3-canary.19
 - vercel@23.1.3-canary.35
 - @vercel/client@10.2.3-canary.20
 - @vercel/frameworks@0.5.1-canary.12
 - vercel-plugin-go@1.0.0-canary.4
 - vercel-plugin-node@1.12.2-canary.10
 - vercel-plugin-python@1.0.0-canary.4
 - vercel-plugin-ruby@1.0.0-canary.3
2021-11-20 10:20:05 -05:00
Sam Ko
db468c489a [frameworks] Fix Parcel default output directory to dist (#7029)
### Related Issues

The Parcel template via the Project Creating Flow returns a build error because the default output directory for the Parcel **Framework Preset** is searching for `public` instead of `dist`. The default behavior of Parcel's CLI I believe is `dist`.

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [ ] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-11-20 01:44:22 +00:00
Steven
edd9bb506c [frameworks][cli] Consolidate buildCommand and devCommand (#7032)
* [frameworks] Consolidate buildCommand and devCommand

* Fix default build command when no override or package.json found
2021-11-19 19:07:52 -05:00
Steven
a72549a290 [tests] Make test more reliable for function timeout (#7033) 2021-11-19 17:26:32 -05:00
Steven
4aa6a13912 Publish Canary
- vercel@23.1.3-canary.34
 - vercel-plugin-python@1.0.0-canary.3
 - @vercel/python@2.0.6-canary.6
2021-11-19 14:42:02 -05:00
Steven
81ea0082f1 [python] Upgrade python 3.9 (#7008)
* [python] Upgrade python 3.9

* Fix python path

* Improve testing

* Add support for version selection via Pipfile

* Parse the "Pipfile.lock" instead

* Fix support for Node.js 12
2021-11-19 13:42:17 -05:00
Jared Palmer
6dff0875f5 [cli] Switch from hardlinks to symlinks in vc build (#7026)
* Switch from hardlinks to symlinks in vc build

* Remove error handling that fs-extra already takes care of

* Add comment

* Put back symlink error handling
2021-11-19 12:36:31 -05:00
Steven
30aa392c0a [tests] Increase CI duration (#7030)
Seems like macOS sometimes exceeds 60 min so this bumps the timeout.

The build can be between 3 minutes and 5 minutes. The tests can be between 45 minutes and 55 minutes.
2021-11-19 14:59:12 +00:00
Miroslav Simulcik
c4fc060030 [cli] Fix spinner output outside of TTY (#7017)
* Fix spinner output outside of TTY

* Use console.log

* Fix tests

* Revert "Fix tests"

This reverts commit 44383eea2dc3bb699d943079d77961ed86fe65d6.

* Revert "Use console.log"

This reverts commit 251bd1d624532e9ecfb4aee5b31538aa4ba740ef.
2021-11-17 14:04:59 +01:00
Steven
3fa08bf64f [cli] Fix update command to favor npm (#7018) 2021-11-16 16:07:31 -05:00
Steven
43056bde1f Publish Canary
- vercel@23.1.3-canary.33
2021-11-15 18:07:17 -05:00
Steven
a49966b9b4 [cli] Change vc build to use stdout (#7005) 2021-11-15 18:06:48 -05:00
Steven
7f55de71bb Publish Canary
- vercel@23.1.3-canary.32
 - @vercel/go@1.2.4-canary.4
 - vercel-plugin-go@1.0.0-canary.3
2021-11-15 13:37:04 -05:00
Steven
db8e36e04c [go] Add support for version 1.17 (#7002)
* Support more Go versions

Co-authored-by: Stefan M <StefMa@users.noreply.github.com>
2021-11-15 13:36:26 -05:00
Andy Bitz
82924bb5c4 Publish Canary
- vercel@23.1.3-canary.31
 - vercel-plugin-node@1.12.2-canary.9
2021-11-15 14:11:55 +01:00
Andy
18b5fac93e [vercel-plugin-node] Use .nft.json files instead of directories. (#6988)
* Ignore install step if package.json does not exist in entrypoint directory

* [plugin-node] Use `.nft.json` files

* Bump @vercel/fun

* Update package.json

* Remove package

* Remove import

* Update paths

* Revert "Update paths"

This reverts commit fa304e90381f475c64b2333402dca489813522da.

* Update path for windows

* Update handler path
2021-11-15 14:08:49 +01:00
Miroslav Simulcik
a6012e600b [cli] Fix updating of gitignore in vercel link (#6986)
* Fix updating of gitignore in link

* Fix modification of gitignore file during linking

* Fix empty file case
2021-11-12 17:11:21 +01:00
Steven
c3abf73f58 Publish Canary
- @vercel/build-utils@2.12.3-canary.18
 - vercel@23.1.3-canary.30
 - @vercel/client@10.2.3-canary.19
 - vercel-plugin-go@1.0.0-canary.2
 - vercel-plugin-node@1.12.2-canary.8
 - vercel-plugin-python@1.0.0-canary.2
 - vercel-plugin-ruby@1.0.0-canary.2
2021-11-11 14:54:33 -05:00
Steven
4873b8b379 [build-utils][node] Add updateFunctionsManifest function (#6971) 2021-11-11 14:53:43 -05:00
Miroslav Simulcik
6248139281 [cli] Prevent recursion of vercel build and vercel dev (#6960)
* Prevent infinite recursion of vercel build and dev

* Improved text

* Improved the text further

* Add tests

* Debug test

* Add debug log

* Debug test

* debug test

* Debug test

* Fix test

* Debug tests

* Debug test

* Remove only from tests

* Add error documentation

* Improved docs

* Fix other test

* Fixed links to error docs

* Remove legacy error page

* Use nicer error links

Co-authored-by: Leo Lamprecht <leo@vercel.com>
2021-11-11 10:51:30 -05:00
Miroslav Simulcik
507a5de3cd [tests] Fix getting of config paths (#6969)
Co-authored-by: Steven <steven@ceriously.com>
2021-11-09 14:34:41 -05:00
Gary Borton
be1c78e72f Publish Canary
- vercel@23.1.3-canary.29
 - vercel-plugin-middleware@0.0.0-canary.7
2021-11-09 11:07:01 -08:00
Gary Borton
c277c649c6 Fix middleware build result. Return middleware next when invalid result. (#6963)
* Fix middleware build result. Return middleware next when invalid result.

* Add a unit test that would have failed before previous commit.

* Copy next.js behavior.

* Add a test for invalid responses from middleware.

Co-authored-by: Leo Lamprecht <leo@vercel.com>
2021-11-09 11:06:16 -08:00
Steven
ed1dacd276 Publish Canary
- @vercel/build-utils@2.12.3-canary.17
 - vercel@23.1.3-canary.28
 - @vercel/client@10.2.3-canary.18
 - vercel-plugin-go@1.0.0-canary.1
 - vercel-plugin-python@1.0.0-canary.1
 - vercel-plugin-ruby@1.0.0-canary.1
 - @vercel/python@2.0.6-canary.5
 - @vercel/ruby@1.2.8-canary.4
2021-11-09 12:50:34 -05:00
Steven
144e890bfa Add plugin packages for go/python/ruby (#6961)
* Add plugin packages

* Fix usage

* Fix build

* Fix workspace linking to build-utils
2021-11-09 12:48:40 -05:00
Andy Bitz
af097c2c06 Publish Canary
- vercel@23.1.3-canary.27
2021-11-09 16:44:14 +01:00
Andy
873a582986 [cli] Ignore .next/cache in vc build (#6968)
* [cli] Ignore .next/cache in `vc build`

* Handle middleware-manifest.json

* Update manifest update
2021-11-09 16:43:26 +01:00
Andy Bitz
986b4c0b1a Publish Canary
- vercel@23.1.3-canary.26
2021-11-09 01:31:30 +01:00
Andy
14071819ac [cli] Fix NFT output path for monorepos (#6965)
* [cli] Fix `output` path for `.output` for `node_modules`

* Use baseDir instead of cwd

* Update comment

* Update output for requiredServerFiles
2021-11-09 01:30:49 +01:00
jj@jjsweb.site
2a8588a0c5 Publish Canary
- @vercel/build-utils@2.12.3-canary.16
 - vercel@23.1.3-canary.25
 - @vercel/client@10.2.3-canary.17
 - @vercel/frameworks@0.5.1-canary.11
 - @vercel/routing-utils@1.11.4-canary.6
2021-11-08 14:42:18 -06:00
JJ Kasper
0f7e89f76c [routing-utils] Add caseSensitive field to routes schema (#6952)
### Related Issues

x-ref: https://github.com/vercel/customer-issues/issues/34

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-11-08 20:29:31 +00:00
Andy Bitz
e68ed33a88 Publish Canary
- vercel@23.1.3-canary.24
 - vercel-plugin-middleware@0.0.0-canary.6
2021-11-08 19:38:58 +01:00
Gary Borton
d3e98cdb73 [cli] Run middleware as a plugin instead of running directly (#6941)
* Move loadPlugins to a utils file to be shared w/ dev server.

* Update loadCliPlugins to also return startDevServer and runDevMiddleware based plugins.

* Move plugins back to dependencies.

These can't be bundled as it interferes with plugin resolution.

* Hook up middleware plugins to dev server.

* Pass output object to loadCliPlugins instead of a logging function.

* Allow more than one runDevMiddleware defining plugins.

* Bundle esbuild w/ middleware plugin.

* Keep esbuild as an external

* Update middleware's esbuild.

* set old space size

* Revert "set old space size"

This reverts commit b579194a862949a11769e9087f01c31f2e1f3b60.

* Use --max-old-space-size for CLI unit tests

* Increase memory

* Use `run.js` to set the memory

* Make NODE_OPTIONS optional

Co-authored-by: Leo Lamprecht <leo@vercel.com>
Co-authored-by: Andy <AndyBitz@users.noreply.github.com>
Co-authored-by: Andy Bitz <artzbitz@gmail.com>
2021-11-08 19:38:13 +01:00
Andy Bitz
bf4e77110f Publish Canary
- vercel@23.1.3-canary.23
 - @vercel/node@1.12.2-canary.6
 - vercel-plugin-node@1.12.2-canary.7
2021-11-08 15:00:01 +01:00
Nathan Rajlich
5b5197d2c5 [node] Create vercel-plugin-node (#6874)
* [node] Refactor to Vercel CLI Plugin

* Enforce "index" suffix on output Serverless Functions

So that nesting works properly

* Some cleanup

* Add version

* Use `@vercel/static-config`

* .

* Add support for wildcard routes

* Don't compile dotfiles, underscore prefixed files, files within `node_modules`, nor TypeScript definition files

Matches the logic from `maybeGetBuilder()` in `@vercel/build-utils`.

* Bump version

* Introduce testing framework

* Debug

* Add test without any deps

* Longer timeout to install Node.js for vercel/fun

* Install deps

* Add legacy Node.js server interface test

* More tests

* Test "assets" fixture

* Test "helpers" fixture

* fix

* Support AWS native API

* Remove debugging `console.log()` calls

* Use plugin-node for new plugin instead

* Revert "Use plugin-node for new plugin instead"

This reverts commit f317b8c6ecdc67a74d5f2b12a2e7567a27d4b6b8.

* Move to `plugin-node` directory

* Update plugin-node version in package.json

* Checkout node from main

* Add yarn.lock files for tests

* Update node-bridge

Co-authored-by: Andy <AndyBitz@users.noreply.github.com>
Co-authored-by: Andy Bitz <artzbitz@gmail.com>
2021-11-08 14:59:01 +01:00
Steven
a6ccf6c180 Publish Canary
- @vercel/build-utils@2.12.3-canary.15
 - vercel@23.1.3-canary.22
 - @vercel/client@10.2.3-canary.16
 - @vercel/node-bridge@2.1.1-canary.2
 - @vercel/node@1.12.2-canary.5
2021-11-05 18:40:08 -04:00
Steven
8d848ebe8b [node] Fix launcher ESM on Windows dev (#6953) 2021-11-05 18:38:55 -04:00
Steven
6ef2c16d63 [build-utils] Add convertRuntimeToPlugin() (#6942) 2021-11-05 16:12:21 -04:00
Andy Bitz
6c71ceaaeb Publish Canary
- vercel@23.1.3-canary.21
2021-11-05 10:26:15 +01:00
Andy
1dcb6dfc6f [cli] Rename certain outputs in vercel build (#6948) 2021-11-05 10:24:49 +01:00
Steven
4fd24575e5 Publish Canary
- vercel@23.1.3-canary.20
 - vercel-plugin-middleware@0.0.0-canary.5
2021-11-03 09:06:27 -04:00
Gary Borton
8714f1905e [cli] Render an error page when middleware explodes. (#6934)
### Related Issues

This adds error handling for middleware in `vc dev`

Local looks a little different than production:
Local
![image](https://user-images.githubusercontent.com/4172067/139951848-efa08a88-aeee-446f-8319-35c8bb0b1d75.png)

Production
![image](https://user-images.githubusercontent.com/4172067/139951580-33a4ad0f-18a5-4aa1-bfb0-5e1da646a4b8.png)


### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [ ] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-11-02 23:57:46 +00:00
Jared Palmer
2e69f2513d [cli] Make sure vc pull properly sets currentTeam (#6936)
### Related Issues

> Fixes https://github.com/vercel/runtimes/issues/219

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-11-02 23:07:28 +00:00
Gary Borton
979e4b674a [cli] Bundle middleware deps (#6932)
* Use ncc to bundle middleware plugin, move dependencies to devDependencies, remove querystring

* Switch from globby (deprecated dependencies) to glob in middleware plugin.

* Bundle the node-plugin and middleware-plugin into cli.
2021-11-02 17:08:02 -04:00
Nathan Rajlich
07fa47bcfb Publish Canary
- vercel@23.1.3-canary.19
 - vercel-plugin-middleware@0.0.0-canary.4
2021-10-29 18:17:08 -07:00
Nathan Rajlich
307c4fc377 [cli] Bump vercel-plugin-node to latest 2021-10-29 18:16:16 -07:00
Nathan Rajlich
44868d79b6 Add initial vercel-plugin-middleware (#6892)
* Add initial `vercel-plugin-middleware`

* Ignore `entries.js` from ESLint

* Add `runDevMiddleware()` stub

* Add test

* Add support for "_middleware.{js,ts}" to `vercel dev` (#6880)

* Add websandbox from next.js codebase.

* Use node-fetch instead of next's polyfilled fetch.

* Handle middleware rewrites.

* Add response, headers, and request to websandbox context.

* Move websandbox dependency to middleware plugin.

* Add integration tests, update websandbox to support ts files and json imports.

* commit yarn.lock changes after rebasing

* Clean up left over console.logs, fix some tsc issues, and rebase issue.

* Fix failing test and eslint.

* Fix middleware test on windows.

* [examples] Update Vercel Next.js example template to 12.0.1 (#6905)

* Mark the Plugins as external to CLI's ncc build

* [cli] Improve tracing in vc build (#6898)

* [cli] Fix tracing for `vc build`

* Ignore object when there are no changes

* Make Next < 12 work with FS API w/ nft

* Update packages/cli/src/commands/build.ts

Co-authored-by: Nathan Rajlich <n@n8.io>

* Document how Next.js processing works in build

* [cli] Fix static assets (#6906)

* Make sure output path is .next

* Fix up require-server-files for processing

* Fix typo

* Move static

* Update static rename

Co-authored-by: Andy Bitz <artzbitz@gmail.com>
Co-authored-by: Nathan Rajlich <n@n8.io>
Co-authored-by: Andy <AndyBitz@users.noreply.github.com>

* Publish Canary

 - vercel@23.1.3-canary.17
 - @vercel/client@10.2.3-canary.15
 - @vercel/static-config@0.0.1-canary.0

* [cli] Ignore `.env` and `.gitignore` in "vc build" (#6910)

* Publish Canary

 - vercel@23.1.3-canary.18

* Pass workPath to plugins.

The new plugin architecture doesn't pass a full BuildOptions object, previous
to this commit it wasn't passing any options at all. I've added workingPath to
support running dev/build from directories other than the project root.

* Remove error state when package.json exists, but no build script

This allows vercel build to continue working for projects that are not using
frameworks, but use package.json to manage dependencies.

* Fix types, pull in middleware header fix from next.js

Next js PR w/ the header fix:
https://github.com/vercel/next.js/pull/30560

* Fix missing entries file for vc build.

* Update call signature of middleware when using vc build.

Co-authored-by: Drew Bredvick <dbredvick@gmail.com>
Co-authored-by: Nathan Rajlich <n@n8.io>
Co-authored-by: Jared Palmer <jared@jaredpalmer.com>
Co-authored-by: Andy Bitz <artzbitz@gmail.com>
Co-authored-by: Andy <AndyBitz@users.noreply.github.com>

Co-authored-by: Gary Borton <gdborton@gmail.com>
Co-authored-by: Drew Bredvick <dbredvick@gmail.com>
Co-authored-by: Jared Palmer <jared@jaredpalmer.com>
Co-authored-by: Andy Bitz <artzbitz@gmail.com>
Co-authored-by: Andy <AndyBitz@users.noreply.github.com>
2021-10-29 17:15:20 -07:00
Nathan Rajlich
df9a4afa5c Publish Canary
- vercel@23.1.3-canary.18
2021-10-29 12:22:35 -07:00
Nathan Rajlich
8a6869bae2 [cli] Ignore .env and .gitignore in "vc build" (#6910) 2021-10-29 12:21:46 -07:00
Andy Bitz
a3fc3c1ca7 Publish Canary
- vercel@23.1.3-canary.17
 - @vercel/client@10.2.3-canary.15
 - @vercel/static-config@0.0.1-canary.0
2021-10-29 20:49:54 +02:00
Jared Palmer
44037c58be [cli] Improve tracing in vc build (#6898)
* [cli] Fix tracing for `vc build`

* Ignore object when there are no changes

* Make Next < 12 work with FS API w/ nft

* Update packages/cli/src/commands/build.ts

Co-authored-by: Nathan Rajlich <n@n8.io>

* Document how Next.js processing works in build

* [cli] Fix static assets (#6906)

* Make sure output path is .next

* Fix up require-server-files for processing

* Fix typo

* Move static

* Update static rename

Co-authored-by: Andy Bitz <artzbitz@gmail.com>
Co-authored-by: Nathan Rajlich <n@n8.io>
Co-authored-by: Andy <AndyBitz@users.noreply.github.com>
2021-10-29 20:49:21 +02:00
Drew Bredvick
1a9419b690 [examples] Update Vercel Next.js example template to 12.0.1 (#6905) 2021-10-29 13:03:31 -04:00
Nathan Rajlich
93d0e5966c [cli] Fix integration tests that check .gitignore (#6904) 2021-10-28 12:37:39 -07:00
Nathan Rajlich
306f3a1312 Add to "static-config" to run.js script 2021-10-27 17:36:32 -07:00
Nathan Rajlich
9c67e8115e Add @vercel/static-config (#6897) 2021-10-27 17:03:12 -07:00
Andy
b890ac1e44 [cli] Fix tracing for vc build (#6896)
* [cli] Fix tracing for `vc build`

* Ignore object when there are no changes
2021-10-28 00:20:44 +02:00
Andy
28e71ff109 [cli][client] Add step for checks (#6889)
* [cli][client] Add step for checks

* Update output

* Remove skipped message

* Correctly use `finishedEvents`

* Update packages/cli/src/commands/deploy/index.ts

Co-authored-by: Chris <7249920+chriswdmr@users.noreply.github.com>

* Add back deleted files

Co-authored-by: Chris <7249920+chriswdmr@users.noreply.github.com>
2021-10-27 20:22:35 +02:00
Andy Bitz
2bf060c708 Publish Canary
- @vercel/build-utils@2.12.3-canary.14
 - vercel@23.1.3-canary.16
 - @vercel/client@10.2.3-canary.14
 - @vercel/frameworks@0.5.1-canary.10
2021-10-26 14:10:32 +02:00
Jared Palmer
c8ef1d71d1 [cli] Add vercel build (#6861)
* Add PoC pull command

* Improve pull's linking logic

* Remove `__VERCEL_SKIP_PULL_CMD` env var and unneeded type narrowing

* Improve pull's link logic

* Fix team mock

* Add smoke test for vc pull

* Add setupFixture helper

* Remove debug duplicate

* Use a fixture in pull test

* Put back debug

* Fix unit test

* Fix test on windows

* Remove mock-stdin

* Pass cwd to link and pull

* Add help command for `vc pull`

* Organize imports

* Update packages/cli/src/commands/deploy/args.ts

Co-authored-by: Steven <steven@ceriously.com>

* Use tmp-promise instead of tmp

* Update packages/cli/src/commands/pull.ts

Co-authored-by: Steven <steven@ceriously.com>

* Update packages/cli/src/commands/pull.ts

Co-authored-by: Steven <steven@ceriously.com>

* Clean up pull comments and variable declarations

* Remove graceful tmp directory cleanup

* Put back graceful cleanup

* Print output for debugging

* Moar debug

* Set 10s timeout for `vc pull` test

* Change fixture to now-pull-next

* Fix pull test name

* Switch project mock to use encrypted env

* Add --env flag

* Update fixtures

* Remove now- from everywhere

* Remove instrumentation

* Rename setupFixture to setup-fixture

* Add deprecation warning to `vc env pull`

* Update packages/cli/src/commands/deploy/args.ts

Co-authored-by: Nathan Rajlich <nathan@tootallnate.net>

* Update packages/cli/src/commands/env/pull.ts

Co-authored-by: Nathan Rajlich <nathan@tootallnate.net>

* Fix pull and update imports

* Revamped build command

* printConfig -> renderConfig

* Remove frameworks

* Add build state unit test for gatsby

* Update packages/cli/src/commands/pull.ts

Co-authored-by: Steven <steven@ceriously.com>

* Update packages/cli/src/commands/env/index.ts

Co-authored-by: Steven <steven@ceriously.com>

* Update packages/cli/src/util/projects/write-project-settings.ts

Co-authored-by: Nathan Rajlich <nathan@tootallnate.net>

* Update packages/cli/src/commands/pull.ts

Co-authored-by: Nathan Rajlich <nathan@tootallnate.net>

* Don't writeProjectSettings in env pull

* Cleanup fixtures once afterAll

* Add help text for --env and -y

* Add output for pull

* Write project settings output after env output

* Pushing for Nate

* Add todo about handling Other's build output directory

* Add support for plugins

* Improve prompt logic loop

* Pluralize plugin output

* Better plugin failure handling

* Refactor away from BuildState class

* Remove unused file

* Correct framework detection logic, smart copy w/hardlinks

* Generate build manifest

* Generate routes-manifest.json

* Remove ambiguity when calling vc build

* Make sure manifests have all keys

* Ensure that .output is added to .gitignore in vc link

* Remove directoryListing from project settings

* Add support for default cli plugins

* Remove directory listing

* Install vercel-plugin-node

* Patch console.log and console.error for plugins

* Improve build output

* Remove unused unit tests

* Allow build without token

* Add vercel plugin middleware

* Bump vercel-plugin-middleware

* Bump middleware plugin

* Tweak require.resolve

* Tweak require.resolve to __dirname

* Update `vercel-plugin-node`

* Fix prefixed logs when using formatters i.e. `%j`

* Pretty print the manifest files

* Get unique CLI deps

For the case where the local project has one of the CLI default plugins
specified.

* Update packages/cli/package.json

Co-authored-by: Nathan Rajlich <nathan@tootallnate.net>

* Add help output

* Remove p-limit properly

* Confirm before pull in build

* Bump `vercel-plugin-node`

* [cli] Make Next.js move files into .output (#6885)

* Use OUTPUT_DIR

* Return properly if no package.json exists and no build command

* Invert logic for runPackageJsonScript

* Bump `vercel-plugin-middleware`

* Fix defaultHeaders in frameworks

* Fix build when nft files is object

* Update `yarn.lock`

* 2nd attempt at --prebuilt (#6888)

Co-authored-by: Andy Bitz <artzbitz@gmail.com>

* Add beta and feedback to vc build

Co-authored-by: Nathan Rajlich <n@n8.io>
Co-authored-by: Steven <steven@ceriously.com>
Co-authored-by: Nathan Rajlich <nathan@tootallnate.net>
Co-authored-by: Andy Bitz <artzbitz@gmail.com>
2021-10-26 14:04:52 +02:00
Nathan Rajlich
3d2efc7dcd [frameworks] Fix small typo in "Other" preset description (#6882) 2021-10-23 14:56:22 +00:00
jj@jjsweb.site
cd7185a872 Publish Canary
- @vercel/build-utils@2.12.3-canary.13
 - vercel@23.1.3-canary.15
 - @vercel/client@10.2.3-canary.13
 - @vercel/frameworks@0.5.1-canary.9
 - @vercel/routing-utils@1.11.4-canary.5
2021-10-21 17:58:50 -05:00
Kiko Beats
981a76fbe2 [routing-utils] Add missing fields (#6872)
* chore: add missing fields

* Update types.ts

* Update types.ts

* chore add missing as part of the schema

* test: add missing case
2021-10-21 17:57:48 -05:00
Nathan Rajlich
c35c05446b [cli] Add CLI login unit test (#6866)
This has just been sitting in my working tree for a while, might as well push it up.
2021-10-19 20:38:29 +00:00
Jared Palmer
b88e65c4ad [cli] Add vercel pull command (#6822)
Add `vercel pull` command. Closes https://github.com/vercel/runtimes/issues/142. 

![CleanShot 2021-10-19 at 08 50 07](https://user-images.githubusercontent.com/4060187/137946853-860204ba-afaa-42da-be8a-d35bec97c808.png)

It does the following:
- Pull the `.env` file (it calls `pull` internally)
- Adds the following to `.vercel/project.json` (which will then be used by `vercel build`):
   ```tsx
   interface ProjectLink {
        projectId: string
        orgId: string
        settings: {
          buildCommand: string | null,
          devCommand:  string | null,
          directoryListing:  string | null,
          outputDirectory:  string | null,
          rootDirectory:  string | null,
          framework: string | null,
        }
    }
   ```
This PR also deprecates `vc env pull` with a warning:

![CleanShot 2021-10-19 at 08 50 21](https://user-images.githubusercontent.com/4060187/137946847-e102bd99-943a-4f07-b457-fe886007c044.png)

### 📋 Checklist

- [x] Help output
- [x] Flags (need to combine flags from `env pull`)

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [x] This PR has a concise title and thorough description useful to a reviewer
- [x] Issue from task tracker has a link to this PR
2021-10-19 19:10:31 +00:00
Javi Velasco
9e16ce750b Publish Canary
- @vercel/build-utils@2.12.3-canary.12
 - vercel@23.1.3-canary.14
 - @vercel/client@10.2.3-canary.12
 - @vercel/frameworks@0.5.1-canary.8
 - @vercel/routing-utils@1.11.4-canary.4
2021-10-19 14:52:11 +02:00
Javi Velasco
2105d31730 Update middleware route (#6863) 2021-10-19 14:50:41 +02:00
jj@jjsweb.site
3d7e01ebf0 Publish Canary
- @vercel/build-utils@2.12.3-canary.11
 - vercel@23.1.3-canary.13
 - @vercel/client@10.2.3-canary.11
 - @vercel/frameworks@0.5.1-canary.7
 - @vercel/routing-utils@1.11.4-canary.3
2021-10-18 16:50:01 -05:00
JJ Kasper
dccacc4ca0 [routing-utils] Update routes schema for new property (#6860)
Adds an additional property for the `routes` schema. 

### Related Issues

N/A

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-10-18 21:45:42 +00:00
Devon Govett
be5c0da521 [example][frameworks] Add support for Parcel framework (#6836) 2021-10-14 14:53:57 -07:00
Katie Byers
f985d953ed [cli] Fix swapped error messages in executeBuild() (#6724) 2021-10-14 14:31:02 -07:00
Nathan Rajlich
b8f8289afe [cli] Use getters for Now props that mirror Client (#6838)
This will prevent any issues where the `Now` instance is out-of-sync with the `Client` instance, for example, during a re-auth where a new auth token is issued. Also reduces a bit of code which is nice.
2021-10-13 22:40:06 +00:00
Nathan Rajlich
e01a1cebfd [cli] Don't pass teamId query param to /verify token endpoint (#6841)
Fixes an issue where the token would not be properly upgraded while
a Team scope was currently active, causing a new auth token to be issued
and lose the previous access scope(s).
2021-10-13 14:39:24 -07:00
Matt Netkow
2515d522a3 [frameworks] Make "vercel dev" work with Ionic Angular projects (#6658) 2021-10-13 11:32:26 -07:00
Nathan Rajlich
32e935d632 [cli] Use GET /v2/user endpoint (#6828)
The `/www/user` endpoint is deprecated.
2021-10-13 17:20:54 +00:00
Miroslav Simulcik
e6818dd3f9 Publish Canary
- @vercel/build-utils@2.12.3-canary.10
 - vercel@23.1.3-canary.12
 - @vercel/client@10.2.3-canary.10
2021-10-13 16:52:12 +02:00
Miroslav Simulcik
e510415a66 Add regions to lambda options (#6829) 2021-10-13 16:47:18 +02:00
Nathan Rajlich
1be75712e0 [cli] Add outputBuffer getter and mutable isTTY for tests (#6827)
These changes originally from #6652, but pulled out to be merged
separately.

`outputBuffer` is a simpler way of asserting tests against the CLI
output instead of working directly withe Jest mock function.

`output.isTTY` is also now mutable, so that we can write tests for both
cases when the output is different based on TTY-ness (for example,
see the updated `vc whoami` tests in this PR).
2021-10-12 16:16:55 -07:00
Andy Bitz
f682aefc9d Publish Canary
- @vercel/build-utils@2.12.3-canary.9
 - vercel@23.1.3-canary.11
 - @vercel/client@10.2.3-canary.9
 - @vercel/frameworks@0.5.1-canary.6
2021-10-12 12:56:49 +02:00
Andy
cd485c1866 [frameworks] Add Nuxt 3 to framework detection (#6823) 2021-10-12 12:43:40 +02:00
Steven
f7de7227b4 Publish Canary
- @vercel/build-utils@2.12.3-canary.8
 - vercel@23.1.3-canary.10
 - @vercel/client@10.2.3-canary.8
2021-09-23 14:28:52 -04:00
Steven
abea217177 [build-utils] Add allowQuery to Prerender (#6766) 2021-09-23 14:25:44 -04:00
Steven
4e52f8532b Publish Canary
- @vercel/build-utils@2.12.3-canary.7
 - vercel@23.1.3-canary.9
 - @vercel/client@10.2.3-canary.7
 - @vercel/go@1.2.4-canary.3
 - @vercel/node@1.12.2-canary.4
 - @vercel/python@2.0.6-canary.4
 - @vercel/ruby@1.2.8-canary.3
2021-09-21 22:20:00 -04:00
Steven
702cb9e29c [all] Revert to @vercel/ncc@0.24.0 (#6749) 2021-09-21 22:17:06 -04:00
jj@jjsweb.site
d3d5555d79 Publish Canary
- @vercel/build-utils@2.12.3-canary.6
 - vercel@23.1.3-canary.8
 - @vercel/client@10.2.3-canary.6
 - @vercel/frameworks@0.5.1-canary.5
 - @vercel/routing-utils@1.11.4-canary.2
2021-09-20 19:35:05 -05:00
JJ Kasper
2fd3fc73e5 [routing-utils] Allow passing internal params to convertRewrites (#6742)
This adds an argument to allow passing internal param names that should be ignored when considering whether params should be auto-added to a rewrite's destination query. After adding this we should be able to resolve https://github.com/vercel/next.js/issues/27563 in the runtime where `convertRewrites` is called. 

This matches Next.js' handling for internal params which can be seen [here](e90825ad88/packages/next/shared/lib/router/utils/prepare-destination.ts (L203))

### Related Issues

x-ref: https://github.com/vercel/next.js/issues/27563

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-09-21 00:15:29 +00:00
Steven
de0b13a46e Publish Canary
- vercel@23.1.3-canary.7
 - @vercel/node@1.12.2-canary.3
2021-09-16 12:54:47 -04:00
Steven
d0fe85db92 [node] Bump nft to 0.14.0 (#6727) 2021-09-16 12:49:04 -04:00
jj@jjsweb.site
bfbd927320 Publish Canary
- @vercel/build-utils@2.12.3-canary.5
 - vercel@23.1.3-canary.6
 - @vercel/client@10.2.3-canary.5
 - @vercel/frameworks@0.5.1-canary.4
 - @vercel/routing-utils@1.11.4-canary.1
2021-09-14 15:02:32 -05:00
JJ Kasper
90bacf88b8 [routing-utils] Fix host segment replacing (#6713)
* Fix host segment replacing

* Add additional check
2021-09-14 13:20:35 -05:00
Steven
07c369c542 Publish Canary
- @vercel/build-utils@2.12.3-canary.4
 - vercel@23.1.3-canary.5
 - @vercel/client@10.2.3-canary.4
 - @vercel/go@1.2.4-canary.2
 - @vercel/node@1.12.2-canary.2
 - @vercel/python@2.0.6-canary.3
 - @vercel/ruby@1.2.8-canary.2
2021-09-13 16:32:45 -04:00
Steven
a2e4186ccb [all] Bump ncc to 0.31.1 (#6700)
https://github.com/vercel/ncc/releases/tag/0.31.0

https://github.com/vercel/ncc/releases/tag/0.31.1
2021-09-13 20:20:48 +00:00
Steven
6e1d708e3f Publish Canary
- vercel@23.1.3-canary.4
 - @vercel/python@2.0.6-canary.2
2021-09-08 13:56:20 -04:00
Noa
38503103c3 [python] Use pip --upgrade when installing function dependencies (#6683)
Co-authored-by: Steven <steven@ceriously.com>
2021-09-08 13:54:03 -04:00
jj@jjsweb.site
e8fec4b69c Publish Canary
- @vercel/build-utils@2.12.3-canary.3
 - vercel@23.1.3-canary.3
 - @vercel/client@10.2.3-canary.3
 - @vercel/frameworks@0.5.1-canary.3
 - @vercel/routing-utils@1.11.4-canary.0
2021-09-07 11:52:01 -05:00
JJ Kasper
b3ffcdf80d [routing-utils] Ensure headers with only has items are replaced correctly (#6686)
This ensures we replace header values correctly when no named segments are used and only has items are used. 

### Related Issues

Fixes: https://vercel.slack.com/archives/CHTTGQYQ4/p1631023974185700

### 📋 Checklist

<!--
  Please keep your PR as a Draft until the checklist is complete
-->

#### Tests

- [x] The code changed/added as part of this PR has been covered with tests
- [x] All tests pass locally with `yarn test-unit`

#### Code Review

- [ ] This PR has a concise title and thorough description useful to a reviewer
- [ ] Issue from task tracker has a link to this PR
2021-09-07 16:17:01 +00:00
Leo Lamprecht
43c1a93c1d Enabled blank issues temporarily 2021-09-06 18:24:53 +02:00
Leo Lamprecht
5b118fd4e6 Disable blank issues again 2021-09-06 14:47:15 +02:00
Leo Lamprecht
8916b674af Temporarily enable blank issues 2021-09-06 14:41:32 +02:00
Brody McKee
1807f83c69 Update NPM publish token (#6672) 2021-09-03 19:44:59 +03:00
Steven
74e8ec7c64 Fix lerna publish for automation token (#6666)
Related to https://github.com/lerna/lerna/issues/2788
2021-09-03 00:20:20 +00:00
Steven
2644e3127b Publish Canary
- @vercel/build-utils@2.12.3-canary.2
 - vercel@23.1.3-canary.2
 - @vercel/client@10.2.3-canary.2
2021-09-02 08:42:33 -04:00
Leo Lamprecht
d77ac04b0c Disable blank issues again 2021-09-02 13:52:18 +02:00
Leo Lamprecht
0ef9c8df4d Temporarily enable issues 2021-09-02 13:45:20 +02:00
Steven
dfc4c98820 [build-utils] Fix custom 404 route (#6657)
The Custom 404 feature was originally implemented in #4563 but was matching too broadly (see [gist](https://gist.github.com/kjk/4dc57da62d7e715c687cc7914847ffb2))

This PR fixes the custom 404 route and updates the tests.
2021-09-02 00:12:45 +00:00
430 changed files with 21900 additions and 1670 deletions

View File

@@ -1,11 +1,10 @@
node_modules
dist
examples
packages/build-utils/test/fixtures
packages/*/test/fixtures
packages/cli/@types
packages/cli/download
packages/cli/dist
packages/cli/test/fixtures
packages/cli/test/dev/fixtures
packages/cli/bin
packages/cli/link
@@ -13,6 +12,6 @@ packages/cli/src/util/dev/templates/*.ts
packages/client/tests/fixtures
packages/client/lib
packages/node/src/bridge.ts
packages/node/test/fixtures
packages/node-bridge/bridge.js
packages/node-bridge/launcher.js
packages/middleware/src/entries.js

View File

@@ -1,4 +1,4 @@
blank_issues_enabled: false
blank_issues_enabled: true
contact_links:
- name: Bug Report
url: https://vercel.com/support/request

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 2
steps:
- uses: styfle/cancel-workflow-action@0.4.1
- uses: styfle/cancel-workflow-action@0.9.1
with:
workflow_id: 849295, 849296, 849297, 849298
access_token: ${{ github.token }}

View File

@@ -29,6 +29,6 @@ jobs:
- name: Publish
run: yarn publish-from-github
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN_ELEVATED }}
GA_TRACKING_ID: ${{ secrets.GA_TRACKING_ID }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}

View File

@@ -11,7 +11,7 @@ on:
jobs:
test:
name: Dev
timeout-minutes: 60
timeout-minutes: 75
strategy:
fail-fast: false
matrix:

1
.gitignore vendored
View File

@@ -27,3 +27,4 @@ test/lib/deployment/failed-page.txt
/public
__pycache__
.vercel
.output

View File

@@ -332,7 +332,7 @@ This is an abstract enumeration type that is implemented by one of the following
- `nodejs10.x`
- `go1.x`
- `java11`
- `python3.8`
- `python3.9`
- `python3.6`
- `dotnetcore2.1`
- `ruby2.5`
@@ -398,12 +398,12 @@ This utility allows you to _scan_ the filesystem and return a [`Files`](#files)
The following trivial example downloads everything to the filesystem, only to return it back (therefore just re-creating the passed-in [`Files`](#files)):
```js
const { glob, download } = require('@vercel/build-utils')
const { glob, download } = require('@vercel/build-utils');
exports.build = ({ files, workPath }) => {
await download(files, workPath)
return glob('**', workPath)
}
await download(files, workPath);
return glob('**', workPath);
};
```
### `getWritableDirectory()`

View File

@@ -14,8 +14,6 @@ const frameworks = (_frameworks as Framework[])
sort: undefined,
dependency: undefined,
defaultRoutes: undefined,
devCommand: undefined,
buildCommand: undefined,
};
if (framework.logo) {

View File

@@ -9,7 +9,7 @@
"lint": "next lint"
},
"dependencies": {
"next": "11.1.2",
"next": "12.0.1",
"react": "17.0.2",
"react-dom": "17.0.2"
},

View File

@@ -43,7 +43,14 @@
core-js-pure "^3.16.0"
regenerator-runtime "^0.13.4"
"@babel/runtime@7.15.3", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2":
"@babel/runtime@7.15.4":
version "7.15.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2":
version "7.15.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz#2e1c2880ca118e5b2f9988322bd8a7656a32502b"
integrity sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==
@@ -112,10 +119,10 @@
resolved "https://registry.yarnpkg.com/@napi-rs/triples/-/triples-1.0.3.tgz#76d6d0c3f4d16013c61e45dfca5ff1e6c31ae53c"
integrity sha512-jDJTpta+P4p1NZTFVLHJ/TLFVYVcOqv6l8xwOeBKNPMgY/zDYH/YH7SJbvrr/h1RcS9GzbPcLKGzpuK9cV56UA==
"@next/env@11.1.2":
version "11.1.2"
resolved "https://registry.yarnpkg.com/@next/env/-/env-11.1.2.tgz#27996efbbc54c5f949f5e8c0a156e3aa48369b99"
integrity sha512-+fteyVdQ7C/OoulfcF6vd1Yk0FEli4453gr8kSFbU8sKseNSizYq6df5MKz/AjwLptsxrUeIkgBdAzbziyJ3mA==
"@next/env@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/env/-/env-12.0.1.tgz#d57141ef1fe844f6f7c18cdaf29a712788c18ca4"
integrity sha512-+eJ8mQbAcV/ZILRAgIx9xwDg6hrqm6m/7QLfEvsf2BPnsh+fwU4Xf1zgcbyqD2V4ja4OTWG6ow+Hiukgap3mZQ==
"@next/eslint-plugin-next@11.1.0":
version "11.1.0"
@@ -124,15 +131,15 @@
dependencies:
glob "7.1.7"
"@next/polyfill-module@11.1.2":
version "11.1.2"
resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-11.1.2.tgz#1fe92c364fdc81add775a16c678f5057c6aace98"
integrity sha512-xZmixqADM3xxtqBV0TpAwSFzWJP0MOQzRfzItHXf1LdQHWb0yofHHC+7eOrPFic8+ZGz5y7BdPkkgR1S25OymA==
"@next/polyfill-module@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-12.0.1.tgz#d20abf06f686ee7a8bd0d9056accfd0662f19e87"
integrity sha512-fTrndwGuvrQO+4myVGcPtsYI4/tmZBhHHJId7MSHWz+9gW4NFgsmDlr8OI9Th2ZXpqk5WHLsTYQ+dLiQp1zV4g==
"@next/react-dev-overlay@11.1.2":
version "11.1.2"
resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-11.1.2.tgz#73795dc5454b7af168bac93df7099965ebb603be"
integrity sha512-rDF/mGY2NC69mMg2vDqzVpCOlWqnwPUXB2zkARhvknUHyS6QJphPYv9ozoPJuoT/QBs49JJd9KWaAzVBvq920A==
"@next/react-dev-overlay@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-12.0.1.tgz#134299ae44fad5a59448d5e671518074f37cba95"
integrity sha512-dLv1to40bvadbr0VO8pBsbr9ddgktCLilfejOpEFQkOOrdQBUuIfegqqEDiCL9THkAO3QGYY4t/ZPfv9wrxLZQ==
dependencies:
"@babel/code-frame" "7.12.11"
anser "1.4.9"
@@ -144,32 +151,67 @@
shell-quote "1.7.2"
source-map "0.8.0-beta.0"
stacktrace-parser "0.1.10"
strip-ansi "6.0.0"
strip-ansi "6.0.1"
"@next/react-refresh-utils@11.1.2":
version "11.1.2"
resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-11.1.2.tgz#44ea40d8e773e4b77bad85e24f6ac041d5e4b4a5"
integrity sha512-hsoJmPfhVqjZ8w4IFzoo8SyECVnN+8WMnImTbTKrRUHOVJcYMmKLL7xf7T0ft00tWwAl/3f3Q3poWIN2Ueql/Q==
"@next/react-refresh-utils@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-12.0.1.tgz#219be7a81696a7bd1e2d4ee397ca100eb8262f23"
integrity sha512-CjTBR9a6ai+2fUT8KFya9AiTaCnfDY34H6pDmtdJdkD+vY08AwtPpv10kzsgNEhsL06210yVzH59IsEQLBIllA==
"@next/swc-darwin-arm64@11.1.2":
version "11.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-11.1.2.tgz#93226c38db488c4b62b30a53b530e87c969b8251"
integrity sha512-hZuwOlGOwBZADA8EyDYyjx3+4JGIGjSHDHWrmpI7g5rFmQNltjlbaefAbiU5Kk7j3BUSDwt30quJRFv3nyJQ0w==
"@next/swc-android-arm64@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.0.1.tgz#c776853e0911c12fcc69a69cd7ab111dff29f8d2"
integrity sha512-zI/6zsZuO2igknzHzfaQep0PeD3d4/qdjXUcQLwLHJQtGdhPvZFMke1z3BBWZqePHVsR1JPjE4QTii7udF5qsQ==
"@next/swc-darwin-x64@11.1.2":
version "11.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-11.1.2.tgz#792003989f560c00677b5daeff360b35b510db83"
integrity sha512-PGOp0E1GisU+EJJlsmJVGE+aPYD0Uh7zqgsrpD3F/Y3766Ptfbe1lEPPWnRDl+OzSSrSrX1lkyM/Jlmh5OwNvA==
"@next/swc-darwin-arm64@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.0.1.tgz#bee9c5932511c993ab384ef9aedb86c02532d41e"
integrity sha512-vRfHz7rEt9+TTfwi3uY9ObUSLhzMmgVZ96b+yOSmZ6Kxs/V46IXHOLawCnoldXylpskZ/+HTWcrB1D3aimGeZA==
"@next/swc-linux-x64-gnu@11.1.2":
version "11.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-11.1.2.tgz#8216b2ae1f21f0112958735c39dd861088108f37"
integrity sha512-YcDHTJjn/8RqvyJVB6pvEKXihDcdrOwga3GfMv/QtVeLphTouY4BIcEUfrG5+26Nf37MP1ywN3RRl1TxpurAsQ==
"@next/swc-darwin-x64@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.0.1.tgz#a0bdcbcf11b8b62190ec8e0406cecbbcc810b7fc"
integrity sha512-mM7QLIqRUqR8I74gbZ4Uq+dY8k3Whrs98wK+vPurmDTBhXhaVnAYblEkEwe0DJGqlmjD4w6faYfCydmFI69jqw==
"@next/swc-win32-x64-msvc@11.1.2":
version "11.1.2"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-11.1.2.tgz#e15824405df137129918205e43cb5e9339589745"
integrity sha512-e/pIKVdB+tGQYa1cW3sAeHm8gzEri/HYLZHT4WZojrUxgWXqx8pk7S7Xs47uBcFTqBDRvK3EcQpPLf3XdVsDdg==
"@next/swc-linux-arm-gnueabihf@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.0.1.tgz#d0132637288f452ad5c6a6161e42aebcd4355f82"
integrity sha512-QF5LVyAWTah5i1p/yG4a8nTGRXerHoDkS3kWYCdjcwlALOiAJ9m0GUTks/O47izNokBAbZnL7URUdvtGFjP0Ng==
"@next/swc-linux-arm64-gnu@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.0.1.tgz#6b310344b9bac7700eaff8f4c536540b1226e378"
integrity sha512-ETFUh373WsjUJJr32GHSDlVSgwFwS+EJUJuSH40Pr4xB6250YxuRk8ccF6QR5LHqTL4tbbVEEfCD8sZVnccP8w==
"@next/swc-linux-arm64-musl@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.0.1.tgz#8ab1fc81d18bbb70bb15bcc4250382257bba6298"
integrity sha512-pfnXNjKywXyp2DJsjFhkfOlvcNu9xa8HgEhCUKXm1OZ4pGnpeb1+UD4t5Pn9b9ggiWPzauZK1abR/9nShvbSzw==
"@next/swc-linux-x64-gnu@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.0.1.tgz#a664268aedec402da5df34efac1b337d9b0e492e"
integrity sha512-d9cXS27Ar7TTtA3BJ8gxosDDdVNSFy4MQiwsszKlEiqfGrnINeXKdVgeiOa+xxq+JxNvPzonp4sbX6k8InIocg==
"@next/swc-linux-x64-musl@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.0.1.tgz#4b7e5fee5a62adb6d9c9aad1a4aa00a6a09b53dc"
integrity sha512-4SAmi7riavU6TFGX7wQFioFi/vx8uJ2/Cx7ZfrYiZzzKmmuu2eM8onW1kcKu+aQD777x/kvzW4+2pWkM2gyPOA==
"@next/swc-win32-arm64-msvc@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.0.1.tgz#9ff0c2a2f00f41d40bd44d6da195bdf649d807c6"
integrity sha512-JRad3QyXvs5zDkeEmc6z5tEvm/ZZnjnsBY921zWw7OIcIZR5wAs+1AnRVjIxHTEHSExxOvBgPyEMpgVkB8OyxQ==
"@next/swc-win32-ia32-msvc@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.0.1.tgz#5a927ec832b184ce2e35f8ec668daa34175e47d0"
integrity sha512-ierQmzVWPi6a7PqrdgfI6nrQ/SWJ9W5jllByyQeFIOKhOzZiz030Tw+U6V7NqE3gGNeRwpj56Iya8nUb3hlM1g==
"@next/swc-win32-x64-msvc@12.0.1":
version "12.0.1"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.0.1.tgz#fe145cf7baf79564159a87a545e430f96c835578"
integrity sha512-li3CCXpdMX0+wJlQpy0xZmHCgHMebaBf5X2BIAJrv8cQXYc6dejeojttXLFNCF0dNAo3UzlbP6h7N+8p6Wbakw==
"@node-rs/helper@1.2.1":
version "1.2.1"
@@ -258,6 +300,16 @@ acorn-jsx@^5.3.1:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn@8.5.0:
version "8.5.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2"
integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==
acorn@^6.2.1:
version "6.4.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
acorn@^7.4.0:
version "7.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
@@ -298,6 +350,11 @@ ansi-regex@^5.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
@@ -390,24 +447,11 @@ assert@2.0.0:
object-is "^1.0.1"
util "^0.12.0"
assert@^1.1.1:
version "1.5.0"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb"
integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==
dependencies:
object-assign "^4.1.1"
util "0.10.3"
ast-types-flow@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
ast-types@0.13.2:
version "0.13.2"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48"
integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA==
astral-regex@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
@@ -532,7 +576,7 @@ browserify-sign@^4.0.0:
readable-stream "^3.6.0"
safe-buffer "^5.2.0"
browserify-zlib@0.2.0, browserify-zlib@^0.2.0:
browserify-zlib@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==
@@ -563,15 +607,6 @@ buffer@5.6.0:
base64-js "^1.0.2"
ieee754 "^1.1.4"
buffer@^4.3.0:
version "4.9.2"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8"
integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==
dependencies:
base64-js "^1.0.2"
ieee754 "^1.1.4"
isarray "^1.0.0"
builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
@@ -692,12 +727,7 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
console-browserify@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==
constants-browserify@1.0.0, constants-browserify@^1.0.0:
constants-browserify@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
@@ -714,11 +744,6 @@ core-js-pure@^3.16.0:
resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.16.1.tgz#b997df2669c957a5b29f06e95813a171f993592e"
integrity sha512-TyofCdMzx0KMhi84mVRS8rL1XsRk2SPUNz2azmth53iRN0/08Uim9fdhQTaZTG1LqaXHYVci4RDHka6WrXfnvg==
core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
create-ecdh@^4.0.0:
version "4.0.4"
resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e"
@@ -759,7 +784,7 @@ cross-spawn@^7.0.2:
shebang-command "^2.0.0"
which "^2.0.1"
crypto-browserify@3.12.0, crypto-browserify@^3.11.0:
crypto-browserify@3.12.0:
version "3.12.0"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==
@@ -886,11 +911,6 @@ domain-browser@4.19.0:
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.19.0.tgz#1093e17c0a17dbd521182fe90d49ac1370054af1"
integrity sha512-fRA+BaAWOR/yr/t7T9E9GJztHPeFjj8U35ajyAjCDtAAnTn1Rc1f6W6VGPJrO1tkQv9zWu+JRof7z6oQtiYVFQ==
domain-browser@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
electron-to-chromium@^1.3.723:
version "1.3.802"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.802.tgz#0afa989321de3e904ac653ee79e0d642883731a1"
@@ -1219,7 +1239,7 @@ etag@1.8.1:
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
events@^3.0.0:
events@3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
@@ -1486,7 +1506,7 @@ http-errors@1.7.3:
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
https-browserify@1.0.0, https-browserify@^1.0.0:
https-browserify@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
@@ -1548,21 +1568,11 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4:
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
inherits@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=
inherits@2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
internal-slot@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
@@ -1706,11 +1716,6 @@ is-typed-array@^1.1.3, is-typed-array@^1.1.6:
foreach "^2.0.5"
has-tostringtag "^1.0.0"
isarray@^1.0.0, isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -1952,32 +1957,30 @@ nanoid@^3.1.23:
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81"
integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==
native-url@0.3.4:
version "0.3.4"
resolved "https://registry.yarnpkg.com/native-url/-/native-url-0.3.4.tgz#29c943172aed86c63cee62c8c04db7f5756661f8"
integrity sha512-6iM8R99ze45ivyH8vybJ7X0yekIcPf5GgLV5K0ENCbmRcaRIDoj37BC8iLEmaaBfqqb8enuZ5p0uhY+lVAbAcA==
dependencies:
querystring "^0.2.0"
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
next@11.1.2:
version "11.1.2"
resolved "https://registry.yarnpkg.com/next/-/next-11.1.2.tgz#527475787a9a362f1bc916962b0c0655cc05bc91"
integrity sha512-azEYL0L+wFjv8lstLru3bgvrzPvK0P7/bz6B/4EJ9sYkXeW8r5Bjh78D/Ol7VOg0EIPz0CXoe72hzAlSAXo9hw==
neo-async@^2.6.1:
version "2.6.2"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
next@12.0.1:
version "12.0.1"
resolved "https://registry.yarnpkg.com/next/-/next-12.0.1.tgz#7b82a73bc185bfda7372e7e8309f9b38e6be9cb0"
integrity sha512-4MNXAbD9+Tmtejg0TOKbaP52Cgu4mIn2ejKMLHWV0acxWGkkcE7QvdZwvg5pkg3fQBMrgucOxxtmw4D7yWaZvg==
dependencies:
"@babel/runtime" "7.15.3"
"@babel/runtime" "7.15.4"
"@hapi/accept" "5.0.2"
"@next/env" "11.1.2"
"@next/polyfill-module" "11.1.2"
"@next/react-dev-overlay" "11.1.2"
"@next/react-refresh-utils" "11.1.2"
"@next/env" "12.0.1"
"@next/polyfill-module" "12.0.1"
"@next/react-dev-overlay" "12.0.1"
"@next/react-refresh-utils" "12.0.1"
"@node-rs/helper" "1.2.1"
acorn "8.5.0"
assert "2.0.0"
ast-types "0.13.2"
browserify-zlib "0.2.0"
browserslist "4.16.6"
buffer "5.6.0"
@@ -1990,40 +1993,48 @@ next@11.1.2:
domain-browser "4.19.0"
encoding "0.1.13"
etag "1.8.1"
events "3.3.0"
find-cache-dir "3.3.1"
get-orientation "1.1.2"
https-browserify "1.0.0"
image-size "1.0.0"
jest-worker "27.0.0-next.5"
native-url "0.3.4"
node-fetch "2.6.1"
node-html-parser "1.4.9"
node-libs-browser "^2.2.1"
os-browserify "0.3.0"
p-limit "3.1.0"
path-browserify "1.0.1"
pnp-webpack-plugin "1.6.4"
postcss "8.2.15"
process "0.11.10"
querystring-es3 "0.2.1"
raw-body "2.4.1"
react-is "17.0.2"
react-refresh "0.8.3"
react-server-dom-webpack "0.0.0-experimental-3c4c1c470-20211021"
regenerator-runtime "0.13.4"
stream-browserify "3.0.0"
stream-http "3.1.1"
string_decoder "1.3.0"
styled-jsx "4.0.1"
styled-jsx "5.0.0-beta.3"
timers-browserify "2.0.12"
tty-browserify "0.0.1"
use-subscription "1.5.1"
util "0.12.4"
vm-browserify "1.1.2"
watchpack "2.1.1"
web-streams-polyfill "3.0.3"
optionalDependencies:
"@next/swc-darwin-arm64" "11.1.2"
"@next/swc-darwin-x64" "11.1.2"
"@next/swc-linux-x64-gnu" "11.1.2"
"@next/swc-win32-x64-msvc" "11.1.2"
"@next/swc-android-arm64" "12.0.1"
"@next/swc-darwin-arm64" "12.0.1"
"@next/swc-darwin-x64" "12.0.1"
"@next/swc-linux-arm-gnueabihf" "12.0.1"
"@next/swc-linux-arm64-gnu" "12.0.1"
"@next/swc-linux-arm64-musl" "12.0.1"
"@next/swc-linux-x64-gnu" "12.0.1"
"@next/swc-linux-x64-musl" "12.0.1"
"@next/swc-win32-arm64-msvc" "12.0.1"
"@next/swc-win32-ia32-msvc" "12.0.1"
"@next/swc-win32-x64-msvc" "12.0.1"
node-fetch@2.6.1:
version "2.6.1"
@@ -2037,35 +2048,6 @@ node-html-parser@1.4.9:
dependencies:
he "1.2.0"
node-libs-browser@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425"
integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==
dependencies:
assert "^1.1.1"
browserify-zlib "^0.2.0"
buffer "^4.3.0"
console-browserify "^1.1.0"
constants-browserify "^1.0.0"
crypto-browserify "^3.11.0"
domain-browser "^1.1.1"
events "^3.0.0"
https-browserify "^1.0.0"
os-browserify "^0.3.0"
path-browserify "0.0.1"
process "^0.11.10"
punycode "^1.2.4"
querystring-es3 "^0.2.0"
readable-stream "^2.3.3"
stream-browserify "^2.0.1"
stream-http "^2.7.2"
string_decoder "^1.0.0"
timers-browserify "^2.0.4"
tty-browserify "0.0.0"
url "^0.11.0"
util "^0.11.0"
vm-browserify "^1.0.1"
node-releases@^1.1.71:
version "1.1.74"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.74.tgz#e5866488080ebaa70a93b91144ccde06f3c3463e"
@@ -2166,7 +2148,7 @@ optionator@^0.9.1:
type-check "^0.4.0"
word-wrap "^1.2.3"
os-browserify@0.3.0, os-browserify@^0.3.0:
os-browserify@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=
@@ -2247,11 +2229,6 @@ parse-json@^4.0.0:
error-ex "^1.3.1"
json-parse-better-errors "^1.0.1"
path-browserify@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a"
integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==
path-browserify@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
@@ -2341,13 +2318,6 @@ platform@1.3.6:
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7"
integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==
pnp-webpack-plugin@1.6.4:
version "1.6.4"
resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149"
integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==
dependencies:
ts-pnp "^1.1.6"
postcss@8.2.15:
version "8.2.15"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.15.tgz#9e66ccf07292817d226fc315cbbf9bc148fbca65"
@@ -2362,12 +2332,7 @@ prelude-ls@^1.2.1:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
process@0.11.10, process@^0.11.10:
process@0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
@@ -2398,36 +2363,16 @@ public-encrypt@^4.0.0:
randombytes "^2.0.1"
safe-buffer "^5.1.2"
punycode@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d"
integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=
punycode@^1.2.4:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
punycode@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
querystring-es3@0.2.1, querystring-es3@^0.2.0:
querystring-es3@0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=
querystring@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
querystring@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.1.tgz#40d77615bb09d16902a85c3e38aa8b5ed761c2dd"
integrity sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==
queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
@@ -2489,6 +2434,16 @@ react-refresh@0.8.3:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
react-server-dom-webpack@0.0.0-experimental-3c4c1c470-20211021:
version "0.0.0-experimental-3c4c1c470-20211021"
resolved "https://registry.yarnpkg.com/react-server-dom-webpack/-/react-server-dom-webpack-0.0.0-experimental-3c4c1c470-20211021.tgz#cdcaa2f19c8d820c1f4d31252319fb05e2de0e88"
integrity sha512-YyRlED5kR0C2aQ3IJ/8BR2TELt51RcDZhnUDKz+m/HU+Gb/qak0CZkG0A8Zxffom9VI6HFkUj1dRFZqm0Lh9Pg==
dependencies:
acorn "^6.2.1"
loose-envify "^1.1.0"
neo-async "^2.6.1"
object-assign "^4.1.1"
react@17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
@@ -2514,19 +2469,6 @@ read-pkg@^3.0.0:
normalize-package-data "^2.3.2"
path-type "^3.0.0"
readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@^2.3.6:
version "2.3.7"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~2.0.0"
safe-buffer "~5.1.1"
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
readable-stream@^3.5.0, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
@@ -2543,6 +2485,11 @@ readdirp@~3.5.0:
dependencies:
picomatch "^2.2.1"
regenerator-runtime@0.13.4:
version "0.13.4"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.4.tgz#e96bf612a3362d12bb69f7e8f74ffeab25c7ac91"
integrity sha512-plpwicqEzfEyTQohIKktWigcLzmNStMGwbOUbykx51/29Z3JOGYldaaNGK7ngNXV+UcoqvIMmloZ48Sr74sd+g==
regenerator-runtime@^0.13.4:
version "0.13.9"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
@@ -2619,7 +2566,7 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2,
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safe-buffer@~5.1.0, safe-buffer@~5.1.1:
safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
@@ -2780,14 +2727,6 @@ stream-browserify@3.0.0:
inherits "~2.0.4"
readable-stream "^3.5.0"
stream-browserify@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b"
integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==
dependencies:
inherits "~2.0.1"
readable-stream "^2.0.2"
stream-http@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564"
@@ -2798,17 +2737,6 @@ stream-http@3.1.1:
readable-stream "^3.6.0"
xtend "^4.0.2"
stream-http@^2.7.2:
version "2.8.3"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc"
integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==
dependencies:
builtin-status-codes "^3.0.0"
inherits "^2.0.1"
readable-stream "^2.3.6"
to-arraybuffer "^1.0.0"
xtend "^4.0.0"
stream-parser@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773"
@@ -2860,21 +2788,21 @@ string.prototype.trimstart@^1.0.4:
call-bind "^1.0.2"
define-properties "^1.1.3"
string_decoder@1.3.0, string_decoder@^1.0.0, string_decoder@^1.1.1:
string_decoder@1.3.0, string_decoder@^1.1.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
dependencies:
safe-buffer "~5.2.0"
string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
strip-ansi@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
safe-buffer "~5.1.0"
ansi-regex "^5.0.1"
strip-ansi@6.0.0, strip-ansi@^6.0.0:
strip-ansi@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
@@ -2891,10 +2819,10 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
styled-jsx@4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-4.0.1.tgz#ae3f716eacc0792f7050389de88add6d5245b9e9"
integrity sha512-Gcb49/dRB1k8B4hdK8vhW27Rlb2zujCk1fISrizCcToIs+55B4vmUM0N9Gi4nnVfFZWe55jRdWpAqH1ldAKWvQ==
styled-jsx@5.0.0-beta.3:
version "5.0.0-beta.3"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0-beta.3.tgz#400d16179b5dff10d5954ab8be27a9a1b7780dd2"
integrity sha512-HtDDGSFPvmjHIqWf9n8Oo54tAoY/DTplvlyOH2+YOtD80Sp31Ap8ffSmxhgk5EkUoJ7xepdXMGT650mSffWuRA==
dependencies:
"@babel/plugin-syntax-jsx" "7.14.5"
"@babel/types" "7.15.0"
@@ -2953,18 +2881,13 @@ text-table@^0.2.0:
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
timers-browserify@2.0.12, timers-browserify@^2.0.4:
timers-browserify@2.0.12:
version "2.0.12"
resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee"
integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==
dependencies:
setimmediate "^1.0.4"
to-arraybuffer@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
@@ -2989,11 +2912,6 @@ tr46@^1.0.1:
dependencies:
punycode "^2.1.0"
ts-pnp@^1.1.6:
version "1.2.0"
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
tsconfig-paths@^3.9.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz#79ae67a68c15289fdf5c51cb74f397522d795ed7"
@@ -3015,11 +2933,6 @@ tsutils@^3.21.0:
dependencies:
tslib "^1.8.1"
tty-browserify@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
tty-browserify@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811"
@@ -3064,14 +2977,6 @@ uri-js@^4.2.2:
dependencies:
punycode "^2.1.0"
url@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"
integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=
dependencies:
punycode "1.3.2"
querystring "0.2.0"
use-subscription@1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"
@@ -3079,18 +2984,11 @@ use-subscription@1.5.1:
dependencies:
object-assign "^4.1.1"
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
util-deprecate@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
util@0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"
integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk=
dependencies:
inherits "2.0.1"
util@0.12.4, util@^0.12.0:
version "0.12.4"
resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253"
@@ -3103,13 +3001,6 @@ util@0.12.4, util@^0.12.0:
safe-buffer "^5.1.2"
which-typed-array "^1.1.2"
util@^0.11.0:
version "0.11.1"
resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61"
integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==
dependencies:
inherits "2.0.3"
v8-compile-cache@^2.0.3:
version "2.3.0"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
@@ -3123,7 +3014,7 @@ validate-npm-package-license@^3.0.1:
spdx-correct "^3.0.0"
spdx-expression-parse "^3.0.0"
vm-browserify@1.1.2, vm-browserify@^1.0.1:
vm-browserify@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
@@ -3136,6 +3027,11 @@ watchpack@2.1.1:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"
web-streams-polyfill@3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.0.3.tgz#f49e487eedeca47a207c1aee41ee5578f884b42f"
integrity sha512-d2H/t0eqRNM4w2WvmTdoeIvzAUSpK7JmATB8Nr2lb7nQ9BTIJVjbQ/TRFVEh2gUH1HwclPdoPtfMoFfetXaZnA==
webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@@ -3190,7 +3086,7 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
xtend@^4.0.0, xtend@^4.0.2:
xtend@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==

7
examples/parcel/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
node_modules
.parcel-cache
dist
/.pnp
.pnp.js
.DS_Store
.vercel

34
examples/parcel/README.md Normal file
View File

@@ -0,0 +1,34 @@
This is a vanilla web app built with [Parcel](https://parceljs.org).
## Getting Started
Run the dev server:
```bash
yarn start
# or
npm start
```
And open [localhost:1234](http://localhost:1234) in your browser!
As you make changes, you should see your app automatically update in the browser without even refreshing the page!
## Learn More
- [Getting started guide](https://parceljs.org/getting-started/webapp/)
- [Documentation](https://parceljs.org/docs/)
## Deploy Your Own
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/vercel/tree/main/examples/parcel&template=parcel)
_Live Example: https://parcel.examples.vercel.com_
### Deploying From Your Terminal
You can deploy your new Parcel project with a single command from your terminal using [Vercel CLI](https://vercel.com/download):
```shell
$ vercel
```

View File

@@ -0,0 +1,12 @@
{
"name": "parcel-app",
"private": true,
"source": "src/index.html",
"scripts": {
"start": "parcel",
"build": "parcel build"
},
"devDependencies": {
"parcel": "^2.0.0"
}
}

View File

@@ -0,0 +1 @@
console.log('Hello world!');

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>My First Parcel App</title>
<link rel="stylesheet" href="styles.css" />
<script type="module" src="app.js"></script>
</head>
<body>
<h1>Hello, Parcel!</h1>
<p>This is a vanilla web app built with Parcel 2!<br>Check out the <a href="https://parceljs.org/getting-started/webapp/" target="_blank">getting started guide</a> and the <a href="https://parceljs.org/docs/" target="_blank">documentation</a> to learn more!</p>
</body>
</html>

View File

@@ -0,0 +1,18 @@
body {
text-align: center;
}
h1 {
color: hotpink;
font-family: cursive;
font-size: 55px;
}
p {
font-family: Helvetica, Arial, sans-serif;
line-height: 1.5em;
}
a {
color: dodgerblue;
}

4541
examples/parcel/yarn.lock Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@
"eslint-config-prettier": "8.3.0",
"eslint-plugin-jest": "24.3.6",
"husky": "6.0.0",
"jest": "27.0.6",
"jest": "27.3.1",
"json5": "2.1.1",
"lint-staged": "9.2.5",
"node-fetch": "2.6.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.12.3-canary.1",
"version": "2.12.3-canary.20",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -21,7 +21,7 @@
"@types/async-retry": "^1.2.1",
"@types/cross-spawn": "6.0.0",
"@types/end-of-stream": "^1.4.0",
"@types/fs-extra": "^5.0.5",
"@types/fs-extra": "9.0.13",
"@types/glob": "^7.1.1",
"@types/jest": "27.0.1",
"@types/js-yaml": "3.12.1",
@@ -30,15 +30,15 @@
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",
"@vercel/frameworks": "0.5.1-canary.2",
"@vercel/ncc": "0.29.2",
"@vercel/frameworks": "0.5.1-canary.12",
"@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",
"async-sema": "2.1.4",
"boxen": "4.2.0",
"cross-spawn": "6.0.5",
"end-of-stream": "1.4.1",
"fs-extra": "7.0.0",
"fs-extra": "10.0.0",
"glob": "7.1.3",
"into-stream": "5.0.0",
"js-yaml": "3.13.1",

View File

@@ -0,0 +1,202 @@
import fs from 'fs-extra';
import { join, dirname, relative } from 'path';
import glob from './fs/glob';
import { normalizePath } from './fs/normalize-path';
import { FILES_SYMBOL, getLambdaOptionsFromFunction, Lambda } from './lambda';
import type FileBlob from './file-blob';
import type { BuilderFunctions, BuildOptions, Files } from './types';
import minimatch from 'minimatch';
/**
* Convert legacy Runtime to a Plugin.
* @param buildRuntime - a legacy build() function from a Runtime
* @param ext - the file extension, for example `.py`
*/
export function convertRuntimeToPlugin(
buildRuntime: (options: BuildOptions) => Promise<{ output: Lambda }>,
ext: string
) {
return async function build({ workPath }: { workPath: string }) {
const opts = { cwd: workPath };
const files = await glob('**', opts);
delete files['vercel.json']; // Builders/Runtimes didn't have vercel.json
const entrypoints = await glob(`api/**/*${ext}`, opts);
const pages: { [key: string]: any } = {};
const { functions = {} } = await readVercelConfig(workPath);
const traceDir = join(workPath, '.output', 'runtime-traced-files');
await fs.ensureDir(traceDir);
for (const entrypoint of Object.keys(entrypoints)) {
const key =
Object.keys(functions).find(
src => src === entrypoint || minimatch(entrypoint, src)
) || '';
const config = functions[key] || {};
const { output } = await buildRuntime({
files,
entrypoint,
workPath,
config: {
zeroConfig: true,
includeFiles: config.includeFiles,
excludeFiles: config.excludeFiles,
},
});
pages[entrypoint] = {
handler: output.handler,
runtime: output.runtime,
memory: output.memory,
maxDuration: output.maxDuration,
environment: output.environment,
allowQuery: output.allowQuery,
regions: output.regions,
};
// @ts-ignore This symbol is a private API
const lambdaFiles: Files = output[FILES_SYMBOL];
const entry = join(workPath, '.output', 'server', 'pages', entrypoint);
await fs.ensureDir(dirname(entry));
await linkOrCopy(files[entrypoint].fsPath, entry);
const tracedFiles: {
absolutePath: string;
relativePath: string;
}[] = [];
Object.entries(lambdaFiles).forEach(async ([relPath, file]) => {
const newPath = join(traceDir, relPath);
tracedFiles.push({ absolutePath: newPath, relativePath: relPath });
if (file.fsPath) {
await linkOrCopy(file.fsPath, newPath);
} else if (file.type === 'FileBlob') {
const { data, mode } = file as FileBlob;
await fs.writeFile(newPath, data, { mode });
} else {
throw new Error(`Unknown file type: ${file.type}`);
}
});
const nft = join(
workPath,
'.output',
'server',
'pages',
`${entrypoint}.nft.json`
);
const json = JSON.stringify({
version: 1,
files: tracedFiles.map(f => ({
input: normalizePath(relative(nft, f.absolutePath)),
output: normalizePath(f.relativePath),
})),
});
await fs.ensureDir(dirname(nft));
await fs.writeFile(nft, json);
}
await updateFunctionsManifest({ workPath, pages });
};
}
async function linkOrCopy(existingPath: string, newPath: string) {
try {
await fs.createLink(existingPath, newPath);
} catch (err: any) {
if (err.code !== 'EEXIST') {
await fs.copyFile(existingPath, newPath);
}
}
}
async function readJson(filePath: string): Promise<{ [key: string]: any }> {
try {
const str = await fs.readFile(filePath, 'utf8');
return JSON.parse(str);
} catch (err) {
if (err.code === 'ENOENT') {
return {};
}
throw err;
}
}
async function readVercelConfig(
workPath: string
): Promise<{ functions?: BuilderFunctions; regions?: string[] }> {
const vercelJsonPath = join(workPath, 'vercel.json');
return readJson(vercelJsonPath);
}
/**
* If `.output/functions-manifest.json` exists, append to the pages
* property. Otherwise write a new file. This will also read `vercel.json`
* and apply relevant `functions` property config.
*/
export async function updateFunctionsManifest({
workPath,
pages,
}: {
workPath: string;
pages: { [key: string]: any };
}) {
const functionsManifestPath = join(
workPath,
'.output',
'functions-manifest.json'
);
const vercelConfig = await readVercelConfig(workPath);
const functionsManifest = await readJson(functionsManifestPath);
if (!functionsManifest.version) functionsManifest.version = 1;
if (!functionsManifest.pages) functionsManifest.pages = {};
for (const [pageKey, pageConfig] of Object.entries(pages)) {
const fnConfig = await getLambdaOptionsFromFunction({
sourceFile: pageKey,
config: vercelConfig,
});
functionsManifest.pages[pageKey] = {
...pageConfig,
memory: fnConfig.memory || pageConfig.memory,
maxDuration: fnConfig.maxDuration || pageConfig.maxDuration,
regions: vercelConfig.regions || pageConfig.regions,
};
}
await fs.writeFile(functionsManifestPath, JSON.stringify(functionsManifest));
}
/**
* Will append routes to the `routes-manifest.json` file.
* If the file does not exist, it'll be created.
*/
export async function updateRoutesManifest({
workPath,
dynamicRoutes,
}: {
workPath: string;
dynamicRoutes?: {
page: string;
regex: string;
namedRegex?: string;
routeKeys?: { [named: string]: string };
}[];
}) {
const routesManifestPath = join(workPath, '.output', 'routes-manifest.json');
const routesManifest = await readJson(routesManifestPath);
if (!routesManifest.version) routesManifest.version = 1;
if (routesManifest.pages404 === undefined) routesManifest.pages404 = true;
if (dynamicRoutes) {
if (!routesManifest.dynamicRoutes) routesManifest.dynamicRoutes = [];
routesManifest.dynamicRoutes.push(...dynamicRoutes);
}
await fs.writeFile(routesManifestPath, JSON.stringify(routesManifest));
}

View File

@@ -1030,7 +1030,7 @@ function getRouteResult(
// https://nextjs.org/docs/advanced-features/custom-error-page
errorRoutes.push({
status: 404,
src: '^/(?!.*api).*$',
src: '^(?!/api).*$',
dest: options.cleanUrls ? '/404' : '/404.html',
});
}

View File

@@ -3,6 +3,7 @@ import assert from 'assert';
import vanillaGlob_ from 'glob';
import { promisify } from 'util';
import { lstat, Stats } from 'fs-extra';
import { normalizePath } from './normalize-path';
import FileFsRef from '../file-fs-ref';
export type GlobOptions = vanillaGlob_.IOptions;
@@ -45,7 +46,7 @@ export default async function glob(
const files = await vanillaGlob(pattern, options);
for (const relativePath of files) {
const fsPath = path.join(options.cwd!, relativePath).replace(/\\/g, '/');
const fsPath = normalizePath(path.join(options.cwd!, relativePath));
let stat: Stats = options.statCache![fsPath] as Stats;
assert(
stat,

View File

@@ -0,0 +1,8 @@
const isWin = process.platform === 'win32';
/**
* Convert Windows separators to Unix separators.
*/
export function normalizePath(p: string): string {
return isWin ? p.replace(/\\/g, '/') : p;
}

View File

@@ -81,6 +81,12 @@ export {
export { detectFramework } from './detect-framework';
export { DetectorFilesystem } from './detectors/filesystem';
export { readConfigFile } from './fs/read-config-file';
export { normalizePath } from './fs/normalize-path';
export {
convertRuntimeToPlugin,
updateFunctionsManifest,
updateRoutesManifest,
} from './convert-runtime-to-plugin';
export * from './schemas';
export * from './types';

View File

@@ -20,6 +20,7 @@ interface LambdaOptions {
maxDuration?: number;
environment: Environment;
allowQuery?: string[];
regions?: string[];
}
interface CreateLambdaOptions {
@@ -30,13 +31,16 @@ interface CreateLambdaOptions {
maxDuration?: number;
environment?: Environment;
allowQuery?: string[];
regions?: string[];
}
interface GetLambdaOptionsFromFunctionOptions {
sourceFile: string;
config?: Config;
config?: Pick<Config, 'functions'>;
}
export const FILES_SYMBOL = Symbol('files');
export class Lambda {
public type: 'Lambda';
public zipBuffer: Buffer;
@@ -46,6 +50,7 @@ export class Lambda {
public maxDuration?: number;
public environment: Environment;
public allowQuery?: string[];
public regions?: string[];
constructor({
zipBuffer,
@@ -55,6 +60,7 @@ export class Lambda {
memory,
environment,
allowQuery,
regions,
}: LambdaOptions) {
this.type = 'Lambda';
this.zipBuffer = zipBuffer;
@@ -64,6 +70,7 @@ export class Lambda {
this.maxDuration = maxDuration;
this.environment = environment;
this.allowQuery = allowQuery;
this.regions = regions;
}
}
@@ -78,6 +85,7 @@ export async function createLambda({
maxDuration,
environment = {},
allowQuery,
regions,
}: CreateLambdaOptions): Promise<Lambda> {
assert(typeof files === 'object', '"files" must be an object');
assert(typeof handler === 'string', '"handler" is not a string');
@@ -100,18 +108,30 @@ export async function createLambda({
);
}
if (regions !== undefined) {
assert(Array.isArray(regions), '"regions" is not an Array');
assert(
regions.every(r => typeof r === 'string'),
'"regions" is not a string Array'
);
}
await sema.acquire();
try {
const zipBuffer = await createZip(files);
return new Lambda({
const lambda = new Lambda({
zipBuffer,
handler,
runtime,
memory,
maxDuration,
environment,
regions,
});
// @ts-ignore This symbol is a private API
lambda[FILES_SYMBOL] = files;
return lambda;
} finally {
sema.release();
}

View File

@@ -9,6 +9,7 @@ interface PrerenderOptions {
fallback: FileBlob | FileFsRef | FileRef | null;
group?: number;
bypassToken?: string | null /* optional to be non-breaking change */;
allowQuery?: string[];
}
export class Prerender {
@@ -18,6 +19,7 @@ export class Prerender {
public fallback: FileBlob | FileFsRef | FileRef | null;
public group?: number;
public bypassToken: string | null;
public allowQuery?: string[];
constructor({
expiration,
@@ -25,6 +27,7 @@ export class Prerender {
fallback,
group,
bypassToken,
allowQuery,
}: PrerenderOptions) {
this.type = 'Prerender';
this.expiration = expiration;
@@ -62,5 +65,19 @@ export class Prerender {
);
}
this.fallback = fallback;
if (allowQuery !== undefined) {
if (!Array.isArray(allowQuery)) {
throw new Error(
'The `allowQuery` argument for `Prerender` must be Array.'
);
}
if (!allowQuery.every(q => typeof q === 'string')) {
throw new Error(
'The `allowQuery` argument for `Prerender` must be Array of strings.'
);
}
this.allowQuery = allowQuery;
}
}
}

View File

@@ -10,6 +10,7 @@ export interface File {
mode: number;
contentType?: string;
toStream: () => NodeJS.ReadableStream;
toStreamAsync?: () => Promise<NodeJS.ReadableStream>;
/**
* The absolute path to the file in the filesystem
*/

View File

@@ -1,5 +1,5 @@
{
"version": 2,
"builds": [{ "src": "package.json", "use": "@vercel/static-build" }],
"probes": [{ "path": "/", "mustContain": "npm version: 7" }]
"probes": [{ "path": "/", "mustContain": "npm version: 8" }]
}

View File

@@ -2013,15 +2013,11 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
framework: 'redwoodjs',
};
const {
builders,
defaultRoutes,
rewriteRoutes,
errorRoutes,
} = await detectBuilders(files, null, {
projectSettings,
featHandleMiss,
});
const { builders, defaultRoutes, rewriteRoutes, errorRoutes } =
await detectBuilders(files, null, {
projectSettings,
featHandleMiss,
});
expect(builders).toStrictEqual([
{
@@ -2038,7 +2034,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(errorRoutes).toStrictEqual([
{
status: 404,
src: '^/(?!.*api).*$',
src: '^(?!/api).*$',
dest: '/404.html',
},
]);
@@ -2050,15 +2046,11 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
framework: 'redwoodjs',
};
const {
builders,
defaultRoutes,
rewriteRoutes,
errorRoutes,
} = await detectBuilders(files, null, {
projectSettings,
featHandleMiss,
});
const { builders, defaultRoutes, rewriteRoutes, errorRoutes } =
await detectBuilders(files, null, {
projectSettings,
featHandleMiss,
});
expect(builders).toStrictEqual([
{
@@ -2096,7 +2088,7 @@ describe('Test `detectBuilders` with `featHandleMiss=true`', () => {
expect(errorRoutes).toStrictEqual([
{
status: 404,
src: '^/(?!.*api).*$',
src: '^(?!/api).*$',
dest: '/404.html',
},
]);
@@ -2417,7 +2409,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
expect(errorRoutes).toStrictEqual([
{
status: 404,
src: '^/(?!.*api).*$',
src: '^(?!/api).*$',
dest: '/404.html',
},
]);
@@ -2435,6 +2427,11 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
'/another/sub/index.html',
'/another/sub/page.html',
'/another/sub/page',
'/another/api',
'/another/api/page.html',
'/rapid',
'/rapid/page.html',
'/health-api.html',
].forEach(file => {
expect(file).toMatch(pattern);
});
@@ -2443,12 +2440,12 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
'/api',
'/api/',
'/api/index.html',
'/api/page.html',
'/api/page',
'/api/users.js',
'/api/users',
'/api/sub',
'/api/sub/index.html',
'/api/sub/page.html',
'/api/sub/page',
'/api/sub/users.js',
'/api/sub/users',
].forEach(file => {
expect(file).not.toMatch(pattern);
});
@@ -2819,12 +2816,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
{
const files = ['api/user.go', 'api/team.js', 'api/package.json'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
errorRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes, errorRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -2836,7 +2829,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
expect(errorRoutes).toStrictEqual([
{
status: 404,
src: '^/(?!.*api).*$',
src: '^(?!/api).*$',
dest: '/404',
},
]);
@@ -2904,11 +2897,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
{
const files = ['api/[endpoint].js', 'api/[endpoint]/[id].js'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -2936,11 +2926,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
'api/[endpoint]/[id].js',
];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -2974,11 +2961,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
const files = ['public/index.html', 'api/[endpoint].js'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, pkg, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, pkg, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3004,11 +2988,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
{
const files = ['api/date/index.js', 'api/date.js'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3022,11 +3003,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
{
const files = ['api/date.js', 'api/[date]/index.js'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3051,11 +3029,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
'api/food.ts',
'api/ts/gold.ts',
];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3071,11 +3046,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
const functions = { 'api/user.php': { runtime: 'vercel-php@0.1.0' } };
const files = ['api/user.php'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, { functions, ...options });
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, { functions, ...options });
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3105,11 +3077,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
{
const files = ['api/user.go', 'api/team.js', 'api/package.json'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3152,11 +3121,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
{
const files = ['api/[endpoint].js', 'api/[endpoint]/[id].js'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3184,11 +3150,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
'api/[endpoint]/[id].js',
];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3222,11 +3185,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
const files = ['public/index.html', 'api/[endpoint].js'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, pkg, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, pkg, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3245,11 +3205,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
{
const files = ['api/date/index.js', 'api/date.js'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3263,11 +3220,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
{
const files = ['api/date.js', 'api/[date]/index.js'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3292,11 +3246,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
'api/food.ts',
'api/ts/gold.ts',
];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
@@ -3312,11 +3263,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
const functions = { 'api/user.php': { runtime: 'vercel-php@0.1.0' } };
const files = ['api/user.php'];
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, { functions, ...options });
const { defaultRoutes, redirectRoutes, rewriteRoutes } =
await detectBuilders(files, null, { functions, ...options });
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([

View File

@@ -0,0 +1,182 @@
import { join } from 'path';
import fs from 'fs-extra';
import { BuildOptions, createLambda } from '../src';
import { convertRuntimeToPlugin } from '../src/convert-runtime-to-plugin';
async function fsToJson(dir: string, output: Record<string, any> = {}) {
const files = await fs.readdir(dir);
for (const file of files) {
const fsPath = join(dir, file);
const stat = await fs.stat(fsPath);
if (stat.isDirectory()) {
output[file] = {};
await fsToJson(fsPath, output[file]);
} else {
output[file] = await fs.readFile(fsPath, 'utf8');
}
}
return output;
}
const workPath = join(__dirname, 'walk', 'python-api');
describe('convert-runtime-to-plugin', () => {
afterEach(async () => {
await fs.remove(join(workPath, '.output'));
});
it('should create correct fileystem for python', async () => {
const lambdaOptions = {
handler: 'index.handler',
runtime: 'python3.9',
memory: 512,
maxDuration: 5,
environment: {},
regions: ['sfo1'],
};
const buildRuntime = async (opts: BuildOptions) => {
const lambda = await createLambda({
files: opts.files,
...lambdaOptions,
});
return { output: lambda };
};
const lambdaFiles = await fsToJson(workPath);
delete lambdaFiles['vercel.json'];
const build = await convertRuntimeToPlugin(buildRuntime, '.py');
await build({ workPath });
const output = await fsToJson(join(workPath, '.output'));
expect(output).toMatchObject({
'functions-manifest.json': expect.stringContaining('{'),
'runtime-traced-files': lambdaFiles,
server: {
pages: {
api: {
'index.py': expect.stringContaining('index'),
'index.py.nft.json': expect.stringContaining('{'),
users: {
'get.py': expect.stringContaining('get'),
'get.py.nft.json': expect.stringContaining('{'),
'post.py': expect.stringContaining('post'),
'post.py.nft.json': expect.stringContaining('{'),
},
},
},
},
});
const funcManifest = JSON.parse(output['functions-manifest.json']);
expect(funcManifest).toMatchObject({
version: 1,
pages: {
'api/index.py': lambdaOptions,
'api/users/get.py': lambdaOptions,
'api/users/post.py': { ...lambdaOptions, memory: 3008 },
},
});
const indexJson = JSON.parse(output.server.pages.api['index.py.nft.json']);
expect(indexJson).toMatchObject({
version: 1,
files: [
{
input: '../../../../runtime-traced-files/api/index.py',
output: 'api/index.py',
},
{
input: '../../../../runtime-traced-files/api/users/get.py',
output: 'api/users/get.py',
},
{
input: '../../../../runtime-traced-files/api/users/post.py',
output: 'api/users/post.py',
},
{
input: '../../../../runtime-traced-files/file.txt',
output: 'file.txt',
},
{
input: '../../../../runtime-traced-files/util/date.py',
output: 'util/date.py',
},
{
input: '../../../../runtime-traced-files/util/math.py',
output: 'util/math.py',
},
],
});
const getJson = JSON.parse(
output.server.pages.api.users['get.py.nft.json']
);
expect(getJson).toMatchObject({
version: 1,
files: [
{
input: '../../../../../runtime-traced-files/api/index.py',
output: 'api/index.py',
},
{
input: '../../../../../runtime-traced-files/api/users/get.py',
output: 'api/users/get.py',
},
{
input: '../../../../../runtime-traced-files/api/users/post.py',
output: 'api/users/post.py',
},
{
input: '../../../../../runtime-traced-files/file.txt',
output: 'file.txt',
},
{
input: '../../../../../runtime-traced-files/util/date.py',
output: 'util/date.py',
},
{
input: '../../../../../runtime-traced-files/util/math.py',
output: 'util/math.py',
},
],
});
const postJson = JSON.parse(
output.server.pages.api.users['post.py.nft.json']
);
expect(postJson).toMatchObject({
version: 1,
files: [
{
input: '../../../../../runtime-traced-files/api/index.py',
output: 'api/index.py',
},
{
input: '../../../../../runtime-traced-files/api/users/get.py',
output: 'api/users/get.py',
},
{
input: '../../../../../runtime-traced-files/api/users/post.py',
output: 'api/users/post.py',
},
{
input: '../../../../../runtime-traced-files/file.txt',
output: 'file.txt',
},
{
input: '../../../../../runtime-traced-files/util/date.py',
output: 'util/date.py',
},
{
input: '../../../../../runtime-traced-files/util/math.py',
output: 'util/math.py',
},
],
});
expect(output.server.pages['file.txt']).toBeUndefined();
expect(output.server.pages.api['file.txt']).toBeUndefined();
});
});

View File

@@ -0,0 +1 @@
# index

View File

@@ -0,0 +1 @@
# get

View File

@@ -0,0 +1 @@
# post

View File

@@ -0,0 +1 @@
This file should also be included

View File

@@ -0,0 +1 @@
# date

View File

@@ -0,0 +1 @@
# math

View File

@@ -0,0 +1,10 @@
{
"functions": {
"api/users/post.py": {
"memory": 3008
},
"api/not-matching-anything.py": {
"memory": 768
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "23.1.3-canary.1",
"version": "23.1.3-canary.38",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -43,14 +43,17 @@
"node": ">= 12"
},
"dependencies": {
"@vercel/build-utils": "2.12.3-canary.1",
"@vercel/go": "1.2.4-canary.1",
"@vercel/node": "1.12.2-canary.1",
"@vercel/python": "2.0.6-canary.1",
"@vercel/ruby": "1.2.8-canary.1",
"update-notifier": "4.1.0"
"@vercel/build-utils": "2.12.3-canary.20",
"@vercel/go": "1.2.4-canary.4",
"@vercel/node": "1.12.2-canary.7",
"@vercel/python": "2.1.0",
"@vercel/ruby": "1.2.8-canary.4",
"update-notifier": "4.1.0",
"vercel-plugin-middleware": "0.0.0-canary.7",
"vercel-plugin-node": "1.12.2-canary.11"
},
"devDependencies": {
"@next/env": "11.1.2",
"@sentry/node": "5.5.0",
"@sindresorhus/slugify": "0.11.0",
"@tootallnate/once": "1.1.2",
@@ -63,7 +66,7 @@
"@types/dotenv": "6.1.1",
"@types/escape-html": "0.0.20",
"@types/express": "4.17.13",
"@types/fs-extra": "5.0.5",
"@types/fs-extra": "9.0.13",
"@types/glob": "7.1.1",
"@types/http-proxy": "1.16.2",
"@types/inquirer": "7.3.1",
@@ -87,8 +90,9 @@
"@types/update-notifier": "5.1.0",
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@vercel/frameworks": "0.5.1-canary.2",
"@vercel/ncc": "0.29.2",
"@vercel/frameworks": "0.5.1-canary.12",
"@vercel/ncc": "0.24.0",
"@vercel/nft": "0.17.0",
"@zeit/fun": "0.11.2",
"@zeit/source-map-support": "0.6.2",
"ajv": "6.12.2",
@@ -120,7 +124,7 @@
"execa": "3.2.0",
"express": "4.17.1",
"fast-deep-equal": "3.1.3",
"fs-extra": "7.0.1",
"fs-extra": "10.0.0",
"get-port": "5.1.1",
"glob": "7.1.2",
"http-proxy": "1.18.1",

View File

@@ -49,19 +49,12 @@ async function main() {
// Do the initial `ncc` build
console.log();
const src = join(dirRoot, 'src/index.ts');
const args = [
'ncc',
'build',
'--no-asset-builds',
'--external',
'update-notifier',
];
const args = ['ncc', 'build', '--external', 'update-notifier'];
if (isDev) {
args.push('--source-map');
}
args.push(src);
await execa('yarn', args, { stdio: 'inherit' });
args.push('src/index.ts');
await execa('yarn', args, { stdio: 'inherit', cwd: dirRoot });
// `ncc` has some issues with `@zeit/fun`'s runtime files:
// - Executable bits on the `bootstrap` files appear to be lost:

View File

@@ -51,8 +51,6 @@ const help = () => {
};
let argv;
let debug;
let apiUrl;
let subcommand;
export default async client => {
@@ -65,8 +63,6 @@ export default async client => {
argv._ = argv._.slice(1);
debug = argv['--debug'];
apiUrl = client.apiUrl;
subcommand = argv._[0];
if (argv['--help'] || !subcommand) {
@@ -76,17 +72,13 @@ export default async client => {
const {
output,
authConfig: { token },
config: { currentTeam },
} = client;
const start = new Date();
const creditCards = new NowCreditCards({
apiUrl,
token,
debug,
client,
currentTeam,
output,
});
let contextName = null;

View File

@@ -0,0 +1,791 @@
import { loadEnvConfig, processEnv } from '@next/env';
import {
execCommand,
getScriptName,
GlobOptions,
scanParentDirs,
spawnAsync,
} from '@vercel/build-utils';
import { nodeFileTrace } from '@vercel/nft';
import Sema from 'async-sema';
import chalk from 'chalk';
import { SpawnOptions } from 'child_process';
import { assert } from 'console';
import { createHash } from 'crypto';
import fs from 'fs-extra';
import ogGlob from 'glob';
import { isAbsolute, join, parse, relative, resolve } from 'path';
import pluralize from 'pluralize';
import Client from '../util/client';
import { emoji, prependEmoji } from '../util/emoji';
import getArgs from '../util/get-args';
import handleError from '../util/handle-error';
import confirm from '../util/input/confirm';
import { isSettingValue } from '../util/is-setting-value';
import cmd from '../util/output/cmd';
import logo from '../util/output/logo';
import param from '../util/output/param';
import stamp from '../util/output/stamp';
import { getCommandName, getPkgName } from '../util/pkg-name';
import { loadCliPlugins } from '../util/plugins';
import { findFramework } from '../util/projects/find-framework';
import { VERCEL_DIR } from '../util/projects/link';
import { readProjectSettings } from '../util/projects/project-settings';
import pull from './pull';
const sema = new Sema(16, {
capacity: 100,
});
const help = () => {
return console.log(`
${chalk.bold(`${logo} ${getPkgName()} build`)}
${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
--cwd [path] The current working directory
-d, --debug Debug mode [off]
-y, --yes Skip the confirmation prompt
${chalk.dim('Examples:')}
${chalk.gray('')} Build the project
${chalk.cyan(`$ ${getPkgName()} build`)}
${chalk.cyan(`$ ${getPkgName()} build --cwd ./path-to-project`)}
`);
};
const OUTPUT_DIR = '.output';
export default async function main(client: Client) {
if (process.env.__VERCEL_BUILD_RUNNING) {
client.output.error(
`${cmd(
`${getPkgName()} build`
)} must not recursively invoke itself. Check the Build Command in the Project Settings or the ${cmd(
'build'
)} script in ${cmd('package.json')}`
);
client.output.error(
`Learn More: https://vercel.link/recursive-invocation-of-commands`
);
return 1;
} else {
process.env.__VERCEL_BUILD_RUNNING = '1';
}
let argv;
const buildStamp = stamp();
try {
argv = getArgs(client.argv.slice(2), {
'--debug': Boolean,
'--cwd': String,
});
} catch (err) {
handleError(err);
return 1;
}
if (argv['--help']) {
help();
return 2;
}
let cwd = argv['--cwd'] || process.cwd();
let project = await readProjectSettings(join(cwd, VERCEL_DIR));
// If there are no project settings, only then do we pull them down
while (!project?.settings) {
const confirmed = await confirm(
`No Project Settings found locally. Run ${getCommandName(
'pull'
)} for retrieving them?`,
true
);
if (!confirmed) {
client.output.print(`Aborted. No Project Settings retrieved.\n`);
return 0;
}
const result = await pull(client);
if (result !== 0) {
return result;
}
project = await readProjectSettings(join(cwd, VERCEL_DIR));
}
// If `rootDirectory` exists, then `baseDir` will be the repo's root directory.
const baseDir = cwd;
cwd = project.settings.rootDirectory
? join(cwd, project.settings.rootDirectory)
: cwd;
// Load the environment
const { combinedEnv, loadedEnvFiles } = loadEnvConfig(cwd, false, {
info: () => ({}), // we don't want to log this yet.
error: (...args: any[]) => client.output.error(args.join(' ')),
});
// Set process.env with loaded environment variables
await processEnv(loadedEnvFiles);
const spawnOpts = {
env: { ...combinedEnv, VERCEL: '1' },
};
process.chdir(cwd);
const framework = findFramework(project.settings.framework);
// If this is undefined, we bail. If it is null, then findFramework should return "Other",
// so this should really never happen, but just in case....
if (framework === undefined) {
client.output.error(
`Framework detection failed or is malformed. Please run ${getCommandName(
'pull'
)} again.`
);
return 1;
}
const buildState = { ...project.settings };
const formatSetting = (
name: string,
override: string | null | undefined,
defaults: typeof framework.settings.outputDirectory
) =>
` - ${chalk.bold(`${name}:`)} ${`${
override
? override + ` (override)`
: 'placeholder' in defaults
? chalk.italic(`${defaults.placeholder}`)
: defaults.value
}`}`;
console.log(`Retrieved Project Settings:`);
console.log(
chalk.dim(` - ${chalk.bold(`Framework Preset:`)} ${framework.name}`)
);
console.log(
chalk.dim(
formatSetting(
'Build Command',
project.settings.buildCommand,
framework.settings.buildCommand
)
)
);
console.log(
chalk.dim(
formatSetting(
'Output Directory',
project.settings.outputDirectory,
framework.settings.outputDirectory
)
)
);
buildState.outputDirectory =
project.settings.outputDirectory ||
(isSettingValue(framework.settings.outputDirectory)
? framework.settings.outputDirectory.value
: null);
buildState.rootDirectory = project.settings.rootDirectory;
if (loadedEnvFiles.length > 0) {
console.log(
`Loaded Environment Variables from ${loadedEnvFiles.length} ${pluralize(
'file',
loadedEnvFiles.length
)}:`
);
for (let envFile of loadedEnvFiles) {
console.log(chalk.dim(` - ${envFile.path}`));
}
}
// Load plugins
const debug = argv['--debug'];
let plugins;
try {
plugins = await loadCliPlugins(cwd, client.output);
} catch (error) {
client.output.error('Failed to load CLI Plugins');
handleError(error, { debug });
return 1;
}
const origLog = console.log;
const origErr = console.error;
const prefixedLog = (
prefix: string,
args: any[],
logger: (...args: any[]) => void
) => {
if (typeof args[0] === 'string') {
args[0] = `${prefix} ${args[0]}`;
} else {
args.unshift(prefix);
}
return logger(...args);
};
if (plugins?.pluginCount && plugins?.pluginCount > 0) {
console.log(
`Loaded ${plugins.pluginCount} CLI ${pluralize(
'Plugin',
plugins.pluginCount
)}`
);
// preBuild Plugins
if (plugins.preBuildPlugins.length > 0) {
console.log(
`Running ${plugins.pluginCount} CLI ${pluralize(
'Plugin',
plugins.pluginCount
)} before Build Command:`
);
for (let item of plugins.preBuildPlugins) {
const { name, plugin, color } = item;
if (typeof plugin.preBuild === 'function') {
const pluginStamp = stamp();
const fullName = name + '.preBuild';
const prefix = chalk.gray(' > ') + color(fullName + ':');
client.output.debug(`Running ${fullName}:`);
try {
console.log = (...args: any[]) =>
prefixedLog(prefix, args, origLog);
console.error = (...args: any[]) =>
prefixedLog(prefix, args, origErr);
await plugin.preBuild();
client.output.debug(
`Completed ${fullName} ${chalk.dim(`${pluginStamp()}`)}`
);
} catch (error) {
client.output.error(`${prefix} failed`);
handleError(error, { debug });
return 1;
} finally {
console.log = origLog;
console.error = origErr;
}
}
}
}
}
// Clean the output directory
fs.removeSync(join(cwd, OUTPUT_DIR));
// Yarn v2 PnP mode may be activated, so force
// "node-modules" linker style
const env = {
YARN_NODE_LINKER: 'node-modules',
...spawnOpts.env,
};
if (typeof buildState.buildCommand === 'string') {
console.log(`Running Build Command: ${cmd(buildState.buildCommand)}`);
await execCommand(buildState.buildCommand, {
...spawnOpts,
env,
cwd,
});
} else if (fs.existsSync(join(cwd, 'package.json'))) {
await runPackageJsonScript(
client,
cwd,
['vercel-build', 'now-build', 'build'],
spawnOpts
);
} else if (typeof framework.settings.buildCommand.value === 'string') {
console.log(
`Running Build Command: ${cmd(framework.settings.buildCommand.value)}`
);
await execCommand(framework.settings.buildCommand.value, {
...spawnOpts,
env,
cwd,
});
}
if (!fs.existsSync(join(cwd, OUTPUT_DIR))) {
let outputDir = join(OUTPUT_DIR, 'static');
let distDir = await framework.getFsOutputDir(cwd);
if (framework.slug === 'nextjs') {
outputDir = OUTPUT_DIR;
}
const copyStamp = stamp();
await fs.ensureDir(join(cwd, outputDir));
const relativeDistDir = relative(cwd, distDir);
client.output.spinner(
`Copying files from ${param(distDir)} to ${param(outputDir)}`
);
const files = await glob(join(relativeDistDir, '**'), {
ignore: [
'node_modules/**',
'.vercel/**',
'.env',
'.env.*',
'.*ignore',
'_middleware.ts',
'_middleware.mts',
'_middleware.cts',
'_middleware.mjs',
'_middleware.cjs',
'_middleware.js',
'api/**',
'.git/**',
'.next/cache/**',
],
nodir: true,
dot: true,
cwd,
absolute: true,
});
await Promise.all(
files.map(f =>
smartCopy(
client,
f,
distDir === '.'
? join(cwd, outputDir, relative(cwd, f))
: f.replace(distDir, outputDir)
)
)
);
client.output.stopSpinner();
console.log(
`Copied ${files.length.toLocaleString()} files from ${param(
distDir
)} to ${param(outputDir)} ${copyStamp()}`
);
const buildManifestPath = join(cwd, OUTPUT_DIR, 'build-manifest.json');
const routesManifestPath = join(cwd, OUTPUT_DIR, 'routes-manifest.json');
if (!fs.existsSync(buildManifestPath)) {
client.output.debug(
`Generating build manifest: ${param(buildManifestPath)}`
);
const buildManifest = {
cache: framework.cachePattern ? [framework.cachePattern] : [],
};
await fs.writeJSON(buildManifestPath, buildManifest, { spaces: 2 });
}
if (!fs.existsSync(routesManifestPath)) {
client.output.debug(
`Generating routes manifest: ${param(routesManifestPath)}`
);
const routesManifest = {
version: 3,
pages404: true,
basePath: '',
redirects: framework.defaultRedirects ?? [],
headers: framework.defaultHeaders ?? [],
dynamicRoutes: [],
dataRoutes: [],
rewrites: framework.defaultRewrites ?? [],
};
await fs.writeJSON(
join(cwd, OUTPUT_DIR, 'routes-manifest.json'),
routesManifest,
{ spaces: 2 }
);
}
// Special Next.js processing.
if (framework.slug === 'nextjs') {
// The contents of `.output/static` should be placed inside of `.output/static/_next/static`
const tempStatic = '___static';
await fs.rename(
join(cwd, OUTPUT_DIR, 'static'),
join(cwd, OUTPUT_DIR, tempStatic)
);
await fs.mkdirp(join(cwd, OUTPUT_DIR, 'static', '_next', 'static'));
await fs.rename(
join(cwd, OUTPUT_DIR, tempStatic),
join(cwd, OUTPUT_DIR, 'static', '_next', 'static')
);
// Next.js might reference files from the `static` directory in `middleware-manifest.json`.
// Since we move all files from `static` to `static/_next/static`, we'll need to change
// those references as well and update the manifest file.
const middlewareManifest = join(
cwd,
OUTPUT_DIR,
'server',
'middleware-manifest.json'
);
if (fs.existsSync(middlewareManifest)) {
const manifest = await fs.readJSON(middlewareManifest);
Object.keys(manifest.middleware).forEach(key => {
const files = manifest.middleware[key].files.map((f: string) => {
if (f.startsWith('static/')) {
const next = f.replace(/^static\//gm, 'static/_next/static/');
client.output.debug(
`Replacing file in \`middleware-manifest.json\`: ${f} => ${next}`
);
return next;
}
return f;
});
manifest.middleware[key].files = files;
});
await fs.writeJSON(middlewareManifest, manifest);
}
// We want to pick up directories for user-provided static files into `.`output/static`.
// More specifically, the static directory contents would then be mounted to `output/static/static`,
// and the public directory contents would be mounted to `output/static`. Old Next.js versions
// allow `static`, and newer ones allow both, but since there's nobody that actually uses both,
// we can check for the existence of both and pick the first match that we find (first
// `public`, then`static`). We can't read both at the same time because that would mean we'd
// read public for old Next.js versions that don't support it, which might be breaking (and
// we don't want to make vercel build specific framework versions).
const publicFiles = await glob('public/**', {
nodir: true,
dot: true,
cwd,
absolute: true,
});
if (publicFiles.length > 0) {
await Promise.all(
publicFiles.map(f =>
smartCopy(
client,
f,
f.replace('public', join(OUTPUT_DIR, 'static'))
)
)
);
} else {
const staticFiles = await glob('static/**', {
nodir: true,
dot: true,
cwd,
absolute: true,
});
await Promise.all(
staticFiles.map(f =>
smartCopy(
client,
f,
f.replace('static', join(OUTPUT_DIR, 'static', 'static'))
)
)
);
}
// Regardless of the Next.js version, we make sure that it is compatible with
// the Filesystem API. We get there by moving all the files needed
// into the outputs directory `inputs` folder. Next.js is > 12, we can
// read the .nft.json files directly. If there aren't .nft.json files
// we trace and create them. We then resolve the files in each nft file list
// and move them into the "inputs" directory. We rename them with hashes to
// prevent collisions and then update the related .nft files accordingly
// to point to the newly named input files. Again, all of this is so that Next.js
// works with the Filesystem API (and so .output contains all inputs
// needed to run Next.js) and `vc --prebuilt`.
const nftFiles = await glob(join(OUTPUT_DIR, '**', '*.nft.json'), {
nodir: true,
dot: true,
cwd,
absolute: true,
});
// If there are no .nft.json files, we know that Next.js < 12. We then
// execute the tracing on our own.
if (nftFiles.length === 0) {
const serverFiles = await glob(
join(OUTPUT_DIR, 'server', 'pages', '**', '*.js'),
{
nodir: true,
dot: true,
cwd,
ignore: ['webpack-runtime.js'],
absolute: true,
}
);
for (let f of serverFiles) {
const { ext, dir } = parse(f);
const { fileList } = await nodeFileTrace([f], {
ignore: [
relative(cwd, f),
'node_modules/next/dist/pages/**/*',
'node_modules/next/dist/compiled/webpack/(bundle4|bundle5).js',
'node_modules/react/**/*.development.js',
'node_modules/react-dom/**/*.development.js',
'node_modules/use-subscription/**/*.development.js',
'node_modules/sharp/**/*',
],
});
fileList.delete(relative(cwd, f));
await resolveNftToOutput({
client,
baseDir,
outputDir: OUTPUT_DIR,
nftFileName: f.replace(ext, '.js.nft.json'),
nft: {
version: 1,
files: Array.from(fileList).map(fileListEntry =>
relative(dir, fileListEntry)
),
},
});
}
} else {
for (let f of nftFiles) {
const json = await fs.readJson(f);
await resolveNftToOutput({
client,
baseDir,
outputDir: OUTPUT_DIR,
nftFileName: f,
nft: json,
});
}
}
const requiredServerFilesPath = join(
OUTPUT_DIR,
'required-server-files.json'
);
const requiredServerFilesJson = await fs.readJSON(
requiredServerFilesPath
);
await fs.writeJSON(requiredServerFilesPath, {
...requiredServerFilesJson,
appDir: '.',
files: requiredServerFilesJson.files.map((i: string) => {
const absolutePath = join(cwd, i.replace('.next', '.output'));
const output = relative(baseDir, absolutePath);
return {
input: i.replace('.next', '.output'),
output,
};
}),
});
}
}
// Build Plugins
if (plugins?.buildPlugins && plugins.buildPlugins.length > 0) {
console.log(
`Running ${plugins.pluginCount} CLI ${pluralize(
'Plugin',
plugins.pluginCount
)} after Build Command:`
);
for (let item of plugins.buildPlugins) {
const { name, plugin, color } = item;
if (typeof plugin.build === 'function') {
const pluginStamp = stamp();
const fullName = name + '.build';
const prefix = chalk.gray(' > ') + color(fullName + ':');
client.output.debug(`Running ${fullName}:`);
try {
console.log = (...args: any[]) => prefixedLog(prefix, args, origLog);
console.error = (...args: any[]) =>
prefixedLog(prefix, args, origErr);
await plugin.build({
workPath: cwd,
});
client.output.debug(
`Completed ${fullName} ${chalk.dim(`${pluginStamp()}`)}`
);
} catch (error) {
client.output.error(`${prefix} failed`);
handleError(error, { debug });
return 1;
} finally {
console.log = origLog;
console.error = origLog;
}
}
}
}
console.log(
`${prependEmoji(
`Build Completed in ${chalk.bold(OUTPUT_DIR)} ${chalk.gray(
buildStamp()
)}`,
emoji('success')
)}`
);
return 0;
}
export async function runPackageJsonScript(
client: Client,
destPath: string,
scriptNames: string | Iterable<string>,
spawnOpts?: SpawnOptions
) {
assert(isAbsolute(destPath));
const { packageJson, cliType, lockfileVersion } = await scanParentDirs(
destPath,
true
);
const scriptName = getScriptName(
packageJson,
typeof scriptNames === 'string' ? [scriptNames] : scriptNames
);
if (!scriptName) return false;
client.output.debug('Running user script...');
const runScriptTime = Date.now();
const opts: any = { cwd: destPath, ...spawnOpts };
const env = (opts.env = { ...process.env, ...opts.env });
if (cliType === 'npm') {
opts.prettyCommand = `npm run ${scriptName}`;
if (typeof lockfileVersion === 'number' && lockfileVersion >= 2) {
// Ensure that npm 7 is at the beginning of the `$PATH`
env.PATH = `/node16/bin-npm7:${env.PATH}`;
}
} else {
opts.prettyCommand = `yarn run ${scriptName}`;
// Yarn v2 PnP mode may be activated, so force "node-modules" linker style
if (!env.YARN_NODE_LINKER) {
env.YARN_NODE_LINKER = 'node-modules';
}
}
console.log(`Running Build Command: ${cmd(opts.prettyCommand)}\n`);
await spawnAsync(cliType, ['run', scriptName], opts);
console.log(); // give it some room
client.output.debug(`Script complete [${Date.now() - runScriptTime}ms]`);
return true;
}
async function linkOrCopy(existingPath: string, newPath: string) {
try {
if (
newPath.endsWith('.nft.json') ||
newPath.endsWith('middleware-manifest.json') ||
newPath.endsWith('required-server-files.json')
) {
await fs.copy(existingPath, newPath, {
overwrite: true,
});
} else {
await fs.createLink(existingPath, newPath);
}
} catch (err: any) {
// eslint-disable-line
// If a symlink to the same file already exists
// then trying to copy it will make an empty file from it.
if (err['code'] === 'EEXIST') return;
// In some VERY rare cases (1 in a thousand), symlink creation fails on Windows.
// In that case, we just fall back to copying.
// This issue is reproducible with "pnpm add @material-ui/icons@4.9.1"
await fs.copy(existingPath, newPath, {
overwrite: true,
});
}
}
async function smartCopy(client: Client, from: string, to: string) {
sema.acquire();
try {
client.output.debug(`Copying from ${from} to ${to}`);
await linkOrCopy(from, to);
} finally {
sema.release();
}
}
async function glob(pattern: string, options: GlobOptions): Promise<string[]> {
return new Promise((resolve, reject) => {
ogGlob(pattern, options, (err, files) => {
err ? reject(err) : resolve(files);
});
});
}
/**
* Computes a hash for the given buf.
*
* @param {Buffer} file data
* @return {String} hex digest
*/
function hash(buf: Buffer): string {
return createHash('sha1').update(buf).digest('hex');
}
interface NftFile {
version: number;
files: (string | { input: string; output: string })[];
}
// resolveNftToOutput takes nft file and moves all of its trace files
// into the specified directory + `inputs`, (renaming them to their hash + ext) and
// subsequently updating the original nft file accordingly. This is done
// to make the `.output` directory be self-contained, so that it works
// properly with `vc --prebuilt`.
async function resolveNftToOutput({
client,
baseDir,
outputDir,
nftFileName,
nft,
}: {
client: Client;
baseDir: string;
outputDir: string;
nftFileName: string;
nft: NftFile;
}) {
client.output.debug(`Processing and resolving ${nftFileName}`);
await fs.ensureDir(join(outputDir, 'inputs'));
const newFilesList: NftFile['files'] = [];
for (let fileEntity of nft.files) {
const relativeInput: string =
typeof fileEntity === 'string' ? fileEntity : fileEntity.input;
const fullInput = resolve(join(parse(nftFileName).dir, relativeInput));
// if the resolved path is NOT in the .output directory we move in it there
if (!fullInput.includes(outputDir)) {
const { ext } = parse(fullInput);
const raw = await fs.readFile(fullInput);
const newFilePath = join(outputDir, 'inputs', hash(raw) + ext);
smartCopy(client, fullInput, newFilePath);
// We have to use `baseDir` instead of `cwd`, because we want to
// mount everything from there (especially `node_modules`).
// This is important for NPM Workspaces where `node_modules` is not
// in the directory of the workspace.
const output = relative(baseDir, fullInput).replace('.output', '.next');
newFilesList.push({
input: relative(parse(nftFileName).dir, newFilePath),
output,
});
} else {
newFilesList.push(relativeInput);
}
}
// Update the .nft.json with new input and output mapping
await fs.writeJSON(nftFileName, {
...nft,
files: newFilesList,
});
}

View File

@@ -18,9 +18,10 @@ export const help = () => `
init [example] Initialize an example project
ls | list [app] Lists deployments
inspect [id] Displays information related to a deployment
link Link local directory to a Vercel Project
link [path] Link local directory to a Vercel Project
login [email] Logs into your account or creates a new one
logout Logs out of your account
pull [path] Pull your Project Settings from the cloud
switch [scope] Switches between teams and your personal account
help [cmd] Displays complete help for [cmd]

View File

@@ -60,13 +60,10 @@ import { getCommandName } from '../../util/pkg-name';
import { getPreferredPreviewURL } from '../../util/deploy/get-preferred-preview-url';
import { Output } from '../../util/output';
import { help } from './args';
import { getDeploymentChecks } from '../../util/deploy/get-deployment-checks';
export default async (client: Client) => {
const {
apiUrl,
output,
authConfig: { token },
} = client;
const { output } = client;
let argv = null;
@@ -82,6 +79,7 @@ export default async (client: Client) => {
// This is not an array in favor of matching
// the config property name.
'--regions': String,
'--prebuilt': Boolean,
'--prod': Boolean,
'--confirm': Boolean,
'-f': '--force',
@@ -157,10 +155,8 @@ export default async (client: Client) => {
}
}
const { log, debug, error, warn } = output;
const debugEnabled = argv['--debug'];
const { log, debug, error, warn, isTTY } = output;
const { isTTY } = process.stdout;
const quiet = !isTTY;
// check paths
@@ -437,11 +433,8 @@ export default async (client: Client) => {
const currentTeam = org?.type === 'team' ? org.id : undefined;
const now = new Now({
apiUrl,
token,
debug: debugEnabled,
client,
currentTeam,
output,
});
let deployStamp = stamp();
let deployment = null;
@@ -453,6 +446,7 @@ export default async (client: Client) => {
build: { env: deploymentBuildEnv },
forceNew: argv['--force'],
withCache: argv['--with-cache'],
prebuilt: argv['--prebuilt'],
quiet,
wantsPublic: argv['--public'] || localConfig.public,
isFile,
@@ -536,6 +530,20 @@ export default async (client: Client) => {
return 1;
}
if (deployment.checksConclusion === 'failed') {
const { checks } = await getDeploymentChecks(client, deployment.id);
const counters = new Map<string, number>();
checks.forEach(c => {
counters.set(c.conclusion, (counters.get(c.conclusion) ?? 0) + 1);
});
const counterList = Array.from(counters)
.map(([name, no]) => `${no} ${name}`)
.join(', ');
output.error(`Running Checks: ${counterList}`);
return 1;
}
const deploymentResponse = await getDeploymentByIdOrHost(
client,
contextName,

View File

@@ -6,7 +6,6 @@ import { ProjectEnvVariable } from '../../types';
import Client from '../../util/client';
import { getLinkedProject } from '../../util/projects/link';
import { getFrameworks } from '../../util/get-frameworks';
import { isSettingValue } from '../../util/is-setting-value';
import { ProjectSettings } from '../../types';
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
import setupAndLink from '../../util/link/setup-and-link';
@@ -71,9 +70,9 @@ export default async function dev(
frameworkSlug = framework.slug;
}
const defaults = framework.settings.devCommand;
if (isSettingValue(defaults)) {
devCommand = defaults.value;
const defaults = framework.settings.devCommand.value;
if (defaults) {
devCommand = defaults;
}
}
}

View File

@@ -48,6 +48,22 @@ const help = () => {
};
export default async function main(client: Client) {
if (process.env.__VERCEL_DEV_RUNNING) {
client.output.error(
`${cmd(
`${getPkgName()} dev`
)} must not recursively invoke itself. Check the Development Command in the Project Settings or the ${cmd(
'dev'
)} script in ${cmd('package.json')}`
);
client.output.error(
`Learn More: https://vercel.link/recursive-invocation-of-commands`
);
return 1;
} else {
process.env.__VERCEL_DEV_RUNNING = '1';
}
let argv;
let args;
const { output } = client;
@@ -90,22 +106,21 @@ export default async function main(client: Client) {
if (pkg) {
const { scripts } = pkg as PackageJson;
if (scripts && scripts.dev && /\bnow\b\W+\bdev\b/.test(scripts.dev)) {
output.error(
`The ${cmd('dev')} script in ${cmd(
'package.json'
)} must not contain ${cmd('now dev')}`
if (
scripts &&
scripts.dev &&
/\b(now|vercel)\b\W+\bdev\b/.test(scripts.dev)
) {
client.output.error(
`${cmd(
`${getPkgName()} dev`
)} must not recursively invoke itself. Check the Development Command in the Project Settings or the ${cmd(
'dev'
)} script in ${cmd('package.json')}`
);
output.error(`Learn More: http://err.sh/vercel/now-dev-as-dev-script`);
return 1;
}
if (scripts && scripts.dev && /\bvercel\b\W+\bdev\b/.test(scripts.dev)) {
output.error(
`The ${cmd('dev')} script in ${cmd(
'package.json'
)} must not contain ${cmd('vercel dev')}`
client.output.error(
`Learn More: https://vercel.link/recursive-invocation-of-commands`
);
output.error(`Learn More: http://err.sh/vercel/now-dev-as-dev-script`);
return 1;
}
}
@@ -121,7 +136,7 @@ export default async function main(client: Client) {
} catch (err) {
if (err.code === 'ENOTFOUND') {
// Error message will look like the following:
// "request to https://api.vercel.com/www/user failed, reason: getaddrinfo ENOTFOUND api.vercel.com"
// "request to https://api.vercel.com/v2/user failed, reason: getaddrinfo ENOTFOUND api.vercel.com"
const matches = /getaddrinfo ENOTFOUND (.*)$/.exec(err.message || '');
if (matches && matches[1]) {
const hostname = matches[1];

View File

@@ -194,8 +194,8 @@ async function findDestinationMatch(
user: User,
teams: Team[]
) {
if (user.uid === destination || user.username === destination) {
return user.uid;
if (user.id === destination || user.username === destination) {
return user.id;
}
for (const team of teams) {

View File

@@ -1,18 +1,16 @@
import chalk from 'chalk';
import getArgs from '../../util/get-args';
import getSubcommand from '../../util/get-subcommand';
import getInvalidSubcommand from '../../util/get-invalid-subcommand';
import { getEnvTargetPlaceholder } from '../../util/env/env-target';
import { getLinkedProject } from '../../util/projects/link';
import Client from '../../util/client';
import { getEnvTargetPlaceholder } from '../../util/env/env-target';
import getArgs from '../../util/get-args';
import getInvalidSubcommand from '../../util/get-invalid-subcommand';
import getSubcommand from '../../util/get-subcommand';
import handleError from '../../util/handle-error';
import logo from '../../util/output/logo';
import { getCommandName, getPkgName } from '../../util/pkg-name';
import { getLinkedProject } from '../../util/projects/link';
import add from './add';
import pull from './pull';
import ls from './ls';
import pull from './pull';
import rm from './rm';
const help = () => {
@@ -139,6 +137,13 @@ export default async function main(client: Client) {
case 'rm':
return rm(client, project, argv, args, output);
case 'pull':
output.warn(
`${getCommandName(
'env pull'
)} is deprecated and will be removed in future releases. Run ${getCommandName(
'pull'
)} instead.`
);
return pull(client, project, argv, args, output);
default:
output.error(getInvalidSubcommand(COMMAND_CONFIG));

View File

@@ -1,18 +1,18 @@
import chalk from 'chalk';
import { closeSync, openSync, promises, readSync } from 'fs';
import { resolve } from 'path';
import { Project } from '../../types';
import { Output } from '../../util/output';
import confirm from '../../util/input/confirm';
import Client from '../../util/client';
import stamp from '../../util/output/stamp';
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
import param from '../../util/output/param';
import { join } from 'path';
import { promises, openSync, closeSync, readSync } from 'fs';
import exposeSystemEnvs from '../../util/dev/expose-system-envs';
import { emoji, prependEmoji } from '../../util/emoji';
import getSystemEnvValues from '../../util/env/get-system-env-values';
import getDecryptedEnvRecords from '../../util/get-decrypted-env-records';
import confirm from '../../util/input/confirm';
import { Output } from '../../util/output';
import param from '../../util/output/param';
import stamp from '../../util/output/stamp';
import { getCommandName } from '../../util/pkg-name';
const { writeFile } = promises;
import exposeSystemEnvs from '../../util/dev/expose-system-envs';
import getSystemEnvValues from '../../util/env/get-system-env-values';
const CONTENTS_PREFIX = '# Created by Vercel CLI\n';
@@ -56,8 +56,9 @@ export default async function pull(
return 1;
}
// handle relative or absolute filename
const [filename = '.env'] = args;
const fullPath = join(process.cwd(), filename);
const fullPath = resolve(filename);
const skipConfirmation = opts['--yes'];
const head = tryReadHeadSync(fullPath, Buffer.byteLength(CONTENTS_PREFIX));

View File

@@ -2,6 +2,7 @@ export default new Map([
['alias', 'alias'],
['aliases', 'alias'],
['billing', 'billing'],
['build', 'build'],
['cc', 'billing'],
['cert', 'certs'],
['certs', 'certs'],
@@ -24,6 +25,7 @@ export default new Map([
['ls', 'list'],
['project', 'projects'],
['projects', 'projects'],
['pull', 'pull'],
['remove', 'remove'],
['rm', 'remove'],
['secret', 'secrets'],

View File

@@ -77,14 +77,8 @@ export default async function main(client: Client) {
return 1;
}
const {
authConfig: { token },
output,
apiUrl,
config,
} = client;
const { output, config } = client;
const debugEnabled = argv['--debug'];
const { print, log, error, note, debug, spinner } = output;
if (argv._.length > 2) {
@@ -126,10 +120,7 @@ export default async function main(client: Client) {
spinner(`Fetching deployments in ${chalk.bold(contextName)}`);
const now = new Now({
apiUrl,
token,
debug: debugEnabled,
output,
client,
currentTeam,
});
const start = Date.now();

View File

@@ -0,0 +1,116 @@
import chalk from 'chalk';
import { join } from 'path';
import Client from '../util/client';
import { emoji, prependEmoji } from '../util/emoji';
import getArgs from '../util/get-args';
import handleError from '../util/handle-error';
import setupAndLink from '../util/link/setup-and-link';
import logo from '../util/output/logo';
import stamp from '../util/output/stamp';
import { getPkgName } from '../util/pkg-name';
import {
getLinkedProject,
VERCEL_DIR,
VERCEL_DIR_PROJECT,
} from '../util/projects/link';
import { writeProjectSettings } from '../util/projects/project-settings';
import pull from './env/pull';
const help = () => {
return console.log(`
${chalk.bold(`${logo} ${getPkgName()} pull`)} [path]
${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]
--env [filename] The file to write Development Environment Variables to [.env]
-y, --yes Skip the confirmation prompt
${chalk.dim('Examples:')}
${chalk.gray('')} Pull the latest Project Settings from the cloud
${chalk.cyan(`$ ${getPkgName()} pull`)}
${chalk.cyan(`$ ${getPkgName()} pull ./path-to-project`)}
${chalk.cyan(`$ ${getPkgName()} pull --env .env.local`)}
${chalk.cyan(`$ ${getPkgName()} pull ./path-to-project --env .env.local`)}
`);
};
export default async function main(client: Client) {
let argv;
try {
argv = getArgs(client.argv.slice(2), {
'--yes': Boolean,
'--env': String,
'--debug': Boolean,
'-d': '--debug',
'-y': '--yes',
});
} catch (err) {
handleError(err);
return 1;
}
if (argv['--help']) {
help();
return 2;
}
const cwd = argv._[1] || process.cwd();
const yes = argv['--yes'];
const env = argv['--env'] ?? '.env';
const settingsStamp = stamp();
let link = await getLinkedProject(client, cwd);
if (link.status === 'not_linked') {
link = await setupAndLink(client, cwd, {
autoConfirm: yes,
successEmoji: 'link',
setupMsg: 'Set up',
});
if (link.status === 'not_linked') {
// User aborted project linking questions
return 0;
}
}
if (link.status === 'error') {
return link.exitCode;
}
const { project, org } = link;
client.config.currentTeam = org.type === 'team' ? org.id : undefined;
const result = await pull(
client,
project,
argv,
[join(cwd, env)],
client.output
);
if (result !== 0) {
// an error happened
return result;
}
await writeProjectSettings(cwd, project, org);
client.output.print(
`${prependEmoji(
`Downloaded project settings to ${chalk.bold(
join(VERCEL_DIR, VERCEL_DIR_PROJECT)
)} ${chalk.gray(settingsStamp())}`,
emoji('success')
)}\n`
);
return 0;
}

View File

@@ -85,8 +85,6 @@ export default async function main(client: Client) {
argv._ = argv._.slice(1);
const {
apiUrl,
authConfig: { token },
output,
config: { currentTeam },
} = client;
@@ -245,11 +243,8 @@ export default async function main(client: Client) {
}
const now = new Now({
apiUrl,
token,
debug: argv['--debug'],
client,
currentTeam,
output,
});
const start = Date.now();

View File

@@ -72,8 +72,6 @@ const help = () => {
// Options
let argv;
let debug;
let apiUrl;
let subcommand;
let nextTimestamp;
@@ -90,8 +88,6 @@ const main = async client => {
argv._ = argv._.slice(1);
debug = argv.debug;
apiUrl = client.apiUrl;
subcommand = argv._[0];
nextTimestamp = argv.next;
@@ -101,7 +97,6 @@ const main = async client => {
}
const {
authConfig: { token },
output,
config: { currentTeam },
} = client;
@@ -118,7 +113,7 @@ const main = async client => {
throw err;
}
return run({ output, token, contextName, currentTeam, client });
return run({ output, contextName, currentTeam, client });
};
export default async client => {
@@ -130,8 +125,8 @@ export default async client => {
}
};
async function run({ output, token, contextName, currentTeam, client }) {
const secrets = new NowSecrets({ apiUrl, token, debug, currentTeam, output });
async function run({ output, contextName, currentTeam, client }) {
const secrets = new NowSecrets({ client, currentTeam });
const args = argv._.slice(1);
const start = Date.now();
const { 'test-warning': testWarningFlag } = argv;

View File

@@ -56,7 +56,7 @@ export default async function list(client: Client): Promise<number> {
}
if (accountIsCurrent) {
currentTeam = user.uid;
currentTeam = user.id;
}
const teamList = teams.map(({ id, slug, name }) => ({
@@ -67,7 +67,7 @@ export default async function list(client: Client): Promise<number> {
}));
teamList.unshift({
id: user.uid,
id: user.id,
name: user.email,
value: user.username || user.email,
current: accountIsCurrent ? chars.tick : '',

View File

@@ -160,18 +160,26 @@ const main = async () => {
// * a path to deploy (as in: `vercel path/`)
// * a subcommand (as in: `vercel ls`)
const targetOrSubcommand = argv._[2];
const isBuildOrDev =
targetOrSubcommand === 'build' || targetOrSubcommand === 'dev';
output.print(
`${chalk.grey(
`${getTitleName()} CLI ${pkg.version}${
targetOrSubcommand === 'dev' ? ' dev (beta)' : ''
}${
isCanary || targetOrSubcommand === 'dev'
? ' — https://vercel.com/feedback'
: ''
}`
)}\n`
);
if (isBuildOrDev) {
console.log(
`${chalk.grey(
`${getTitleName()} CLI ${
pkg.version
} ${targetOrSubcommand} (beta) — https://vercel.com/feedback`
)}`
);
} else {
output.print(
`${chalk.grey(
`${getTitleName()} CLI ${pkg.version}${
isCanary ? ' — https://vercel.com/feedback' : ''
}`
)}\n`
);
}
// Handle `--version` directly
if (!targetOrSubcommand && argv['--version']) {
@@ -286,7 +294,14 @@ const main = async () => {
let authConfig = null;
const subcommandsWithoutToken = ['login', 'logout', 'help', 'init', 'update'];
const subcommandsWithoutToken = [
'login',
'logout',
'help',
'init',
'update',
'build',
];
if (authConfigExists) {
try {
@@ -393,20 +408,33 @@ const main = async () => {
} else if (commands.has(singular)) {
alternative = singular;
}
console.error(
error(
`The supplied argument ${param(targetOrSubcommand)} is ambiguous.` +
`\nIf you wish to deploy the ${fileType} ${param(
targetOrSubcommand
)}, first run "cd ${targetOrSubcommand}". ` +
if (targetOrSubcommand === 'build') {
output.note(
`If you wish to deploy the ${fileType} ${param(
targetOrSubcommand
)}, run ${getCommandName('deploy build')}.` +
(alternative
? `\nIf you wish to use the subcommand ${param(
targetOrSubcommand
)}, use ${param(alternative)} instead.`
: '')
)
);
return 1;
);
} else {
console.error(
error(
`The supplied argument ${param(targetOrSubcommand)} is ambiguous.` +
`\nIf you wish to deploy the ${fileType} ${param(
targetOrSubcommand
)}, first run "cd ${targetOrSubcommand}". ` +
(alternative
? `\nIf you wish to use the subcommand ${param(
targetOrSubcommand
)}, use ${param(alternative)} instead.`
: '')
)
);
return 1;
}
}
if (subcommandExists) {
@@ -550,7 +578,7 @@ const main = async () => {
return 1;
}
if (user.uid === scope || user.email === scope || user.username === scope) {
if (user.id === scope || user.email === scope || user.username === scope) {
delete client.config.currentTeam;
} else {
let teams = [];
@@ -587,20 +615,99 @@ const main = async () => {
}
}
if (!targetCommand) {
const sub = param(subcommand);
console.error(error(`The ${sub} subcommand does not exist`));
return 1;
}
const metric = metrics();
let exitCode;
const eventCategory = 'Exit Code';
try {
const start = Date.now();
const full = require(`./commands/${targetCommand}`).default;
exitCode = await full(client);
let func: any;
switch (targetCommand) {
case 'alias':
func = await import('./commands/alias');
break;
case 'billing':
func = await import('./commands/billing');
break;
case 'build':
func = await import('./commands/build');
break;
case 'certs':
func = await import('./commands/certs');
break;
case 'deploy':
func = await import('./commands/deploy');
break;
case 'dev':
func = await import('./commands/dev');
break;
case 'dns':
func = await import('./commands/dns');
break;
case 'domains':
func = await import('./commands/domains');
break;
case 'env':
func = await import('./commands/env');
break;
case 'init':
func = await import('./commands/init');
break;
case 'inspect':
func = await import('./commands/inspect');
break;
case 'link':
func = await import('./commands/link');
break;
case 'list':
func = await import('./commands/list');
break;
case 'logs':
func = await import('./commands/logs');
break;
case 'login':
func = await import('./commands/login');
break;
case 'logout':
func = await import('./commands/logout');
break;
case 'projects':
func = await import('./commands/projects');
break;
case 'pull':
func = await import('./commands/pull');
break;
case 'remove':
func = await import('./commands/remove');
break;
case 'secrets':
func = await import('./commands/secrets');
break;
case 'teams':
func = await import('./commands/teams');
break;
case 'update':
func = await import('./commands/update');
break;
case 'whoami':
func = await import('./commands/whoami');
break;
default:
func = null;
break;
}
if (!func || !targetCommand) {
const sub = param(subcommand);
output.error(`The ${sub} subcommand does not exist`);
return 1;
}
if (func.default) {
func = func.default;
}
exitCode = await func(client);
const end = Date.now() - start;
if (shouldCollectMetrics) {
@@ -614,7 +721,7 @@ const main = async () => {
} catch (err) {
if (err.code === 'ENOTFOUND') {
// Error message will look like the following:
// "request to https://api.vercel.com/www/user failed, reason: getaddrinfo ENOTFOUND api.vercel.com"
// "request to https://api.vercel.com/v2/user failed, reason: getaddrinfo ENOTFOUND api.vercel.com"
const matches = /getaddrinfo ENOTFOUND (.*)$/.exec(err.message || '');
if (matches && matches[1]) {
const hostname = matches[1];

View File

@@ -45,25 +45,12 @@ type Billing = {
};
export type User = {
uid: string;
id: string;
avatar: string;
bio?: string;
date: number;
createdAt: number;
email: string;
username: string;
website?: string;
billingChecked: boolean;
billing: Billing;
github?: {
email: string;
installation: {
id: string;
login: string;
loginType: string;
};
login: string;
updatedAt: number;
};
name?: string;
limited?: boolean;
};

View File

@@ -18,7 +18,7 @@ async function getAppLastDeployment(
const deployments = await getDeploymentsByAppName(client, appName);
const deploymentItem = deployments
.sort((a, b) => b.created - a.created)
.filter(dep => dep.state === 'READY' && dep.creator.uid === user.uid)[0];
.filter(dep => dep.state === 'READY' && dep.creator.uid === user.id)[0];
// Try to fetch deployment details
if (deploymentItem) {

View File

@@ -100,7 +100,7 @@ export default class Client extends EventEmitter {
let body;
if (isJSONObject(opts.body)) {
body = JSON.stringify(opts.body);
headers.set('content-type', 'application/json; charset=utf8');
headers.set('content-type', 'application/json; charset=utf-8');
} else {
body = opts.body;
}

View File

@@ -18,12 +18,8 @@ export const isDirectory = (path: string): boolean => {
const getGlobalPathConfig = (): string => {
let customPath: string | undefined;
try {
const argv = getArgs(process.argv.slice(2), {});
customPath = argv['--global-config'];
} catch (_error) {
// args are optional so consume error
}
const argv = getArgs(process.argv.slice(2), {}, { permissive: true });
customPath = argv['--global-config'];
const vercelDirectories = XDGAppPaths('com.vercel.cli').dataDirs();

View File

@@ -7,12 +7,8 @@ import getArgs from '../../util/get-args';
export default function getLocalPathConfig(prefix: string) {
let customPath: string | undefined;
try {
const argv = getArgs(process.argv.slice(2), {});
customPath = argv['--local-config'];
} catch (_error) {
// args are optional so consume error
}
const argv = getArgs(process.argv.slice(2), {}, { permissive: true });
customPath = argv['--local-config'];
// If `--local-config` flag was specified, then that takes priority
if (customPath) {

View File

@@ -0,0 +1,37 @@
import Client from '../client';
type CheckStatus = 'registered' | 'running' | 'completed';
type CheckConclusion =
| 'canceled'
| 'failed'
| 'neutral'
| 'succeeded'
| 'skipped'
| 'stale';
export interface DeploymentCheck {
id: string;
status: CheckStatus;
conclusion: CheckConclusion;
name: string;
startedAt: number;
completedAt: number;
createdAt: number;
updatedAt: number;
integrationId: string;
rerequestable: boolean;
}
export interface DeploymentChecksResponse {
checks: DeploymentCheck[];
}
export async function getDeploymentChecks(
client: Client,
deploymentId: string
) {
const checksResponse = await client.fetch<DeploymentChecksResponse>(
`/v1/deployments/${encodeURIComponent(deploymentId)}/checks`
);
return checksResponse;
}

View File

@@ -47,6 +47,7 @@ export default async function processDeployment({
force?: boolean;
withCache?: boolean;
org: Org;
prebuilt: boolean;
projectName: string;
isSettingUpProject: boolean;
skipAutoDetectionConfirmation?: boolean;
@@ -62,6 +63,7 @@ export default async function processDeployment({
withCache,
nowConfig,
quiet,
prebuilt,
} = args;
const { debug } = output;
@@ -83,6 +85,7 @@ export default async function processDeployment({
path: paths[0],
force,
withCache,
prebuilt,
skipAutoDetectionConfirmation,
};
@@ -179,10 +182,26 @@ export default async function processDeployment({
return event.payload;
}
if (event.type === 'ready') {
// If `checksState` is present, we can only continue to "Completing" if the checks finished,
// otherwise we might show "Completing" before "Running Checks".
if (
event.type === 'ready' &&
(event.payload.checksState
? event.payload.checksState === 'completed'
: true)
) {
output.spinner('Completing', 0);
}
if (event.type === 'checks-running') {
output.spinner('Running Checks', 0);
}
if (event.type === 'checks-conclusion-failed') {
output.stopSpinner();
return event.payload;
}
// Handle error events
if (event.type === 'error') {
output.stopSpinner();

View File

@@ -217,13 +217,13 @@ export async function executeBuild(
if (output.maxDuration) {
throw new Error(
'The result of "builder.build()" must not contain `memory`'
'The result of "builder.build()" must not contain `maxDuration`'
);
}
if (output.memory) {
throw new Error(
'The result of "builder.build()" must not contain `maxDuration`'
'The result of "builder.build()" must not contain `memory`'
);
}

View File

@@ -89,6 +89,7 @@ import {
} from './types';
import { ProjectEnvVariable, ProjectSettings } from '../../types';
import exposeSystemEnvs from './expose-system-envs';
import { loadCliPlugins } from '../plugins';
const frontendRuntimeSet = new Set(
frameworkList.map(f => f.useRuntime?.use || '@vercel/static-build')
@@ -1349,6 +1350,30 @@ export default class DevServer {
return false;
};
runDevMiddleware = async (
req: http.IncomingMessage,
res: http.ServerResponse
) => {
const { devMiddlewarePlugins } = await loadCliPlugins(
this.cwd,
this.output
);
try {
for (let plugin of devMiddlewarePlugins) {
const result = await plugin.plugin.runDevMiddleware(req, res, this.cwd);
if (result.finished) {
return result;
}
}
return { finished: false };
} catch (e) {
return {
finished: true,
error: e,
};
}
};
/**
* Serve project directory as a v2 deployment.
*/
@@ -1416,6 +1441,36 @@ export default class DevServer {
let prevUrl = req.url;
let prevHeaders: HttpHeadersConfig = {};
const middlewareResult = await this.runDevMiddleware(req, res);
if (middlewareResult) {
if (middlewareResult.error) {
this.sendError(
req,
res,
requestId,
'EDGE_FUNCTION_INVOCATION_FAILED',
500
);
return;
}
if (middlewareResult.finished) {
return;
}
if (middlewareResult.pathname) {
const origUrl = url.parse(req.url || '/', true);
origUrl.pathname = middlewareResult.pathname;
prevUrl = url.format(origUrl);
}
if (middlewareResult.query && prevUrl) {
const origUrl = url.parse(req.url || '/', true);
delete origUrl.search;
Object.assign(origUrl.query, middlewareResult.query);
prevUrl = url.format(origUrl);
}
}
for (const phase of phases) {
statusCode = undefined;
@@ -2106,7 +2161,10 @@ export default class DevServer {
process.stdout.write(data.replace(proxyPort, devPort));
});
p.on('exit', () => {
p.on('exit', (code: number) => {
if (code > 0) {
process.exit(code);
}
this.devProcessPort = undefined;
});

View File

@@ -1,11 +1,9 @@
import { Stats } from 'fs';
import { sep, dirname, join, resolve } from 'path';
import { readJSON, lstat, readlink, readFile, realpath } from 'fs-extra';
import { lstat, readlink, readFile, realpath } from 'fs-extra';
import { isCanary } from './is-canary';
import { getPkgName } from './pkg-name';
// `npm` tacks a bunch of extra properties on the `package.json` file,
// so check for one of them to determine yarn vs. npm.
async function isYarn(): Promise<boolean> {
let s: Stats;
let binPath = process.argv[1];
@@ -20,8 +18,12 @@ async function isYarn(): Promise<boolean> {
}
}
const pkgPath = join(dirname(binPath), '..', 'package.json');
const pkg = await readJSON(pkgPath).catch(() => ({}));
return !('_id' in pkg);
/*
* Generally, pkgPath looks like:
* "/Users/username/.config/yarn/global/node_modules/vercel/package.json"
* "/usr/local/share/.config/yarn/global/node_modules/vercel/package.json"
*/
return pkgPath.includes(join('yarn', 'global'));
}
async function getConfigPrefix() {

View File

@@ -4,7 +4,7 @@ import { APIError, InvalidToken, MissingUser } from './errors-ts';
export default async function getUser(client: Client) {
try {
const res = await client.fetch<{ user: User }>('/www/user', {
const res = await client.fetch<{ user: User }>('/v2/user', {
useCurrentTeam: false,
});

View File

@@ -10,25 +10,21 @@ import chalk from 'chalk';
import ua from './ua';
import processDeployment from './deploy/process-deployment';
import highlight from './output/highlight';
import createOutput, { Output } from './output';
import { responseError } from './error';
import stamp from './output/stamp';
import { APIError, BuildError } from './errors-ts';
import printIndications from './print-indications';
import { Org } from '../types';
import { VercelConfig } from './dev/types';
import { FetchOptions, isJSONObject } from './client';
import Client, { FetchOptions, isJSONObject } from './client';
import { Dictionary } from '@vercel/client';
export interface NowOptions {
apiUrl: string;
token?: string;
client: Client;
url?: string | null;
currentTeam?: string | null;
output: Output;
forceNew?: boolean;
withCache?: boolean;
debug?: boolean;
}
export interface CreateOptions {
@@ -40,6 +36,7 @@ export interface CreateOptions {
name: string;
project?: string;
wantsPublic: boolean;
prebuilt?: boolean;
meta: Dictionary<string>;
regions?: string[];
quiet?: boolean;
@@ -66,39 +63,46 @@ export interface ListOptions {
export default class Now extends EventEmitter {
url: string | null;
currentTeam: string | null;
_apiUrl: string;
_token?: string;
_debug: boolean;
_client: Client;
_forceNew: boolean;
_withCache: boolean;
_output: Output;
_syncAmount?: number;
_files?: any[];
_missing?: string[];
constructor({
apiUrl,
token,
client,
url = null,
currentTeam = null,
forceNew = false,
withCache = false,
debug = false,
output = createOutput({ debug }),
}: NowOptions) {
super();
this.url = url;
this._token = token;
this._debug = debug;
this._client = client;
this._forceNew = forceNew;
this._withCache = withCache;
this._output = output;
this._apiUrl = apiUrl;
this._onRetry = this._onRetry.bind(this);
this.currentTeam = currentTeam;
}
get _apiUrl() {
return this._client.apiUrl;
}
get _token() {
return this._client.authConfig.token;
}
get _output() {
return this._client.output;
}
get _debug() {
return this._client.output.isDebugEnabled();
}
async create(
paths: string[],
{
@@ -108,6 +112,7 @@ export default class Now extends EventEmitter {
// Latest
name,
project,
prebuilt = false,
wantsPublic,
meta,
regions,
@@ -162,6 +167,7 @@ export default class Now extends EventEmitter {
isSettingUpProject,
skipAutoDetectionConfirmation,
cwd,
prebuilt,
});
if (deployment && deployment.warnings) {

View File

@@ -29,7 +29,7 @@ export default async function selectOrg(
const choices: Choice[] = [
{
name: user.name || user.username,
value: { type: 'user', id: user.uid, slug: user.username },
value: { type: 'user', id: user.id, slug: user.username },
},
...teams.map<Choice>(team => ({
name: team.name || team.slug,

View File

@@ -43,13 +43,7 @@ export default async function setupAndLink(
projectName,
}: SetupAndLinkOptions
): Promise<ProjectLinkResult> {
const {
authConfig: { token },
localConfig,
apiUrl,
output,
config,
} = client;
const { localConfig, output, config } = client;
const debug = output.isDebugEnabled();
const isFile = !isDirectory(path);
@@ -153,10 +147,7 @@ export default async function setupAndLink(
if (isZeroConfig) {
const now = new Now({
apiUrl,
token,
debug,
output,
client,
currentTeam: config.currentTeam,
});
const createArgs: CreateOptions = {

View File

@@ -31,5 +31,5 @@ export default function verify(
url.searchParams.set('ssoUserId', ssoUserId);
}
return client.fetch<LoginResultSuccess>(url.href);
return client.fetch<LoginResultSuccess>(url.href, { useCurrentTeam: false });
}

View File

@@ -1,6 +1,5 @@
import crypto from 'crypto';
import ua from 'universal-analytics';
import { platform, release, userInfo } from 'os';
import { getPlatformEnv } from '@vercel/build-utils';
import userAgent from './ua-browser';
@@ -16,10 +15,15 @@ export const shouldCollectMetrics =
export const metrics = (): ua.Visitor => {
const token =
typeof config.token === 'string' ? config.token : platform() + release();
const salt = userInfo().username;
typeof config.token === 'string'
? config.token
: process.platform + process.arch;
const salt =
(process.env.USER || '') +
(process.env.LANG || '') +
(process.env.SHELL || '');
const hash = crypto
.pbkdf2Sync(token, salt, 1000, 64, 'sha512')
.pbkdf2Sync(token, salt, 100, 64, 'sha512')
.toString('hex')
.substring(0, 24);

View File

@@ -0,0 +1,24 @@
import chalk from 'chalk';
const colors = [
chalk.cyan,
chalk.magenta,
chalk.green,
chalk.yellow,
chalk.blue,
];
let childIndex = 0;
const packageNameColorCache = new Map<string, chalk.Chalk>();
/** Return a consistent (gradient) color for a given package name */
export function getColorForPkgName(pkgName: string) {
let color = packageNameColorCache.get(pkgName);
if (!color) {
color = colors[childIndex++ % colors.length];
packageNameColorCache.set(pkgName, color);
}
return color;
}

View File

@@ -20,15 +20,13 @@ export class Output {
private debugEnabled: boolean;
private spinnerMessage: string;
private _spinner: StopSpinner | null;
isTTY: boolean;
constructor({ debug: debugEnabled = false }: OutputOptions = {}) {
this.debugEnabled = debugEnabled;
this.spinnerMessage = '';
this._spinner = null;
}
get isTTY() {
return process.stdout.isTTY;
this.isTTY = process.stdout.isTTY || false;
}
isDebugEnabled = () => {
@@ -127,10 +125,14 @@ export class Output {
this.debug(`Spinner invoked (${message}) with a ${delay}ms delay`);
return;
}
if (this._spinner) {
this._spinner.text = message;
if (this.isTTY) {
if (this._spinner) {
this._spinner.text = message;
} else {
this._spinner = wait(message, delay);
}
} else {
this._spinner = wait(message, delay);
this.print(`${message}\n`);
}
};

View File

@@ -1,11 +1,6 @@
import { relative as nativeRelative } from 'path';
const isWin = process.platform === 'win32';
import { normalizePath } from '@vercel/build-utils';
export function relative(a: string, b: string): string {
let p = nativeRelative(a, b);
if (isWin) {
p = p.replace(/\\/g, '/');
}
return p;
return normalizePath(nativeRelative(a, b));
}

View File

@@ -0,0 +1,76 @@
import code from '../util/output/code';
import { getColorForPkgName } from '../util/output/color-name-cache';
import cliPkgJson from '../util/pkg';
import { scanParentDirs } from '@vercel/build-utils';
import { Output } from './output';
const VERCEL_PLUGIN_PREFIX = 'vercel-plugin-';
export async function loadCliPlugins(cwd: string, output: Output) {
const { packageJson } = await scanParentDirs(cwd, true);
let pluginCount = 0;
const preBuildPlugins = [];
const buildPlugins = [];
const devServerPlugins = [];
const devMiddlewarePlugins = [];
const deps = new Set(
[
...Object.keys(packageJson?.dependencies || {}),
...Object.keys(packageJson?.devDependencies || {}),
...Object.keys(cliPkgJson.dependencies),
].filter(dep => dep.startsWith(VERCEL_PLUGIN_PREFIX))
);
for (let dep of deps) {
pluginCount++;
const resolved = require.resolve(dep, {
paths: [cwd, process.cwd(), __dirname],
});
let plugin;
try {
plugin = require(resolved);
const color = getColorForPkgName(dep);
if (typeof plugin.preBuild === 'function') {
preBuildPlugins.push({
plugin,
name: dep,
color,
});
}
if (typeof plugin.build === 'function') {
buildPlugins.push({
plugin,
name: dep,
color,
});
}
if (typeof plugin.startDevServer === 'function') {
devServerPlugins.push({
plugin,
name: dep,
color,
});
}
if (typeof plugin.runDevMiddleware === 'function') {
devMiddlewarePlugins.push({
plugin,
name: dep,
color,
});
}
} catch (error) {
output.error(`Failed to import ${code(dep)}`);
throw error;
}
}
return {
pluginCount,
preBuildPlugins,
buildPlugins,
devServerPlugins,
devMiddlewarePlugins,
};
}

View File

@@ -0,0 +1,5 @@
import { Framework, frameworks } from '@vercel/frameworks';
export function findFramework(slug?: string | null) {
return (frameworks as any as Framework[]).find(f => f.slug === slug);
}

View File

@@ -23,6 +23,7 @@ const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
export const VERCEL_DIR = '.vercel';
export const VERCEL_OUTPUT_DIR = '.output';
export const VERCEL_DIR_FALLBACK = '.now';
export const VERCEL_DIR_README = 'README.txt';
export const VERCEL_DIR_PROJECT = 'project.json';
@@ -67,12 +68,14 @@ async function getLink(path?: string): Promise<ProjectLink | null> {
return getLinkFromDir(dir);
}
async function getLinkFromDir(dir: string): Promise<ProjectLink | null> {
export async function getLinkFromDir<T = ProjectLink>(
dir: string
): Promise<T | null> {
try {
const json = await readFile(join(dir, VERCEL_DIR_PROJECT), 'utf8');
const ajv = new AJV();
const link: ProjectLink = JSON.parse(json);
const link: T = JSON.parse(json);
if (!ajv.validate(linkSchema, link)) {
throw new Error(
@@ -106,7 +109,7 @@ async function getOrgById(client: Client, orgId: string): Promise<Org | null> {
}
const user = await getUser(client);
if (user.uid !== orgId) return null;
if (user.id !== orgId) return null;
return { type: 'user', id: orgId, slug: user.username };
}
@@ -241,16 +244,27 @@ export async function linkFolderToProject(
try {
const gitIgnorePath = join(path, '.gitignore');
const gitIgnore = await readFile(gitIgnorePath, 'utf8').catch(() => null);
const EOL = gitIgnore && gitIgnore.includes('\r\n') ? '\r\n' : os.EOL;
let gitIgnore =
(await readFile(gitIgnorePath, 'utf8').catch(() => null)) ?? '';
const EOL = gitIgnore.includes('\r\n') ? '\r\n' : os.EOL;
let contentModified = false;
if (!gitIgnore || !gitIgnore.split(EOL).includes(VERCEL_DIR)) {
await writeFile(
gitIgnorePath,
gitIgnore
? `${gitIgnore}${EOL}${VERCEL_DIR}${EOL}`
: `${VERCEL_DIR}${EOL}`
);
if (!gitIgnore.split(EOL).includes(VERCEL_DIR)) {
gitIgnore += `${
gitIgnore.endsWith(EOL) || gitIgnore.length === 0 ? '' : EOL
}${VERCEL_DIR}${EOL}`;
contentModified = true;
}
if (!gitIgnore.split(EOL).includes(VERCEL_OUTPUT_DIR)) {
gitIgnore += `${
gitIgnore.endsWith(EOL) || gitIgnore.length === 0 ? '' : EOL
}${VERCEL_OUTPUT_DIR}${EOL}`;
contentModified = true;
}
if (contentModified) {
await writeFile(gitIgnorePath, gitIgnore);
isGitIgnoreUpdated = true;
}
} catch (error) {

View File

@@ -0,0 +1,42 @@
import { writeFile } from 'fs-extra';
import { Org, Project, ProjectLink } from '../../types';
import { getLinkFromDir, VERCEL_DIR, VERCEL_DIR_PROJECT } from './link';
import { join } from 'path';
export type ProjectLinkAndSettings = ProjectLink & {
settings: {
buildCommand: Project['buildCommand'];
devCommand: Project['devCommand'];
outputDirectory: Project['outputDirectory'];
rootDirectory: Project['rootDirectory'];
framework: Project['framework'];
};
};
// writeProjectSettings writes the project configuration to `vercel/project.json`
// Write the project configuration to `.vercel/project.json`
// that is needed for `vercel build` and `vercel dev` commands
export async function writeProjectSettings(
cwd: string,
project: Project,
org: Org
) {
return await writeFile(
join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT),
JSON.stringify({
projectId: project.id,
orgId: org.id,
settings: {
buildCommand: project.buildCommand,
devCommand: project.devCommand,
directoryListing: project.directoryListing,
rootDirectory: project.rootDirectory,
framework: project.framework,
},
})
);
}
export async function readProjectSettings(cwd: string) {
return await getLinkFromDir<ProjectLinkAndSettings>(cwd);
}

View File

@@ -27,7 +27,7 @@ export default async function reportError(
if (user) {
const spec = {
email: user.email,
id: user.uid,
id: user.id,
username: user.username,
name: (user as any).name,
};

View File

@@ -23,7 +23,7 @@ describe('inspect', () => {
client.setArgv('inspect', 'bad.com');
const exitCode = await inspect(client);
expect(exitCode).toEqual(1);
expect(client.mockOutput.mock.calls[0][0]).toEqual(
expect(client.outputBuffer).toEqual(
`Error! Failed to find deployment "bad.com" in ${user.username}\n`
);
});

View File

@@ -1,15 +1,25 @@
import { client } from '../mocks/client';
import login from '../../src/commands/login';
import { client } from '../mocks/client';
import { useUser } from '../mocks/user';
describe('login', () => {
it('should not allow the `--token` flag', async () => {
client.setArgv('login', '--token', 'foo');
const exitCode = await login(client);
expect(exitCode).toEqual(2);
expect(client.mockOutput.mock.calls.length).toEqual(1);
expect(client.outputBuffer).toEqual(
'Error! `--token` may not be used with the "login" command\n'
);
});
it('should allow login via email as argument', async () => {
const user = useUser();
client.setArgv('login', user.email);
const exitCode = await login(client);
expect(exitCode).toEqual(0);
expect(
client.mockOutput.mock.calls[0][0].includes(
'`--token` may not be used with the "login" command'
client.outputBuffer.includes(
`Success! Email authentication complete for ${user.email}`
)
).toEqual(true);
});

View File

@@ -0,0 +1,45 @@
import fs from 'fs-extra';
import path from 'path';
import pull from '../../src/commands/pull';
import { setupFixture } from '../helpers/setup-fixture';
import { client } from '../mocks/client';
import { defaultProject, useProject } from '../mocks/project';
import { useTeams } from '../mocks/team';
import { useUser } from '../mocks/user';
describe('pull', () => {
it('should handle pulling', async () => {
const cwd = setupFixture('vercel-pull-next');
useUser();
useTeams();
useProject({
...defaultProject,
id: 'vercel-pull-next',
name: 'vercel-pull-next',
});
client.setArgv('pull', '--yes', cwd);
const exitCode = await pull(client);
expect(exitCode).toEqual(0);
});
it('should handle custom --env flag', async () => {
const cwd = setupFixture('vercel-pull-next');
useUser();
useTeams();
useProject({
...defaultProject,
id: 'vercel-pull-next',
name: 'vercel-pull-next',
});
const expectedEnvFilename = '.env.vercel';
client.setArgv('pull', '--yes', `--env=${expectedEnvFilename}`, cwd);
const exitCode = await pull(client);
const actualEnv = await fs.pathExists(path.join(cwd, expectedEnvFilename));
const raw = await fs.readFile(path.join(cwd, expectedEnvFilename));
expect(exitCode).toEqual(0);
expect(actualEnv).toBeTruthy();
expect(raw.includes('# Created by Vercel CLI')).toBeTruthy();
});
});

View File

@@ -14,7 +14,14 @@ describe('whoami', () => {
const user = useUser();
const exitCode = await whoami(client);
expect(exitCode).toEqual(0);
expect(client.mockOutput.mock.calls.length).toEqual(1);
expect(client.mockOutput.mock.calls[0][0]).toEqual(`${user.username}\n`);
expect(client.outputBuffer).toEqual(`> ${user.username}\n`);
});
it('should print only the Vercel username when output is not a TTY', async () => {
const user = useUser();
client.output.isTTY = false;
const exitCode = await whoami(client);
expect(exitCode).toEqual(0);
expect(client.outputBuffer).toEqual(`${user.username}\n`);
});
});

View File

@@ -0,0 +1,3 @@
export default () => {
throw new Error('asdf');
};

View File

@@ -0,0 +1,3 @@
export default function () {
return 'freecandy';
}

View File

@@ -0,0 +1,5 @@
import { response } from './response';
export default () => {
return new Response(response);
};

View File

@@ -0,0 +1 @@
export const response = 'response';

View File

@@ -0,0 +1,10 @@
import response from './response.json';
export default function () {
return new Response(JSON.stringify(response), {
status: 200,
headers: {
'Content-Type': 'application/json',
},
});
}

View File

@@ -0,0 +1 @@
not hello world

View File

@@ -0,0 +1,3 @@
{
"text": "hello world"
}

View File

@@ -0,0 +1,69 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# dotenv environment variable files
.env*
# gatsby files
.cache/
public
# Mac files
.DS_Store
# Yarn
yarn-error.log
.pnp/
.pnp.js
# Yarn Integrity file
.yarn-integrity

View File

@@ -0,0 +1,4 @@
.cache
package.json
package-lock.json
public

View File

@@ -0,0 +1,7 @@
{
"endOfLine": "lf",
"semi": false,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5"
}

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 gatsbyjs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,97 @@
<!-- AUTO-GENERATED-CONTENT:START (STARTER) -->
<p align="center">
<a href="https://www.gatsbyjs.org">
<img alt="Gatsby" src="https://www.gatsbyjs.org/monogram.svg" width="60" />
</a>
</p>
<h1 align="center">
Gatsby's default starter
</h1>
Kick off your project with this default boilerplate. This starter ships with the main Gatsby configuration files you might need to get up and running blazing fast with the blazing fast app generator for React.
_Have another more specific idea? You may want to check out our vibrant collection of [official and community-created starters](https://www.gatsbyjs.org/docs/gatsby-starters/)._
## 🚀 Quick start
1. **Create a Gatsby site.**
Use the Gatsby CLI to create a new site, specifying the default starter.
```shell
# create a new Gatsby site using the default starter
gatsby new my-default-starter https://github.com/gatsbyjs/gatsby-starter-default
```
1. **Start developing.**
Navigate into your new sites directory and start it up.
```shell
cd my-default-starter/
gatsby develop
```
1. **Open the source code and start editing!**
Your site is now running at `http://localhost:8000`!
_Note: You'll also see a second link: _`http://localhost:8000/___graphql`_. This is a tool you can use to experiment with querying your data. Learn more about using this tool in the [Gatsby tutorial](https://www.gatsbyjs.org/tutorial/part-five/#introducing-graphiql)._
Open the `my-default-starter` directory in your code editor of choice and edit `src/pages/index.js`. Save your changes and the browser will update in real time!
## 🧐 What's inside?
A quick look at the top-level files and directories you'll see in a Gatsby project.
.
├── node_modules
├── src
├── .gitignore
├── .prettierrc
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├── gatsby-ssr.js
├── LICENSE
├── package-lock.json
├── package.json
└── README.md
1. **`/node_modules`**: This directory contains all of the modules of code that your project depends on (npm packages) are automatically installed.
2. **`/src`**: This directory will contain all of the code related to what you will see on the front-end of your site (what you see in the browser) such as your site header or a page template. `src` is a convention for “source code”.
3. **`.gitignore`**: This file tells git which files it should not track / not maintain a version history for.
4. **`.prettierrc`**: This is a configuration file for [Prettier](https://prettier.io/). Prettier is a tool to help keep the formatting of your code consistent.
5. **`gatsby-browser.js`**: This file is where Gatsby expects to find any usage of the [Gatsby browser APIs](https://www.gatsbyjs.org/docs/browser-apis/) (if any). These allow customization/extension of default Gatsby settings affecting the browser.
6. **`gatsby-config.js`**: This is the main configuration file for a Gatsby site. This is where you can specify information about your site (metadata) like the site title and description, which Gatsby plugins youd like to include, etc. (Check out the [config docs](https://www.gatsbyjs.org/docs/gatsby-config/) for more detail).
7. **`gatsby-node.js`**: This file is where Gatsby expects to find any usage of the [Gatsby Node APIs](https://www.gatsbyjs.org/docs/node-apis/) (if any). These allow customization/extension of default Gatsby settings affecting pieces of the site build process.
8. **`gatsby-ssr.js`**: This file is where Gatsby expects to find any usage of the [Gatsby server-side rendering APIs](https://www.gatsbyjs.org/docs/ssr-apis/) (if any). These allow customization of default Gatsby settings affecting server-side rendering.
9. **`LICENSE`**: Gatsby is licensed under the MIT license.
10. **`package-lock.json`** (See `package.json` below, first). This is an automatically generated file based on the exact versions of your npm dependencies that were installed for your project. **(You wont change this file directly).**
11. **`package.json`**: A manifest file for Node.js projects, which includes things like metadata (the projects name, author, etc). This manifest is how npm knows which packages to install for your project.
12. **`README.md`**: A text file containing useful reference information about your project.
## 🎓 Learning Gatsby
Looking for more guidance? Full documentation for Gatsby lives [on the website](https://www.gatsbyjs.org/). Here are some places to start:
- **For most developers, we recommend starting with our [in-depth tutorial for creating a site with Gatsby](https://www.gatsbyjs.org/tutorial/).** It starts with zero assumptions about your level of ability and walks through every step of the process.
- **To dive straight into code samples, head [to our documentation](https://www.gatsbyjs.org/docs/).** In particular, check out the _Guides_, _API Reference_, and _Advanced Tutorials_ sections in the sidebar.
## 💫 Deploy
[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/gatsbyjs/gatsby-starter-default)
<!-- AUTO-GENERATED-CONTENT:END -->

View File

@@ -0,0 +1,7 @@
/**
* Implement Gatsby's Browser APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/browser-apis/
*/
// You can delete this file if you're not using it

View File

@@ -0,0 +1,34 @@
module.exports = {
siteMetadata: {
title: `Gatsby Default Starter`,
description: `Kick off your next, great Gatsby project with this default starter. This barebones starter ships with the main Gatsby configuration files you might need.`,
author: `@gatsbyjs`,
},
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `05-zero-config-gatsby`,
short_name: `starter`,
start_url: `/`,
background_color: `#663399`,
theme_color: `#663399`,
display: `minimal-ui`,
icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
},
},
// this (optional) plugin enables Progressive Web App + Offline functionality
// To learn more, visit: https://gatsby.dev/offline
// `gatsby-plugin-offline`,
],
}

View File

@@ -0,0 +1,7 @@
/**
* Implement Gatsby's Node APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/node-apis/
*/
// You can delete this file if you're not using it

View File

@@ -0,0 +1,7 @@
/**
* Implement Gatsby's SSR (Server Side Rendering) APIs in this file.
*
* See: https://www.gatsbyjs.org/docs/ssr-apis/
*/
// You can delete this file if you're not using it

View File

@@ -0,0 +1,43 @@
{
"name": "vercel-build-gatsby",
"private": true,
"description": "A simple starter to get up and developing quickly with Gatsby",
"version": "0.1.0",
"author": "Kyle Mathews <mathews.kyle@gmail.com>",
"dependencies": {
"gatsby": "^2.17.6",
"gatsby-image": "^2.2.30",
"gatsby-plugin-manifest": "^2.2.25",
"gatsby-plugin-offline": "^3.0.17",
"gatsby-plugin-react-helmet": "^3.1.13",
"gatsby-plugin-sharp": "^2.2.34",
"gatsby-source-filesystem": "^2.1.35",
"gatsby-transformer-sharp": "^2.3.1",
"prop-types": "^15.7.2",
"react": "^16.11.0",
"react-dom": "^16.11.0",
"react-helmet": "^5.2.1"
},
"devDependencies": {
"prettier": "^1.18.2"
},
"keywords": [
"gatsby"
],
"license": "MIT",
"scripts": {
"build": "gatsby build",
"develop": "gatsby develop",
"format": "prettier --write \"**/*.{js,jsx,json,md}\"",
"start": "npm run develop",
"serve": "gatsby serve",
"test": "echo \"Write tests! -> https://gatsby.dev/unit-testing\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/gatsbyjs/gatsby-starter-default"
},
"bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues"
}
}

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