Compare commits

...

24 Commits

Author SHA1 Message Date
Nathan Rajlich
f2d396caae Publish Stable
- @vercel/build-utils@2.11.0
 - vercel@23.0.0
 - @vercel/client@10.1.0
 - @vercel/frameworks@0.4.0
 - @vercel/node@1.11.0
 - @vercel/python@2.0.3
 - @vercel/routing-utils@1.11.1
2021-05-25 14:56:11 -07:00
Matheus Fernandes
001f2f60b8 Use proper Apache License format (#6189)
The existing LICENSE file was missing the Appendix, and also
used weird formatting. Now it's an exact copy of the original:

https://www.apache.org/licenses/LICENSE-2.0.txt.
2021-05-25 13:27:32 -07:00
Nathan Rajlich
78ca930287 [cli] Show user's name in vc switch command (#6288)
This more closely matches the Team picker on vercel.com.

Will still show "email" if no "name" is defined.
2021-05-25 13:18:14 -07:00
Nathan Rajlich
b03e18df12 Publish Canary
- vercel@22.0.2-canary.7
 - @vercel/python@2.0.3-canary.0
2021-05-25 11:07:16 -07:00
Nathan Rajlich
3a6b8b072c [cli] Reauthenticate scopes with limited access in vc switch (#6280)
In the `vc switch` command, if your current access token results in
"limited" Team information being returned, then show a lock emoji
next to the team/user name in the select input.

When a locked scope is selected, then pre-emptively prompt the
user to re-authenticate using a valid login method in relation to
the desired scope.

https://user-images.githubusercontent.com/71256/119441172-87abae80-bcda-11eb-801a-cb6837bae353.mov

[ch21964]
2021-05-25 11:03:06 -07:00
Steven
d480cd6bbd [cli] Bump codecov to 3.8.2 (#6279)
Closes #5814
2021-05-24 23:16:02 +00:00
Nathan Rajlich
181b624bf4 [cli] Add SAML reauthentication logic when using different scope (#6263)
When the API returns a SAML error, then show the proper reauthentication prompt depending on the scope being requested:

Team with SAML enforced, shows only SSO login option:

<img width="476" alt="Screen Shot 2021-05-24 at 1 50 29 PM" src="https://user-images.githubusercontent.com/71256/119406131-31694c00-bc97-11eb-858a-52e5fe7052d1.png">

Team with SAML enabled, but not enforced, prompts with all login methods:

<img width="352" alt="Screen Shot 2021-05-24 at 1 50 36 PM" src="https://user-images.githubusercontent.com/71256/119406134-3201e280-bc97-11eb-9166-60fbfec47ee0.png">

Team without SAML enabled, or User scope, shows prompt with SSO option removed:

<img width="366" alt="Screen Shot 2021-05-24 at 1 50 44 PM" src="https://user-images.githubusercontent.com/71256/119406137-3201e280-bc97-11eb-8c5c-b88eb9983500.png">

[ch21964]
2021-05-24 15:16:24 -07:00
Nathan Rajlich
200495e4ce [cli] Use ts-eager to execute build script (#6278)
* [cli] Use `ts-eager` to execute build script

* Use `node -r ts-eager/register` to workaround Windows issue
2021-05-24 18:14:55 -04:00
Steven
9178f14c40 Publish Stable
- @vercel/python@2.0.2
2021-05-24 16:46:49 -04:00
Nathan Rajlich
9a790f5352 [cli] Set tokenName query param for Git provider login methods (#6277)
We're not currently setting the `tokenName` when logging in via a
Git provider, so the name becomes the default "Website" one which
is confusing / incorrect.
2021-05-24 13:38:55 -07:00
Steven
33d8be7f8f [cli] Fix vc logout retry (#6276)
* [cli] Fix `vc logout` retry

* Fix logout message
2021-05-24 16:26:01 -04:00
JJ Kasper
82aa86b786 Apply dependabot changes (#6275)
* Bump elliptic in /packages/cli/test/dev/fixtures/02-angular-node

Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump node-fetch from 2.6.0 to 2.6.1 in /api

Bumps [node-fetch](https://github.com/bitinn/node-fetch) from 2.6.0 to 2.6.1.
- [Release notes](https://github.com/bitinn/node-fetch/releases)
- [Changelog](https://github.com/node-fetch/node-fetch/blob/master/docs/CHANGELOG.md)
- [Commits](https://github.com/bitinn/node-fetch/compare/v2.6.0...v2.6.1)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ssri from 6.0.1 to 6.0.2 in /examples/blitzjs

Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump hosted-git-info from 2.8.8 to 2.8.9 in /examples/angular

Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump hosted-git-info from 2.8.8 to 2.8.9 in /examples/blitzjs

Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ssri in /packages/cli/test/dev/fixtures/02-angular-node

Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ssri in /packages/cli/test/dev/fixtures/04-create-react-app

Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ssri in /packages/cli/test/dev/fixtures/03-aurelia

Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/npm/ssri/releases)
- [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md)
- [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump hosted-git-info in /packages/cli/test/dev/fixtures/02-angular-node

Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump url-parse in /packages/cli/test/dev/fixtures/04-create-react-app

Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.4.7 to 1.5.1.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.4.7...1.5.1)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump url-parse in /packages/cli/test/dev/fixtures/03-aurelia

Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.4.7 to 1.5.1.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.4.7...1.5.1)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump handlebars in /packages/cli/test/dev/fixtures/02-angular-node

Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.7.6 to 4.7.7.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.7.6...v4.7.7)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump lodash in /packages/cli/test/dev/fixtures/02-angular-node

Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump hosted-git-info in /packages/cli/test/dev/fixtures/03-aurelia

Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump hosted-git-info

Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump lodash in /packages/cli/test/dev/fixtures/03-aurelia

Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

* Bump url-parse in /packages/cli/test/dev/fixtures/02-angular-node

Bumps [url-parse](https://github.com/unshiftio/url-parse) from 1.4.7 to 1.5.1.
- [Release notes](https://github.com/unshiftio/url-parse/releases)
- [Commits](https://github.com/unshiftio/url-parse/compare/1.4.7...1.5.1)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Steven <steven@ceriously.com>
2021-05-24 15:49:31 -04:00
Steven
6288d5ef43 Publish Canary
- vercel@22.0.2-canary.6
 - @vercel/client@10.0.1-canary.5
 - @vercel/node@1.10.1-canary.2
 - @vercel/python@2.0.2-canary.0
2021-05-24 13:37:57 -04:00
Steven
00a97b7ae2 [node] Bump nft to 0.12.2 (#6274) 2021-05-24 13:34:28 -04:00
Steven
a19fb3aa0f [python] Fix installRequirement to use explicit version (#6272)
* [python] Fix installRequirement to use explicit version

* Remove `--upgrade`
2021-05-24 11:41:57 -04:00
Nathan Rajlich
93fae76f9c [cli] Simplify emoji module (#6260) 2021-05-21 13:53:13 -07:00
Nathan Rajlich
e5131d5557 [cli] Update NowConfig references to VercelConfig (#6256)
The `NowConfig` interface is deprecated.
2021-05-21 12:21:38 -07:00
Nathan Rajlich
930063638c [cli] Refactor vc logs command (#6259) 2021-05-21 11:36:58 -07:00
Nathan Rajlich
7b509ae672 [cli] Refactor vc switch command (#6257)
Refactors the `vc switch` command to more closely match how the team picker works on the Vercel dashboard:

 * Converts to TypeScript
 * Adds separator between user scope and team scopes
 * Sorts teams by name
 * No longer places the current scope at the top of the list (but the current scope is still selected by default)
2021-05-20 11:19:38 -07:00
Nathan Rajlich
711da37771 [cli] Refactor vc inspect command (#6258) 2021-05-20 10:30:33 -07:00
Steven
5e50b96994 Publish Canary
- vercel@22.0.2-canary.5
 - @vercel/node@1.10.1-canary.1
2021-05-13 16:40:36 -04:00
Steven
35d2f5950f [node] Bump nft to 0.12.0 (#6229) 2021-05-13 16:22:58 -04:00
Steven
37f969416c Publish Canary
- @vercel/build-utils@2.10.3-canary.4
 - vercel@22.0.2-canary.4
 - @vercel/client@10.0.1-canary.4
 - @vercel/node@1.10.1-canary.0
2021-05-10 14:01:41 -04:00
Steven
75630e0982 [node] Bump nft to 0.11.2 (#6211)
* [node] Bump nft to 0.11.2

* Fix tests since node 10.x is discontinued
2021-05-10 14:01:02 -04:00
77 changed files with 1246 additions and 1066 deletions

332
LICENSE
View File

@@ -1,190 +1,202 @@
Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
1. Definitions.
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
1. Definitions.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
END OF TERMS AND CONDITIONS
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
Copyright 2017 Vercel, Inc.
END OF TERMS AND CONDITIONS
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
APPENDIX: How to apply the Apache License to your work.
https://www.apache.org/licenses/LICENSE-2.0
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Copyright 2017 Vercel, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -10,7 +10,7 @@
"dependencies": {
"@sentry/node": "5.11.1",
"got": "10.2.1",
"node-fetch": "2.6.0",
"node-fetch": "2.6.1",
"parse-github-url": "1.0.2",
"tar-fs": "2.0.0",
"unzip-stream": "0.3.0"

View File

@@ -362,10 +362,10 @@ ms@^2.1.1:
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
node-fetch@2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-fetch@2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
normalize-url@^4.1.0:
version "4.5.0"

View File

@@ -3073,9 +3073,9 @@ hmac-drbg@^1.0.1:
minimalistic-crypto-utils "^1.0.1"
hosted-git-info@^2.1.4, hosted-git-info@^2.6.0, hosted-git-info@^2.7.1:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
hpack.js@^2.1.6:
version "2.1.6"

View File

@@ -4681,9 +4681,9 @@ hmac-drbg@^1.0.1:
minimalistic-crypto-utils "^1.0.1"
hosted-git-info@^2.1.4:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
hsl-regex@^1.0.0:
version "1.0.0"
@@ -8195,9 +8195,9 @@ sprintf-js@~1.0.2:
integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
ssri@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
version "6.0.2"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
dependencies:
figgy-pudding "^3.5.1"

View File

@@ -2,7 +2,7 @@
"name": "vercel-monorepo",
"version": "0.0.0",
"private": true,
"license": "MIT",
"license": "Apache-2.0",
"workspaces": {
"packages": [
"packages/*"

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/build-utils",
"version": "2.10.3-canary.3",
"version": "2.11.0",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",
@@ -29,7 +29,7 @@
"@types/node-fetch": "^2.1.6",
"@types/semver": "6.0.0",
"@types/yazl": "^2.4.1",
"@vercel/frameworks": "0.3.3-canary.3",
"@vercel/frameworks": "0.4.0",
"@vercel/ncc": "0.24.0",
"aggregate-error": "3.0.1",
"async-retry": "1.2.3",

View File

@@ -1 +0,0 @@
declare module 'inquirer';

View File

@@ -0,0 +1,5 @@
declare module 'jsonlines' {
import { Transform } from 'stream';
function parse(): Transform;
}

View File

@@ -1,6 +1,6 @@
{
"name": "vercel",
"version": "22.0.2-canary.3",
"version": "23.0.0",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Vercel",
@@ -17,8 +17,8 @@
"test-integration-dev": "ava test/dev/integration.js --serial --fail-fast --verbose",
"prepublishOnly": "yarn build",
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
"build": "ts-node ./scripts/build.ts",
"build-dev": "ts-node ./scripts/build.ts --dev"
"build": "node -r ts-eager/register ./scripts/build.ts",
"build-dev": "node -r ts-eager/register ./scripts/build.ts --dev"
},
"nyc": {
"include": [
@@ -61,10 +61,10 @@
"node": ">= 12"
},
"dependencies": {
"@vercel/build-utils": "2.10.3-canary.3",
"@vercel/build-utils": "2.11.0",
"@vercel/go": "1.2.2",
"@vercel/node": "1.10.0",
"@vercel/python": "2.0.1",
"@vercel/node": "1.11.0",
"@vercel/python": "2.0.3",
"@vercel/ruby": "1.2.6",
"update-notifier": "4.1.0"
},
@@ -82,13 +82,14 @@
"@types/fs-extra": "5.0.5",
"@types/glob": "7.1.1",
"@types/http-proxy": "1.16.2",
"@types/inquirer": "7.3.1",
"@types/load-json-file": "2.0.7",
"@types/mime-types": "2.1.0",
"@types/minimatch": "3.0.3",
"@types/mri": "1.1.0",
"@types/ms": "0.7.30",
"@types/node": "11.11.0",
"@types/node-fetch": "2.1.4",
"@types/node-fetch": "2.5.10",
"@types/npm-package-arg": "6.1.0",
"@types/pluralize": "0.0.29",
"@types/progress": "2.0.3",
@@ -99,7 +100,7 @@
"@types/universal-analytics": "0.4.2",
"@types/which": "1.3.2",
"@types/write-json-file": "2.2.1",
"@vercel/frameworks": "0.3.3-canary.3",
"@vercel/frameworks": "0.4.0",
"@vercel/ncc": "0.24.0",
"@zeit/fun": "0.11.2",
"@zeit/source-map-support": "0.6.2",
@@ -116,7 +117,7 @@
"chalk": "4.1.0",
"chokidar": "3.3.1",
"clipboardy": "2.1.0",
"codecov": "3.7.1",
"codecov": "3.8.2",
"cpy": "7.2.0",
"credit-card": "3.0.1",
"date-fns": "1.29.0",
@@ -168,6 +169,7 @@
"title": "3.4.1",
"tmp-promise": "1.0.3",
"tree-kill": "1.2.2",
"ts-eager": "2.0.2",
"ts-node": "8.3.0",
"typescript": "3.9.3",
"universal-analytics": "0.4.20",

View File

@@ -19,7 +19,7 @@ import link from '../../util/output/link';
import { User } from '../../types';
import { getCommandName } from '../../util/pkg-name';
import toHost from '../../util/to-host';
import { NowConfig } from '../../util/dev/types';
import { VercelConfig } from '../../util/dev/types';
type Options = {
'--debug': boolean;
@@ -421,7 +421,7 @@ function handleCreateAliasError<T>(
return error;
}
function getTargetsForAlias(args: string[], { alias }: NowConfig) {
function getTargetsForAlias(args: string[], { alias }: VercelConfig) {
if (args.length) {
return [args[args.length - 1]]
.map(target => (target.indexOf('.') !== -1 ? toHost(target) : target))

View File

@@ -111,7 +111,6 @@ async function chooseFromDropdown(message: string, exampleList: string[]) {
return listInput({
message,
separator: false,
choices,
});
}

View File

@@ -3,12 +3,14 @@ import getArgs from '../util/get-args';
import buildsList from '../util/output/builds';
import routesList from '../util/output/routes';
import indent from '../util/output/indent';
import Now from '../util';
import logo from '../util/output/logo';
import elapsed from '../util/output/elapsed.ts';
import elapsed from '../util/output/elapsed';
import { handleError } from '../util/error';
import getScope from '../util/get-scope.ts';
import { getPkgName, getCommandName } from '../util/pkg-name.ts';
import getScope from '../util/get-scope';
import { getPkgName, getCommandName } from '../util/pkg-name';
import Client from '../util/client';
import { getDeployment } from '../util/get-deployment';
import { Deployment } from '@vercel/client';
const help = () => {
console.log(`
@@ -33,15 +35,15 @@ const help = () => {
${chalk.gray('')} Get information about a deployment by its unique URL
${chalk.cyan(`$ ${getPkgName()} inspect my-deployment-ji2fjij2.now.sh`)}
${chalk.cyan(`$ ${getPkgName()} inspect my-deployment-ji2fjij2.vercel.app`)}
${chalk.gray('-')} Get information about the deployment an alias points to
${chalk.cyan(`$ ${getPkgName()} inspect my-deployment.now.sh`)}
${chalk.cyan(`$ ${getPkgName()} inspect my-deployment.vercel.app`)}
`);
};
export default async function main(client) {
export default async function main(client: Client) {
let deployment;
let argv;
@@ -57,14 +59,7 @@ export default async function main(client) {
return 2;
}
const {
apiUrl,
output,
authConfig: { token },
config,
} = client;
const debugEnabled = argv['--debug'];
const { print, log, error } = output;
const { print, log, error } = client.output;
// extract the first parameter
const [, deploymentIdOrHost] = argv._;
@@ -75,9 +70,7 @@ export default async function main(client) {
return 1;
}
const { currentTeam } = config;
let contextName = null;
let contextName: string | null = null;
try {
({ contextName } = await getScope(client));
@@ -90,22 +83,14 @@ export default async function main(client) {
throw err;
}
const now = new Now({
apiUrl,
token,
debug: debugEnabled,
currentTeam,
output,
});
// resolve the deployment, since we might have been given an alias
const depFetchStart = Date.now();
output.spinner(
client.output.spinner(
`Fetching deployment "${deploymentIdOrHost}" in ${chalk.bold(contextName)}`
);
try {
deployment = await now.findDeployment(deploymentIdOrHost);
deployment = await getDeployment(client, deploymentIdOrHost);
} catch (err) {
if (err.status === 404) {
error(
@@ -127,11 +112,11 @@ export default async function main(client) {
throw err;
}
const { id, name, url, created, routes, readyState } = deployment;
const { id, name, url, createdAt, routes, readyState } = deployment;
const { builds } =
deployment.version === 2
? await now.fetch(`/v1/now/deployments/${id}/builds`)
? await client.fetch(`/v1/now/deployments/${id}/builds`)
: { builds: [] };
log(
@@ -146,10 +131,10 @@ export default async function main(client) {
print(` ${chalk.cyan('name')}\t${name}\n`);
print(` ${chalk.cyan('readyState')}\t${stateString(readyState)}\n`);
print(` ${chalk.cyan('url')}\t\t${url}\n`);
if (created) {
if (createdAt) {
print(
` ${chalk.cyan('createdAt')}\t${new Date(created)} ${elapsed(
Date.now() - created,
` ${chalk.cyan('createdAt')}\t${new Date(createdAt)} ${elapsed(
Date.now() - createdAt,
true
)}\n`
);
@@ -157,7 +142,7 @@ export default async function main(client) {
print('\n\n');
if (builds.length > 0) {
const times = {};
const times: { [id: string]: string | null } = {};
for (const build of builds) {
const { id, createdAt, readyStateAt } = build;
@@ -179,7 +164,7 @@ export default async function main(client) {
}
// renders the state string
function stateString(s) {
function stateString(s: Deployment['readyState']) {
switch (s) {
case 'INITIALIZING':
return chalk.yellow(s);

View File

@@ -73,9 +73,9 @@ export default async function login(client: Client): Promise<number> {
if (input) {
// Email or Team slug was provided via command line
if (validateEmail(input)) {
result = await doEmailLogin(input, params);
result = await doEmailLogin(params, input);
} else {
result = await doSsoLogin(input, params);
result = await doSsoLogin(params, input);
}
} else {
// Interactive mode

View File

@@ -1,5 +1,4 @@
import chalk from 'chalk';
import fetch from 'node-fetch';
import logo from '../util/output/logo';
// @ts-ignore
import { handleError } from '../util/error';
@@ -48,10 +47,9 @@ export default async function main(client: Client): Promise<number> {
return 2;
}
const { authConfig, config, apiUrl, output } = client;
const { token } = authConfig;
const { authConfig, config, output } = client;
if (!token) {
if (!authConfig.token) {
output.note(
`Not currently logged in, so ${getCommandName('logout')} did nothing`
);
@@ -59,6 +57,20 @@ export default async function main(client: Client): Promise<number> {
}
output.spinner('Logging out…', 200);
let exitCode = 0;
try {
await client.fetch(`/v3/user/tokens/current`, {
method: 'DELETE',
});
} catch (err) {
if (err.status === 403) {
output.debug('Token is invalid so it cannot be revoked');
} else if (err.status !== 200) {
output.debug(err?.message ?? '');
exitCode = 1;
}
}
delete config.currentTeam;
@@ -75,26 +87,15 @@ export default async function main(client: Client): Promise<number> {
writeToAuthConfigFile(authConfig);
output.debug('Configuration has been deleted');
} catch (err) {
output.error(`Couldn't remove config while logging out`);
return 1;
output.debug(err?.message ?? '');
exitCode = 1;
}
const res = await fetch(`${apiUrl}/v3/user/tokens/current`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${token}`,
},
});
if (res.status === 403) {
output.debug('Token is invalid so it cannot be revoked');
} else if (res.status !== 200) {
const err = await res.json();
output.error('Failed to revoke token');
output.debug(err ? err.message : '');
return 1;
if (exitCode === 0) {
output.log('Logged out!');
} else {
output.error(`Failed during logout`);
}
output.log('Logged out!');
return 0;
return exitCode;
}

View File

@@ -1,13 +1,13 @@
import chalk from 'chalk';
import Now from '../util';
import logo from '../util/output/logo';
import elapsed from '../util/output/elapsed.ts';
import elapsed from '../util/output/elapsed';
import { maybeURL, normalizeURL } from '../util/url';
import printEvents from '../util/events';
import getScope from '../util/get-scope.ts';
import { getPkgName } from '../util/pkg-name.ts';
import getArgs from '../util/get-args.ts';
import handleError from '../util/handle-error.ts';
import printEvents, { DeploymentEvent } from '../util/events';
import getScope from '../util/get-scope';
import { getPkgName } from '../util/pkg-name';
import getArgs from '../util/get-args';
import Client from '../util/client';
import { getDeployment } from '../util/get-deployment';
const help = () => {
console.log(`
@@ -53,35 +53,25 @@ const help = () => {
`);
};
export default async function main(client) {
let argv;
let deploymentIdOrURL;
let debug;
export default async function main(client: Client) {
let head;
let limit;
let follow;
let outputMode;
let since;
let until;
let deploymentIdOrURL;
try {
argv = getArgs(client.argv.slice(2), {
'--since': String,
'--until': String,
'--output': String,
'--limit': Number,
'--head': Boolean,
'--follow': Boolean,
'-f': '--follow',
'-o': '--output',
'-n': '--limit',
});
} catch (error) {
handleError(error);
return 1;
}
const argv = getArgs(client.argv.slice(2), {
'--since': String,
'--until': String,
'--output': String,
'--limit': Number,
'--head': Boolean,
'--follow': Boolean,
'-f': '--follow',
'-o': '--output',
'-n': '--limit',
});
argv._ = argv._.slice(1);
deploymentIdOrURL = argv._[0];
@@ -91,12 +81,7 @@ export default async function main(client) {
return 2;
}
const {
authConfig: { token },
apiUrl,
output,
config,
} = client;
const { output } = client;
try {
since = argv['--since'] ? toTimestamp(argv['--since']) : 0;
@@ -124,40 +109,24 @@ export default async function main(client) {
deploymentIdOrURL = normalizedURL;
}
debug = argv['--debug'];
head = argv['--head'];
limit = argv['--limit'] || 100;
follow = argv['--follow'];
if (follow) until = 0;
outputMode = argv['--output'] in logPrinters ? argv['--output'] : 'short';
const logPrinter = getLogPrinter(argv['--output'], 'short');
const { currentTeam } = config;
const now = new Now({ apiUrl, token, debug, currentTeam, output });
let contextName = null;
const { contextName } = await getScope(client);
try {
({ contextName } = await getScope(client));
} catch (err) {
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
output.error(err.message);
return 1;
}
throw err;
}
let deployment;
const id = deploymentIdOrURL;
const depFetchStart = Date.now();
output.spinner(`Fetching deployment "${id}" in ${chalk.bold(contextName)}`);
let deployment;
try {
deployment = await now.findDeployment(id);
deployment = await getDeployment(client, id);
} catch (err) {
output.stopSpinner();
now.close();
if (err.status === 404) {
output.error(
@@ -183,31 +152,28 @@ export default async function main(client) {
)} ${elapsed(Date.now() - depFetchStart)}`
);
let direction = head ? 'forward' : 'backward';
if (since && !until) direction = 'forward';
const findOpts1 = {
direction,
limit,
since,
until,
}; // no follow
const storage = [];
const storeEvent = event => storage.push(event);
const storage: DeploymentEvent[] = [];
await printEvents(now, deployment.uid || deployment.id, currentTeam, {
let direction = head ? ('forward' as const) : ('backward' as const);
if (since && !until) direction = 'forward';
await printEvents(client, deployment.id, {
mode: 'logs',
onEvent: storeEvent,
onEvent: event => storage.push(event),
quiet: false,
debug,
findOpts: findOpts1,
output,
findOpts: {
direction,
limit,
since,
until,
},
});
const printedEventIds = new Set();
const printEvent = event => {
const printedEventIds = new Set<string>();
const printEvent = (event: DeploymentEvent) => {
if (printedEventIds.has(event.id)) return 0;
printedEventIds.add(event.id);
return logPrinters[outputMode](event);
return logPrinter(event);
};
storage.sort(compareEvents).forEach(printEvent);
@@ -216,26 +182,22 @@ export default async function main(client) {
// NOTE: the API ignores `since` on follow mode.
// (but not sure if it's always true on legacy deployments)
const since2 = lastEvent ? lastEvent.date : Date.now();
const findOpts2 = {
direction: 'forward',
since: since2,
follow: true,
};
await printEvents(now, deployment.uid || deployment.id, currentTeam, {
await printEvents(client, deployment.id, {
mode: 'logs',
onEvent: printEvent,
quiet: false,
debug,
findOpts: findOpts2,
output,
findOpts: {
direction: 'forward',
since: since2,
follow: true,
},
});
}
now.close();
return 0;
}
function compareEvents(d1, d2) {
function compareEvents(d1: DeploymentEvent, d2: DeploymentEvent) {
const c1 = d1.date || d1.created;
const c2 = d2.date || d2.created;
if (c1 !== c2) return c1 - c2;
@@ -246,10 +208,10 @@ function compareEvents(d1, d2) {
return d1.created - d2.created; // if date are equal and no serial
}
function printLogShort(log) {
function printLogShort(log: any) {
if (!log.created) return; // keepalive
let data;
let data: string;
const obj = log.object;
if (log.type === 'request') {
data =
@@ -315,7 +277,7 @@ function printLogShort(log) {
return 0;
}
function printLogRaw(log) {
function printLogRaw(log: any) {
if (!log.created) return; // keepalive
if (log.object) {
@@ -340,7 +302,27 @@ const logPrinters = {
raw: printLogRaw,
};
function toTimestamp(datestr) {
type OutputMode = keyof typeof logPrinters;
const isLogPrinter = (v: any): v is OutputMode => {
return v && v in logPrinters;
};
const getLogPrinter = (mode: string | undefined, def: OutputMode) => {
if (mode) {
if (isLogPrinter(mode)) {
return logPrinters[mode];
}
throw new TypeError(
`Invalid output mode "${mode}". Must be one of: ${Object.keys(
logPrinters
).join(', ')}`
);
}
return logPrinters[def];
};
function toTimestamp(datestr: string) {
const t = Date.parse(datestr);
if (isNaN(t)) {
throw new TypeError('Invalid date string');

View File

@@ -115,8 +115,6 @@ export default async function main(client) {
try {
({ contextName } = await getScope(client));
} catch (err) {
client.close();
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
output.error(err.message);
return 1;
@@ -210,7 +208,6 @@ export default async function main(client) {
.map(id => chalk.bold(`"${id}"`))
.join(', ')}. Run ${getCommandName('ls')} to list.`
);
client.close();
return 1;
}
@@ -233,7 +230,6 @@ export default async function main(client) {
if (confirmation !== 'y' && confirmation !== 'yes') {
output.log('Aborted');
client.close();
return 1;
}
}
@@ -265,7 +261,6 @@ export default async function main(client) {
console.log(`${chalk.gray('-')} ${chalk.bold(project.name)}`);
});
client.close();
return 0;
}

View File

@@ -1,14 +1,15 @@
import chalk from 'chalk';
import error from '../util/output/error';
import NowTeams from '../util/teams';
import logo from '../util/output/logo';
import list from './teams/list';
import add from './teams/add';
import change from './teams/switch';
import invite from './teams/invite';
import { getPkgName } from '../util/pkg-name.ts';
import getArgs from '../util/get-args.ts';
import handleError from '../util/handle-error.ts';
import error from '../../util/output/error';
import NowTeams from '../../util/teams';
import logo from '../../util/output/logo';
import list from './list';
import add from './add';
import change from './switch';
import invite from './invite';
import { getPkgName } from '../../util/pkg-name';
import getArgs from '../../util/get-args';
import handleError from '../../util/handle-error';
import Client from '../../util/client';
const help = () => {
console.log(`
@@ -65,7 +66,7 @@ let debug;
let apiUrl;
let subcommand;
const main = async client => {
export default async (client: Client) => {
try {
argv = getArgs(client.argv.slice(2), {
'--since': String,
@@ -113,7 +114,7 @@ const main = async client => {
}
case 'switch':
case 'change': {
exitCode = await change(client, argv);
exitCode = await change(client, argv._[0]);
break;
}
case 'add':
@@ -139,13 +140,3 @@ const main = async client => {
teams.close();
return exitCode || 0;
};
export default async client => {
try {
return await main(client);
} catch (err) {
console.error(err);
handleError(err);
return 1;
}
};

View File

@@ -1,190 +0,0 @@
// Packages
import chalk from 'chalk';
// Utilities
import listInput from '../../util/input/list';
import success from '../../util/output/success';
import info from '../../util/output/info';
import error from '../../util/output/error';
import param from '../../util/output/param.ts';
import { writeToConfigFile } from '../../util/config/files';
import getUser from '../../util/get-user.ts';
import NowTeams from '../../util/teams';
const updateCurrentTeam = (config, newTeam) => {
if (newTeam) {
config.currentTeam = newTeam.id;
} else {
delete config.currentTeam;
}
writeToConfigFile(config);
};
export default async function change(client, argv) {
const {
apiUrl,
authConfig: { token },
debug,
config,
output,
} = client;
output.spinner('Fetching teams');
// We're loading the teams here without `currentTeam`, so that
// people can use `vercel switch` in the case that their
// current team was deleted.
const teams = new NowTeams({ apiUrl, token, debug, output });
const list = (await teams.ls()).teams;
let { currentTeam } = config;
const accountIsCurrent = !currentTeam;
output.spinner('Fetching user information');
let user;
try {
user = await getUser(client);
} catch (err) {
if (err.code === 'NOT_AUTHORIZED' || err.code === 'TEAM_DELETED') {
output.error(err.message);
return 1;
}
throw err;
}
if (accountIsCurrent) {
currentTeam = {
slug: user.username || user.email,
};
} else {
currentTeam = list.find(team => team.id === currentTeam);
if (!currentTeam) {
output.error(`You are not a part of the current team anymore`);
return 1;
}
}
if (argv._.length !== 0) {
const desiredSlug = argv._[0];
const newTeam = list.find(team => team.slug === desiredSlug);
if (newTeam) {
updateCurrentTeam(config, newTeam);
console.log(
success(
`The team ${chalk.bold(newTeam.name)} (${
newTeam.slug
}) is now active!`
)
);
return 0;
}
if (desiredSlug === user.username) {
output.spinner('Saving');
updateCurrentTeam(config);
output.stopSpinner();
console.log(
success(`Your account (${chalk.bold(desiredSlug)}) is now active!`)
);
return 0;
}
console.error(
error(`Could not find membership for team ${param(desiredSlug)}`)
);
return 1;
}
const choices = list.map(({ id, slug, name }) => {
name = `${slug} (${name})`;
if (id === currentTeam.id) {
name += ` ${chalk.bold('(current)')}`;
}
return {
name,
value: slug,
short: slug,
};
});
const suffix = accountIsCurrent ? ` ${chalk.bold('(current)')}` : '';
const userEntryName = user.username
? `${user.username} (${user.email})${suffix}`
: user.email;
choices.unshift({
name: userEntryName,
value: user.email,
short: user.username,
});
// Let's bring the current team to the beginning of the list
if (!accountIsCurrent) {
const index = choices.findIndex(
choice => choice.value === currentTeam.slug
);
const choice = choices.splice(index, 1)[0];
choices.unshift(choice);
}
output.stopSpinner();
let message;
if (currentTeam) {
message = `Switch to:`;
}
const choice = await listInput({
message,
choices,
separator: false,
eraseFinalAnswer: true,
});
// Abort
if (!choice) {
console.log(info('No changes made'));
return 0;
}
const newTeam = list.find(item => item.slug === choice);
// Switch to account
if (!newTeam) {
if (currentTeam.slug === user.username || currentTeam.slug === user.email) {
console.log(info('No changes made'));
return 0;
}
output.spinner('Saving');
updateCurrentTeam(config);
output.stopSpinner();
console.log(success(`Your account (${chalk.bold(choice)}) is now active!`));
return 0;
}
if (newTeam.slug === currentTeam.slug) {
console.log(info('No changes made'));
return 0;
}
output.spinner('Saving');
updateCurrentTeam(config, newTeam);
output.stopSpinner();
console.log(
success(
`The team ${chalk.bold(newTeam.name)} (${newTeam.slug}) is now active!`
)
);
return 0;
}

View File

@@ -0,0 +1,151 @@
// Packages
import chalk from 'chalk';
// Utilities
import Client from '../../util/client';
import { emoji } from '../../util/emoji';
import getUser from '../../util/get-user';
import getTeams from '../../util/get-teams';
import listInput from '../../util/input/list';
import { Team, GlobalConfig } from '../../types';
import { writeToConfigFile } from '../../util/config/files';
const updateCurrentTeam = (config: GlobalConfig, team?: Team) => {
if (team) {
config.currentTeam = team.id;
} else {
delete config.currentTeam;
}
writeToConfigFile(config);
};
export default async function main(client: Client, desiredSlug?: string) {
const { config, output } = client;
const personalScopeSelected = !config.currentTeam;
output.spinner('Fetching teams information');
const [user, teams] = await Promise.all([getUser(client), getTeams(client)]);
const currentTeam = personalScopeSelected
? undefined
: teams.find(team => team.id === config.currentTeam);
if (!personalScopeSelected && !currentTeam) {
output.error(`You are not a member of the current team anymore.`);
return 1;
}
if (!desiredSlug) {
const teamChoices = teams
.slice(0)
.sort((a, b) => {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
})
.map(team => {
let title = `${team.name} (${team.slug})`;
const selected = team.id === currentTeam?.id;
if (selected) {
title += ` ${chalk.bold('(current)')}`;
}
if (team.limited) {
title += ` ${emoji('locked')}`;
}
return {
name: title,
value: team.slug,
short: team.slug,
selected,
};
});
// Add the User scope entry at the top
let suffix = personalScopeSelected ? ` ${chalk.bold('(current)')}` : '';
// SAML tokens can not interact with the user scope
if (user.limited) {
suffix += ` ${emoji('locked')}`;
}
const choices = [
{ separator: 'Personal Account' },
{
name: `${user.name || user.email} (${user.username})${suffix}`,
value: user.username,
short: user.username,
selected: personalScopeSelected,
},
{ separator: 'Teams' },
...teamChoices,
];
output.stopSpinner();
desiredSlug = await listInput({
message: 'Switch to:',
choices,
eraseFinalAnswer: true,
});
}
// Abort
if (!desiredSlug) {
output.log('No changes made.');
return 0;
}
if (desiredSlug === user.username || desiredSlug === user.email) {
// Switch to user's personal account
if (personalScopeSelected) {
output.log('No changes made');
return 0;
}
if (user.limited) {
await client.reauthenticate({
scope: user.username,
teamId: null,
});
}
updateCurrentTeam(config);
output.success(
`Your account (${chalk.bold(user.username)}) is now active!`
);
return 0;
}
// Switch to selected team
const newTeam = teams.find(team => team.slug === desiredSlug);
if (!newTeam) {
output.error(
`You do not have permission to access scope ${chalk.bold(desiredSlug)}.`
);
return 1;
}
if (newTeam.slug === currentTeam?.slug) {
output.log('No changes made');
return 0;
}
if (newTeam.limited) {
const samlEnabled = newTeam.saml?.connection?.state === 'active';
await client.reauthenticate({
teamId: samlEnabled ? newTeam.id : null,
scope: newTeam.slug,
enforced: samlEnabled && newTeam.saml?.enforced === true,
});
}
updateCurrentTeam(config, newTeam);
output.success(
`The team ${chalk.bold(newTeam.name)} (${newTeam.slug}) is now active!`
);
return 0;
}

View File

@@ -587,10 +587,10 @@ const main = async () => {
const eventCategory = 'Exit Code';
try {
const start = new Date();
const start = Date.now();
const full = require(`./commands/${targetCommand}`).default;
exitCode = await full(client);
const end = new Date() - start;
const end = Date.now() - start;
if (shouldCollectMetrics) {
const category = 'Command Invocation';

View File

@@ -1,3 +1,20 @@
export type Primitive =
| bigint
| boolean
| null
| number
| string
| symbol
| undefined;
export type JSONArray = JSONValue[];
export type JSONValue = Primitive | JSONObject | JSONArray;
export interface JSONObject {
[key: string]: JSONValue;
}
export interface AuthConfig {
token: string;
skipWrite?: boolean;
@@ -45,18 +62,26 @@ export type User = {
updatedAt: number;
};
name?: string;
limited?: boolean;
};
export type Team = {
export interface Team {
id: string;
avatar?: string;
avatar?: string | null;
billing: Billing;
created: string;
creatorId: string;
membership: { uid: string; role: 'MEMBER' | 'OWNER'; created: number };
name: string;
slug: string;
};
limited?: boolean;
saml?: {
enforced: boolean;
connection?: {
state: string;
};
};
}
export type Domain = {
id: string;
@@ -268,3 +293,13 @@ export type ProjectLinkResult =
| { status: 'linked'; org: Org; project: Project }
| { status: 'not_linked'; org: null; project: null }
| { status: 'error'; exitCode: number };
export interface Token {
id: string;
name: string;
type: string;
origin?: string;
activeAt: number;
createdAt: number;
teamId?: string;
}

View File

@@ -3,7 +3,7 @@ import chalk from 'chalk';
import Client from '../client';
import { Output } from '../output';
import { User } from '../../types';
import { NowConfig } from '../dev/types';
import { VercelConfig } from '../dev/types';
import getDeploymentsByAppName from '../deploy/get-deployments-by-appname';
import getDeploymentByIdOrHost from '../deploy/get-deployment-by-id-or-host';
@@ -35,7 +35,7 @@ export async function getDeploymentForAlias(
localConfigPath: string | undefined,
user: User,
contextName: string,
localConfig: NowConfig
localConfig: VercelConfig
) {
output.spinner(`Fetching deployment to alias in ${chalk.bold(contextName)}`);

View File

@@ -1,22 +1,28 @@
import { URLSearchParams } from 'url';
import { EventEmitter } from 'events';
import { URLSearchParams } from 'url';
import { parse as parseUrl } from 'url';
import fetch, { RequestInit } from 'node-fetch';
import { VercelConfig } from '@vercel/client';
import retry, { RetryFunction, Options as RetryOptions } from 'async-retry';
import fetch, { BodyInit, Headers, RequestInit, Response } from 'node-fetch';
import ua from './ua';
import { Output } from './output/create-output';
import responseError from './response-error';
import ua from './ua';
import printIndications from './print-indications';
import { AuthConfig, GlobalConfig } from '../types';
import { NowConfig } from './dev/types';
import doSsoLogin from './login/sso';
import reauthenticate from './login/reauthenticate';
import { SAMLError } from './login/types';
import { writeToAuthConfigFile } from './config/files';
import { AuthConfig, GlobalConfig, JSONObject } from '../types';
import { sharedPromise } from './promise';
import { APIError } from './errors-ts';
import { bold } from 'chalk';
export interface FetchOptions {
body?: NodeJS.ReadableStream | object | string;
headers?: { [key: string]: string };
const isSAMLError = (v: any): v is SAMLError => {
return v && v.saml;
};
export interface FetchOptions extends Omit<RequestInit, 'body'> {
body?: BodyInit | JSONObject;
json?: boolean;
method?: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE';
retry?: RetryOptions;
useCurrentTeam?: boolean;
accountId?: string;
@@ -28,16 +34,20 @@ export interface ClientOptions {
authConfig: AuthConfig;
output: Output;
config: GlobalConfig;
localConfig: NowConfig;
localConfig: VercelConfig;
}
const isJSONObject = (v: any): v is JSONObject => {
return v && typeof v == 'object' && v.constructor === Object;
};
export default class Client extends EventEmitter {
argv: string[];
apiUrl: string;
authConfig: AuthConfig;
output: Output;
config: GlobalConfig;
localConfig: NowConfig;
localConfig: VercelConfig;
constructor(opts: ClientOptions) {
super();
@@ -47,7 +57,6 @@ export default class Client extends EventEmitter {
this.output = opts.output;
this.config = opts.config;
this.localConfig = opts.localConfig;
this._onRetry = this._onRetry.bind(this);
}
retry<T>(fn: RetryFunction<T>, { retries = 3, maxTimeout = Infinity } = {}) {
@@ -78,51 +87,43 @@ export default class Client extends EventEmitter {
}
_url = `${apiUrl}${parsedUrl.pathname}?${query}`;
delete opts.useCurrentTeam;
delete opts.accountId;
}
if (opts.json !== false && opts.body && typeof opts.body === 'object') {
Object.assign(opts, {
body: JSON.stringify(opts.body),
headers: Object.assign({}, opts.headers, {
'Content-Type': 'application/json',
}),
});
}
const headers = new Headers(opts.headers);
headers.set('authorization', `Bearer ${this.authConfig.token}`);
headers.set('user-agent', ua);
opts.headers = opts.headers || {};
opts.headers.Authorization = `Bearer ${this.authConfig.token}`;
opts.headers['user-agent'] = ua;
let body;
if (isJSONObject(opts.body)) {
body = JSON.stringify(opts.body);
headers.set('content-type', 'application/json; charset=utf8');
} else {
body = opts.body;
}
const url = `${apiUrl ? '' : this.apiUrl}${_url}`;
return this.output.time(
`${opts.method || 'GET'} ${url} ${JSON.stringify(opts.body) || ''}`,
fetch(url, opts as RequestInit)
fetch(url, { ...opts, headers, body })
);
}
async fetch<T>(url: string, opts: FetchOptions = {}): Promise<T> {
fetch(url: string, opts: { json: false }): Promise<Response>;
fetch<T>(url: string, opts?: FetchOptions): Promise<T>;
fetch(url: string, opts: FetchOptions = {}) {
return this.retry(async bail => {
const res = await this._fetch(url, opts);
printIndications(res);
if (!res.ok) {
const error = await responseError(res);
if (error.saml && error.teamId) {
// If a SAML error is encountered then we re-trigger the SAML
// authentication flow for the team specified in the error.
const result = await doSsoLogin(error.teamId, this);
if (typeof result === 'number') {
this.output.prettyError(error);
process.exit(1);
return;
}
this.authConfig.token = result;
writeToAuthConfigFile(this.authConfig);
if (isSAMLError(error)) {
// A SAML error means the token is expired, or is not
// designated for the requested team, so the user needs
// to re-authenticate
await this.reauthenticate(error);
} else if (res.status >= 400 && res.status < 500) {
// Any other 4xx should bail without retrying
return bail(error);
@@ -136,21 +137,37 @@ export default class Client extends EventEmitter {
return res;
}
if (!res.headers.get('content-type')) {
const contentType = res.headers.get('content-type');
if (!contentType) {
return null;
}
printIndications(res);
return res.headers.get('content-type').includes('application/json')
? res.json()
: res;
return contentType.includes('application/json') ? res.json() : res;
}, opts.retry);
}
_onRetry(error: Error) {
this.output.debug(`Retrying: ${error}\n${error.stack}`);
}
reauthenticate = sharedPromise(async function (
this: Client,
error: SAMLError
) {
const result = await reauthenticate(this, error);
close() {}
if (typeof result === 'number') {
if (error instanceof APIError) {
this.output.prettyError(error);
} else {
this.output.error(
`Failed to re-authenticate for ${bold(error.scope)} scope`
);
}
process.exit(1);
}
this.authConfig.token = result;
writeToAuthConfigFile(this.authConfig);
});
_onRetry = (error: Error) => {
this.output.debug(`Retrying: ${error}\n${error.stack}`);
};
}

View File

@@ -8,7 +8,7 @@ import getLocalPathConfig from './local-path';
import { NowError } from '../now-error';
import error from '../output/error';
import highlight from '../output/highlight';
import { NowConfig } from '../dev/types';
import { VercelConfig } from '../dev/types';
import { AuthConfig, GlobalConfig } from '../../types';
const VERCEL_DIR = getGlobalPathConfig();
@@ -100,8 +100,8 @@ export function getAuthConfigFilePath() {
export function readLocalConfig(
prefix: string = process.cwd()
): NowConfig | null {
let config: NowConfig | null = null;
): VercelConfig | null {
let config: VercelConfig | null = null;
let target = '';
try {

View File

@@ -1,7 +1,7 @@
import { join } from 'path';
import { CantParseJSONFile } from '../errors-ts';
import readJSONFile from '../read-json-file';
import { NowConfig } from '../dev/types';
import { VercelConfig } from '../dev/types';
import getLocalConfigPath from './local-path';
export default async function readConfig(dir: string) {
@@ -13,7 +13,7 @@ export default async function readConfig(dir: string) {
}
if (result) {
return result as NowConfig;
return result as VercelConfig;
}
return null;

View File

@@ -39,7 +39,9 @@ export default async function getDeploymentsByProjectId(
query.set('from', options.from.toString());
}
const { deployments } = await client.fetch<Response>(`/v4/now/deployments?${query}`);
const { deployments } = await client.fetch<Response>(
`/v4/now/deployments?${query}`
);
total += deployments.length;
if (options.max && total >= options.max) {
@@ -49,15 +51,15 @@ export default async function getDeploymentsByProjectId(
if (options.continue && deployments.length === limit) {
const nextFrom = deployments[deployments.length - 1].created;
const nextOptions = Object.assign({}, options, { from: nextFrom });
deployments.push(...(await getDeploymentsByProjectId(client, projectId, nextOptions, total)));
deployments.push(
...(await getDeploymentsByProjectId(
client,
projectId,
nextOptions,
total
))
);
}
return deployments;
}
export async function getAllDeploymentsByProjectId(
client: Client,
projectId: string
) {
return getDeploymentsByProjectId(client, projectId, { from: null, limit: 100, continue: true });
}

View File

@@ -9,7 +9,7 @@ import {
import { Output } from '../output';
// @ts-ignore
import Now from '../../util';
import { NowConfig } from '../dev/types';
import { VercelConfig } from '../dev/types';
import { Org } from '../../types';
import ua from '../ua';
import { linkFolderToProject } from '../projects/link';
@@ -43,7 +43,7 @@ export default async function processDeployment({
uploadStamp: () => string;
deployStamp: () => string;
quiet: boolean;
nowConfig?: NowConfig;
nowConfig?: VercelConfig;
force?: boolean;
withCache?: boolean;
org: Org;

View File

@@ -27,7 +27,7 @@ import { LambdaSizeExceededError } from '../errors-ts';
import DevServer from './server';
import { getBuilder } from './builder-cache';
import {
NowConfig,
VercelConfig,
BuildMatch,
BuildResult,
BuilderInputs,
@@ -96,7 +96,7 @@ async function createBuildProcess(
}
export async function executeBuild(
nowConfig: NowConfig,
nowConfig: VercelConfig,
devServer: DevServer,
files: BuilderInputs,
match: BuildMatch,
@@ -383,7 +383,7 @@ export async function executeBuild(
}
export async function getBuildMatches(
nowConfig: NowConfig,
nowConfig: VercelConfig,
cwd: string,
output: Output,
devServer: DevServer,

View File

@@ -4,7 +4,7 @@ import PCRE from 'pcre-to-regexp';
import isURL from './is-url';
import DevServer from './server';
import { NowConfig, HttpHeadersConfig, RouteResult } from './types';
import { VercelConfig, HttpHeadersConfig, RouteResult } from './types';
import { isHandler, Route, HandleValue } from '@vercel/routing-utils';
export function resolveRouteParameters(
@@ -50,7 +50,7 @@ export async function devRouter(
reqMethod?: string,
routes?: Route[],
devServer?: DevServer,
nowConfig?: NowConfig,
nowConfig?: VercelConfig,
previousHeaders?: HttpHeadersConfig,
missRoutes?: Route[],
phase?: HandleValue | null

View File

@@ -49,7 +49,7 @@ import sleep from '../sleep';
import { Output } from '../output';
import { relative } from '../path-helpers';
import { getDistTag } from '../get-dist-tag';
import getNowConfigPath from '../config/local-path';
import getVercelConfigPath from '../config/local-path';
import { MissingDotenvVarsError } from '../errors-ts';
import cliPkg from '../pkg';
import { getVercelDirectory } from '../projects/link';
@@ -73,7 +73,7 @@ import errorTemplate502 from './templates/error_502';
import redirectTemplate from './templates/redirect';
import {
NowConfig,
VercelConfig,
DevServerOptions,
BuildMatch,
BuildResult,
@@ -145,7 +145,7 @@ export default class DevServer {
private devServerPids: Set<number>;
private projectSettings?: ProjectSettings;
private getNowConfigPromise: Promise<NowConfig> | null;
private getVercelConfigPromise: Promise<VercelConfig> | null;
private blockingBuildsPromise: Promise<void> | null;
private updateBuildersPromise: Promise<void> | null;
private updateBuildersTimeout: NodeJS.Timeout | undefined;
@@ -181,7 +181,7 @@ export default class DevServer {
this.inProgressBuilds = new Map();
this.devCacheDir = join(getVercelDirectory(cwd), 'cache');
this.getNowConfigPromise = null;
this.getVercelConfigPromise = null;
this.blockingBuildsPromise = null;
this.updateBuildersPromise = null;
this.startPromise = null;
@@ -244,7 +244,7 @@ export default class DevServer {
}
}
const nowConfig = await this.getNowConfig();
const nowConfig = await this.getVercelConfig();
// Update the build matches in case an entrypoint was created or deleted
await this.updateBuildMatches(nowConfig);
@@ -375,7 +375,7 @@ export default class DevServer {
}
async updateBuildMatches(
nowConfig: NowConfig,
nowConfig: VercelConfig,
isInitial = false
): Promise<void> {
const fileList = this.resolveBuildFiles(this.files);
@@ -460,7 +460,7 @@ export default class DevServer {
}
async invalidateBuildMatches(
nowConfig: NowConfig,
nowConfig: VercelConfig,
updatedBuilders: string[]
): Promise<void> {
if (updatedBuilders.length === 0) {
@@ -516,25 +516,25 @@ export default class DevServer {
return {};
}
clearNowConfigPromise = () => {
this.getNowConfigPromise = null;
clearVercelConfigPromise = () => {
this.getVercelConfigPromise = null;
};
getNowConfig(): Promise<NowConfig> {
if (this.getNowConfigPromise) {
return this.getNowConfigPromise;
getVercelConfig(): Promise<VercelConfig> {
if (this.getVercelConfigPromise) {
return this.getVercelConfigPromise;
}
this.getNowConfigPromise = this._getNowConfig();
this.getVercelConfigPromise = this._getVercelConfig();
// Clean up the promise once it has resolved
const clear = this.clearNowConfigPromise;
this.getNowConfigPromise.finally(clear);
const clear = this.clearVercelConfigPromise;
this.getVercelConfigPromise.finally(clear);
return this.getNowConfigPromise;
return this.getVercelConfigPromise;
}
async _getNowConfig(): Promise<NowConfig> {
const configPath = getNowConfigPath(this.cwd);
async _getVercelConfig(): Promise<VercelConfig> {
const configPath = getVercelConfigPath(this.cwd);
const [
pkg = null,
@@ -543,10 +543,10 @@ export default class DevServer {
config = { version: 2, [fileNameSymbol]: 'vercel.json' },
] = await Promise.all([
this.readJsonFile<PackageJson>('package.json'),
this.readJsonFile<NowConfig>(configPath),
this.readJsonFile<VercelConfig>(configPath),
]);
await this.validateNowConfig(config);
await this.validateVercelConfig(config);
const { error: routeError, routes: maybeRoutes } = getTransformedRoutes({
nowConfig: config,
});
@@ -634,7 +634,7 @@ export default class DevServer {
config.builds.sort(sortBuilders);
}
await this.validateNowConfig(config);
await this.validateVercelConfig(config);
this.caseSensitive = hasNewRoutingProperties(config);
this.apiDir = detectApiDirectory(config.builds || []);
@@ -710,8 +710,8 @@ export default class DevServer {
}
async tryValidateOrExit(
config: NowConfig,
validate: (c: NowConfig) => string | null
config: VercelConfig,
validate: (c: VercelConfig) => string | null
): Promise<void> {
const message = validate(config);
@@ -721,7 +721,7 @@ export default class DevServer {
}
}
async validateNowConfig(config: NowConfig): Promise<void> {
async validateVercelConfig(config: VercelConfig): Promise<void> {
if (config.version === 1) {
this.output.error('Cannot run `version: 1` projects.');
await this.exit(1);
@@ -855,7 +855,7 @@ export default class DevServer {
.replace('[::]', 'localhost')
.replace('127.0.0.1', 'localhost');
const nowConfig = await this.getNowConfig();
const nowConfig = await this.getVercelConfig();
const devCommandPromise = this.runDevCommand();
const files = await getFiles(this.cwd, { output: this.output });
@@ -982,7 +982,7 @@ export default class DevServer {
if (devProcess) {
ops.push(
new Promise((resolve, reject) => {
new Promise<void>((resolve, reject) => {
devProcess.once('exit', () => resolve());
try {
process.kill(devProcess.pid);
@@ -1201,7 +1201,7 @@ export default class DevServer {
match: BuildMatch,
requestPath: string | null,
req: http.IncomingMessage | null,
nowConfig: NowConfig,
nowConfig: VercelConfig,
previousBuildResult?: BuildResult,
filesChanged?: string[],
filesRemoved?: string[]
@@ -1290,7 +1290,7 @@ export default class DevServer {
this.output.debug(`${chalk.bold(method)} ${req.url}`);
try {
const nowConfig = await this.getNowConfig();
const nowConfig = await this.getVercelConfig();
await this.serveProjectAsNowV2(req, res, nowRequestId, nowConfig);
} catch (err) {
console.error(err);
@@ -1339,7 +1339,7 @@ export default class DevServer {
req: http.IncomingMessage,
res: http.ServerResponse,
nowRequestId: string,
nowConfig: NowConfig,
nowConfig: VercelConfig,
routes: Route[] | undefined = nowConfig.routes,
callLevel: number = 0
) => {
@@ -1992,7 +1992,7 @@ export default class DevServer {
return true;
}
async hasFilesystem(dest: string, nowConfig: NowConfig): Promise<boolean> {
async hasFilesystem(dest: string, nowConfig: VercelConfig): Promise<boolean> {
if (
await findBuildMatch(
this.buildMatches,
@@ -2181,7 +2181,7 @@ async function findBuildMatch(
files: BuilderInputs,
requestPath: string,
devServer: DevServer,
nowConfig: NowConfig,
nowConfig: VercelConfig,
isFilesystem = false
): Promise<BuildMatch | null> {
requestPath = requestPath.replace(/^\//, '');
@@ -2219,7 +2219,7 @@ async function shouldServe(
files: BuilderInputs,
requestPath: string,
devServer: DevServer,
nowConfig: NowConfig,
nowConfig: VercelConfig,
isFilesystem = false
): Promise<boolean> {
const {
@@ -2284,7 +2284,7 @@ async function findMatchingRoute(
match: BuildMatch,
requestPath: string,
devServer: DevServer,
nowConfig: NowConfig
nowConfig: VercelConfig
): Promise<RouteResult | void> {
const reqUrl = `/${requestPath}`;
for (const buildResult of match.buildResults.values()) {
@@ -2305,7 +2305,7 @@ async function findMatchingRoute(
function findAsset(
match: BuildMatch,
requestPath: string,
nowConfig: NowConfig
nowConfig: VercelConfig
): { asset: BuilderOutput; assetKey: string } | void {
if (!match.buildOutput) {
return;
@@ -2397,7 +2397,7 @@ function filterFrontendBuilds(build: Builder) {
return !frontendRuntimeSet.has(name || '');
}
function hasNewRoutingProperties(nowConfig: NowConfig) {
function hasNewRoutingProperties(nowConfig: VercelConfig) {
return (
typeof nowConfig.cleanUrls !== undefined ||
typeof nowConfig.headers !== undefined ||

View File

@@ -14,12 +14,12 @@ import {
Lambda,
PackageJson,
} from '@vercel/build-utils';
import { NowConfig } from '@vercel/client';
import { VercelConfig } from '@vercel/client';
import { HandleValue, Route } from '@vercel/routing-utils';
import { Output } from '../output';
import { ProjectEnvVariable, ProjectSettings } from '../../types';
export { NowConfig };
export { VercelConfig };
export interface DevServerOptions {
output: Output;

View File

@@ -7,7 +7,7 @@ import {
rewritesSchema,
trailingSlashSchema,
} from '@vercel/routing-utils';
import { NowConfig } from './types';
import { VercelConfig } from './types';
import {
functionsSchema,
buildsSchema,
@@ -36,7 +36,7 @@ const vercelConfigSchema = {
const ajv = new Ajv();
const validate = ajv.compile(vercelConfigSchema);
export function validateConfig(config: NowConfig): NowBuildError | null {
export function validateConfig(config: VercelConfig): NowBuildError | null {
if (!validate(config)) {
if (validate.errors && validate.errors[0]) {
const error = validate.errors[0];

View File

@@ -1,28 +1,17 @@
export type EmojiLabel =
| 'notice'
| 'tip'
| 'warning'
| 'link'
| 'inspect'
| 'success';
export const emojiLabels = {
notice: '📝',
tip: '💡',
warning: '❗️',
link: '🔗',
inspect: '🔍',
success: '✅',
locked: '🔒',
} as const;
export function emoji(label: EmojiLabel): string | undefined {
switch (label) {
case 'notice':
return '📝';
case 'tip':
return '💡';
case 'warning':
return '❗️';
case 'link':
return '🔗';
case 'inspect':
return '🔍';
case 'success':
return '✅';
default:
return undefined;
}
export type EmojiLabel = keyof typeof emojiLabels;
export function emoji(label: EmojiLabel) {
return emojiLabels[label];
}
export function prependEmoji(message: string, emoji?: string): string {

View File

@@ -2,52 +2,41 @@
import { URLSearchParams } from 'url';
// Packages
import retry from 'async-retry';
import jsonlines from 'jsonlines';
import { eraseLines } from 'ansi-escapes';
import jsonlines from 'jsonlines';
import retry from 'async-retry';
import Client from './client';
import { getDeployment } from './get-deployment';
export interface FindOpts {
direction: 'forward' | 'backward';
limit?: number;
since?: number;
until?: number;
follow?: boolean;
}
export interface PrintEventsOptions {
mode: string;
onEvent: (event: DeploymentEvent) => void;
quiet?: boolean;
findOpts: FindOpts;
}
export interface DeploymentEvent {
id: string;
created: number;
date?: number;
serial?: string;
}
async function printEvents(
now,
deploymentIdOrURL,
currentTeam = null,
{
mode,
onOpen = () => {},
onEvent,
quiet,
debugEnabled,
findOpts,
output,
} = {}
client: Client,
deploymentIdOrURL: string,
{ mode, onEvent, quiet, findOpts }: PrintEventsOptions
) {
const { log, debug } = output;
let onOpenCalled = false;
function callOnOpenOnce() {
if (onOpenCalled) return;
onOpenCalled = true;
onOpen();
}
const query = new URLSearchParams({
direction: findOpts.direction,
limit: findOpts.limit,
since: findOpts.since,
until: findOpts.until,
follow: findOpts.follow ? '1' : '',
format: 'lines',
});
let eventsUrl = `/v1/now/deployments/${deploymentIdOrURL}/events?${query}`;
let pollUrl = `/v3/now/deployments/${deploymentIdOrURL}`;
if (currentTeam) {
eventsUrl += `&teamId=${currentTeam.id}`;
pollUrl += `?teamId=${currentTeam.id}`;
}
debug(`Events ${eventsUrl}`);
const { log, debug } = client.output;
// we keep track of how much we log in case we
// drop the connection and have to start over
@@ -59,29 +48,34 @@ async function printEvents(
debug('Retrying events');
}
const eventsRes = await now._fetch(eventsUrl);
const query = new URLSearchParams({
direction: findOpts.direction,
follow: findOpts.follow ? '1' : '',
format: 'lines',
});
if (findOpts.limit) query.set('limit', String(findOpts.limit));
if (findOpts.since) query.set('since', String(findOpts.since));
if (findOpts.until) query.set('until', String(findOpts.until));
const eventsUrl = `/v1/now/deployments/${deploymentIdOrURL}/events?${query}`;
const eventsRes = await client.fetch(eventsUrl, { json: false });
if (eventsRes.ok) {
const readable = eventsRes.readable
? await eventsRes.readable()
: eventsRes.body;
const readable = eventsRes.body;
// handle the event stream and make the promise get rejected
// if errors occur so we can retry
return new Promise((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
const stream = readable.pipe(jsonlines.parse());
let poller;
let poller: ReturnType<typeof setTimeout>;
if (mode === 'deploy') {
poller = (function startPoller() {
return setTimeout(async () => {
try {
const pollRes = await now._fetch(pollUrl);
if (!pollRes.ok)
throw new Error(`Response ${pollRes.status}`);
const json = await pollRes.json();
if (json.state === 'READY') {
const json = await getDeployment(client, deploymentIdOrURL);
if (json.readyState === 'READY') {
stream.end();
finish();
return;
@@ -96,10 +90,9 @@ async function printEvents(
}
let finishCalled = false;
function finish(error) {
function finish(error?: Error) {
if (finishCalled) return;
finishCalled = true;
callOnOpenOnce();
clearTimeout(poller);
if (error) {
reject(error);
@@ -110,26 +103,24 @@ async function printEvents(
let latestLogDate = 0;
const onData = data => {
const { event } = data;
if (event === 'state' && data.payload.value === 'READY') {
const onData = (data: any) => {
const { event, payload, date } = data;
if (event === 'state' && payload.value === 'READY') {
if (mode === 'deploy') {
stream.end();
finish();
}
} else {
latestLogDate = Math.max(latestLogDate, data.date);
const linesPrinted = onEvent(data, callOnOpenOnce);
o += linesPrinted || 0;
latestLogDate = Math.max(latestLogDate, date);
onEvent(data);
}
};
let onErrorCalled = false;
const onError = err => {
const onError = (err: Error) => {
if (finishCalled || onErrorCalled) return;
onErrorCalled = true;
o++;
callOnOpenOnce();
const errorMessage = `Deployment event stream error: ${err.message}`;
if (!findOpts.follow) {
@@ -140,7 +131,6 @@ async function printEvents(
debug(errorMessage);
clearTimeout(poller);
stream.destroy(err);
readable.destroy(err);
const retryFindOpts = {
...findOpts,
@@ -149,12 +139,10 @@ async function printEvents(
setTimeout(() => {
// retry without maximum amount nor clear past logs etc
printEvents(now, deploymentIdOrURL, currentTeam, {
printEvents(client, deploymentIdOrURL, {
mode,
onOpen,
onEvent,
quiet,
debugEnabled,
findOpts: retryFindOpts,
}).then(resolve, reject);
}, 2000);
@@ -166,7 +154,6 @@ async function printEvents(
readable.on('error', onError);
});
}
callOnOpenOnce();
const err = new Error(`Deployment events status ${eventsRes.status}`);
if (eventsRes.status < 500) {

View File

@@ -9,15 +9,15 @@ import {
import humanizePath from './humanize-path';
import readJSONFile from './read-json-file';
import readPackage from './read-package';
import { NowConfig } from './dev/types';
import { VercelConfig } from './dev/types';
import { Output } from './output';
let config: NowConfig;
let config: VercelConfig;
export default async function getConfig(
output: Output,
configFile?: string
): Promise<NowConfig | Error> {
): Promise<VercelConfig | Error> {
// If config was already read, just return it
if (config) {
return config;
@@ -44,7 +44,7 @@ export default async function getConfig(
return localConfig;
}
if (localConfig !== null) {
config = localConfig as NowConfig;
config = localConfig as VercelConfig;
config[fileNameSymbol] = configFile;
return config;
}
@@ -68,13 +68,13 @@ export default async function getConfig(
}
if (vercelConfig !== null) {
output.debug(`Found config in file "${vercelFilePath}"`);
config = vercelConfig as NowConfig;
config = vercelConfig as VercelConfig;
config[fileNameSymbol] = 'vercel.json';
return config;
}
if (nowConfig !== null) {
output.debug(`Found config in file "${nowFilePath}"`);
config = nowConfig as NowConfig;
config = nowConfig as VercelConfig;
config[fileNameSymbol] = 'now.json';
return config;
}
@@ -87,7 +87,7 @@ export default async function getConfig(
}
if (pkgConfig) {
output.debug(`Found config in package ${pkgFilePath}`);
config = pkgConfig as NowConfig;
config = pkgConfig as VercelConfig;
config[fileNameSymbol] = 'package.json';
return config;
}

View File

@@ -0,0 +1,27 @@
import { stringify } from 'querystring';
import { Deployment } from '@vercel/client';
import Client from './client';
export async function getDeployment(
client: Client,
hostOrId: string
): Promise<Deployment> {
let url = `/v13/deployments`;
if (hostOrId.includes('.')) {
let host = hostOrId.replace(/^https:\/\//i, '');
if (host.slice(-1) === '/') {
host = host.slice(0, -1);
}
url += `/get?${stringify({
url: host,
})}`;
} else {
url += `/${encodeURIComponent(hostOrId)}`;
}
const deployment = await client.fetch<Deployment>(url);
return deployment;
}

View File

@@ -1,8 +1,6 @@
import Client from './client';
import { APIError, InvalidToken } from './errors-ts';
import { Team } from '../types';
// @ts-ignore
import NowTeams from './teams.js';
import { APIError, InvalidToken } from './errors-ts';
let teams: Team[] | undefined;
@@ -10,15 +8,11 @@ export default async function getTeams(client: Client): Promise<Team[]> {
if (teams) return teams;
try {
// we're using NowTeams because `client.fetch` hangs on windows
const teamClient = new NowTeams({
apiUrl: client.apiUrl,
token: client.authConfig.token,
debug: client.output.isDebugEnabled(),
const body = await client.fetch<{ teams: Team[] }>('/v1/teams', {
useCurrentTeam: false,
});
teams = (await teamClient.ls()).teams;
return teams || [];
teams = body.teams || [];
return teams;
} catch (error) {
if (error instanceof APIError && error.status === 403) {
throw new InvalidToken();

View File

@@ -6,15 +6,12 @@ export default async function confirm(
): Promise<boolean> {
require('./patch-inquirer');
const name = `${Date.now()}`;
const answers = await inquirer.prompt({
type: 'confirm',
name,
name: 'value',
message,
default: preferred,
});
const answer = answers[name] as boolean;
return answer;
return answers.value;
}

View File

@@ -1,82 +0,0 @@
import inquirer from 'inquirer';
import stripAnsi from 'strip-ansi';
import eraseLines from '../output/erase-lines';
function getLength(string) {
let biggestLength = 0;
string.split('\n').map(str => {
str = stripAnsi(str);
if (str.length > biggestLength) {
biggestLength = str.length;
}
return undefined;
});
return biggestLength;
}
export default async function({
message = 'the question',
// eslint-disable-line no-unused-vars
choices = [
{
name: 'something\ndescription\ndetails\netc',
value: 'something unique',
short: 'generally the first line of `name`',
},
],
pageSize = 15, // Show 15 lines without scrolling (~4 credit cards)
separator = true, // Puts a blank separator between each choice
abort = 'end', // Wether the `abort` option will be at the `start` or the `end`,
eraseFinalAnswer = false, // If true, the line with the final answee that inquirer prints will be erased before returning
}) {
require('./patch-inquirer-legacy');
let biggestLength = 0;
choices = choices.map(choice => {
if (choice.name) {
const length = getLength(choice.name);
if (length > biggestLength) {
biggestLength = length;
}
return choice;
}
throw new Error('Invalid choice');
});
if (separator === true) {
choices = choices.reduce(
(prev, curr) => prev.concat(new inquirer.Separator(' '), curr),
[]
);
}
const abortSeparator = new inquirer.Separator('─'.repeat(biggestLength));
const _abort = {
name: 'Abort',
value: undefined,
};
if (abort === 'start') {
const blankSep = choices.shift();
choices.unshift(abortSeparator);
choices.unshift(_abort);
choices.unshift(blankSep);
} else {
choices.push(abortSeparator);
choices.push(_abort);
}
const nonce = Date.now();
const answer = await inquirer.prompt({
name: nonce,
type: 'list',
message,
choices,
pageSize,
});
if (eraseFinalAnswer === true) {
process.stdout.write(eraseLines(2));
}
return answer[nonce];
}

View File

@@ -0,0 +1,123 @@
import inquirer from 'inquirer';
import stripAnsi from 'strip-ansi';
import eraseLines from '../output/erase-lines';
interface ListEntry {
name: string;
value: string;
short: string;
selected?: boolean;
}
interface ListSeparator {
separator: string;
}
type ListChoice = ListEntry | ListSeparator | typeof inquirer.Separator;
interface ListOptions {
message: string;
choices: ListChoice[];
pageSize?: number;
separator?: boolean;
abort?: 'start' | 'end';
eraseFinalAnswer?: boolean;
}
function getLength(input: string): number {
let biggestLength = 0;
for (const line of input.split('\n')) {
const str = stripAnsi(line);
if (str.length > biggestLength) {
biggestLength = str.length;
}
}
return biggestLength;
}
export default async function list({
message = 'the question',
// eslint-disable-line no-unused-vars
choices: _choices = [
{
name: 'something\ndescription\ndetails\netc',
value: 'something unique',
short: 'generally the first line of `name`',
},
],
pageSize = 15, // Show 15 lines without scrolling (~4 credit cards)
separator = false, // Puts a blank separator between each choice
abort = 'end', // Whether the `abort` option will be at the `start` or the `end`,
eraseFinalAnswer = false, // If true, the line with the final answer that inquirer prints will be erased before returning
}: ListOptions): Promise<string> {
require('./patch-inquirer-legacy');
let biggestLength = 0;
let selected: string | undefined;
// First calculate the biggest length
for (const choice of _choices) {
if ('name' in choice) {
const length = getLength(choice.name);
if (length > biggestLength) {
biggestLength = length;
}
}
}
const choices = _choices.map(choice => {
if (choice instanceof inquirer.Separator) {
return choice;
}
if ('separator' in choice) {
const prefix = `── ${choice.separator} `;
const suffix = '─'.repeat(biggestLength - getLength(prefix));
return new inquirer.Separator(`${prefix}${suffix}`);
}
if ('short' in choice) {
if (choice.selected) {
if (selected) throw new Error('Only one choice may be selected');
selected = choice.short;
}
return choice;
}
throw new Error('Invalid choice');
});
if (separator) {
for (let i = 0; i < choices.length; i += 2) {
choices.splice(i, 0, new inquirer.Separator(' '));
}
}
const abortSeparator = new inquirer.Separator('─'.repeat(biggestLength));
const _abort = {
name: 'Abort',
value: '',
short: '',
};
if (abort === 'start') {
choices.unshift(_abort, abortSeparator);
} else {
choices.push(abortSeparator, _abort);
}
const answer = await inquirer.prompt({
name: 'value',
type: 'list',
default: selected,
message,
choices,
pageSize,
});
if (eraseFinalAnswer === true) {
process.stdout.write(eraseLines(2));
}
return answer.value;
}

View File

@@ -2,7 +2,7 @@ import { join, basename } from 'path';
import chalk from 'chalk';
import { remove } from 'fs-extra';
import { ProjectLinkResult, ProjectSettings } from '../../types';
import { NowConfig } from '../dev/types';
import { VercelConfig } from '../dev/types';
import {
getLinkedProject,
linkFolderToProject,
@@ -134,7 +134,7 @@ export default async function setupAndLink(
return { status: 'error', exitCode: 1 };
}
let localConfig: NowConfig = {};
let localConfig: VercelConfig = {};
if (client.localConfig && !(client.localConfig instanceof Error)) {
localConfig = client.localConfig;
}

View File

@@ -9,5 +9,5 @@ export default function doBitbucketLogin(params: LoginParams) {
// cookie that the OAuth callback URL depends on
'https://vercel.com'
);
return doOauthLogin(url, 'Bitbucket', params);
return doOauthLogin(params, url, 'Bitbucket');
}

View File

@@ -7,8 +7,8 @@ import executeLogin from './login';
import { LoginParams } from './types';
export default async function doEmailLogin(
email: string,
params: LoginParams
params: LoginParams,
email: string
): Promise<number | string> {
let securityCode;
let verificationToken;

View File

@@ -9,5 +9,5 @@ export default function doGithubLogin(params: LoginParams) {
// cookie that the OAuth callback URL depends on
'https://vercel.com'
);
return doOauthLogin(url, 'GitHub', params);
return doOauthLogin(params, url, 'GitHub');
}

View File

@@ -6,5 +6,5 @@ export default function doGitlabLogin(params: LoginParams) {
// Can't use `apiUrl` here because this URL sets a
// cookie that the OAuth callback URL depends on
const url = new URL('/api/registration/gitlab/connect', 'https://vercel.com');
return doOauthLogin(url, 'GitLab', params);
return doOauthLogin(params, url, 'GitLab');
}

View File

@@ -2,15 +2,17 @@ import http from 'http';
import open from 'open';
import { URL } from 'url';
import listen from 'async-listen';
import { hostname } from 'os';
import { LoginParams } from './types';
import prompt from './prompt';
import verify from './verify';
import { getTitleName } from '../pkg-name';
import highlight from '../output/highlight';
export default async function doOauthLogin(
params: LoginParams,
url: URL,
provider: string,
params: LoginParams
provider: string
): Promise<number | string> {
const { output } = params;
@@ -24,6 +26,12 @@ export default async function doOauthLogin(
url.searchParams.append('mode', 'login');
url.searchParams.append('next', `http://localhost:${port}`);
// Append token name param
const hyphens = new RegExp('-', 'g');
const host = hostname().replace(hyphens, ' ').replace('.local', '');
const tokenName = `${getTitleName()} CLI on ${host} via ${provider}`;
url.searchParams.append('tokenName', tokenName);
try {
const [query] = await Promise.all([
new Promise<URL['searchParams']>((resolve, reject) => {

View File

@@ -2,14 +2,17 @@ import inquirer from 'inquirer';
import error from '../output/error';
import listInput from '../input/list';
import { getCommandName } from '../pkg-name';
import { LoginParams } from './types';
import { LoginParams, SAMLError } from './types';
import doSsoLogin from './sso';
import doEmailLogin from './email';
import doGithubLogin from './github';
import doGitlabLogin from './gitlab';
import doBitbucketLogin from './bitbucket';
export default async function prompt(params: LoginParams) {
export default async function prompt(
params: LoginParams,
error?: Pick<SAMLError, 'teamId'>
) {
let result: number | string = 1;
const choices = [
@@ -17,17 +20,17 @@ export default async function prompt(params: LoginParams) {
{ name: 'Continue with GitLab', value: 'gitlab', short: 'gitlab' },
{ name: 'Continue with Bitbucket', value: 'bitbucket', short: 'bitbucket' },
{ name: 'Continue with Email', value: 'email', short: 'email' },
{ name: 'Continue with SAML Single Sign-On', value: 'saml', short: 'saml' },
{ name: 'Continue with SAML Single Sign-On', value: 'sso', short: 'sso' },
];
if (params.ssoUserId) {
// Remove SAML login option if we're connecting SAML Profile
if (params.ssoUserId || (error && !error.teamId)) {
// Remove SAML login option if we're connecting SAML Profile,
// or if this is a SAML error for a user / team without SAML
choices.pop();
}
const choice = await listInput({
message: 'Log in to Vercel',
separator: false,
choices,
});
@@ -39,10 +42,10 @@ export default async function prompt(params: LoginParams) {
result = await doBitbucketLogin(params);
} else if (choice === 'email') {
const email = await readInput('Enter your email address');
result = await doEmailLogin(email, params);
} else if (choice === 'saml') {
const slug = await readInput('Enter your Team slug');
result = await doSsoLogin(slug, params);
result = await doEmailLogin(params, email);
} else if (choice === 'sso') {
const slug = error?.teamId || (await readInput('Enter your Team slug'));
result = await doSsoLogin(params, slug);
}
return result;

View File

@@ -0,0 +1,28 @@
import { bold } from 'chalk';
import doSsoLogin from './sso';
import showLoginPrompt from './prompt';
import { LoginParams, SAMLError } from './types';
import confirm from '../input/confirm';
export default async function reauthenticate(
params: LoginParams,
error: Pick<SAMLError, 'enforced' | 'scope' | 'teamId'>
): Promise<string | number> {
let result: string | number = 1;
if (error.teamId && error.enforced) {
// If team has SAML enforced then trigger the SSO login directly
params.output.log(
`You must re-authenticate with SAML to use ${bold(error.scope)} scope.`
);
if (await confirm(`Log in with SAML?`, true)) {
result = await doSsoLogin(params, error.teamId);
}
} else {
// Personal account, or team that does not have SAML enforced
params.output.log(
`You must re-authenticate to use ${bold(error.scope)} scope.`
);
result = await showLoginPrompt(params, error);
}
return result;
}

View File

@@ -1,17 +1,9 @@
import { URL } from 'url';
import { hostname } from 'os';
import { getTitleName } from '../pkg-name';
import { LoginParams } from './types';
import doOauthLogin from './oauth';
export default function doSsoLogin(teamIdOrSlug: string, params: LoginParams) {
const hyphens = new RegExp('-', 'g');
const host = hostname().replace(hyphens, ' ').replace('.local', '');
const tokenName = `${getTitleName()} CLI on ${host}`;
export default function doSsoLogin(params: LoginParams, teamIdOrSlug: string) {
const url = new URL('/auth/sso', params.apiUrl);
url.searchParams.append('teamId', teamIdOrSlug);
url.searchParams.append('tokenName', tokenName);
return doOauthLogin(url, 'SAML Single Sign-On', params);
return doOauthLogin(params, url, 'SAML Single Sign-On');
}

View File

@@ -10,3 +10,10 @@ export interface LoginData {
token: string;
securityCode: string;
}
export interface SAMLError {
saml?: true;
teamId: string | null;
scope: string;
enforced?: boolean;
}

View File

@@ -0,0 +1,24 @@
/**
* Wraps a function such that only one in-flight invocation is active at a time.
*
* That is, if the returned function is invoked more that one time before the
* promise returned from the initial invocation resolves, then the same promise
* is returned for subsequent invocations.
*
* Once the promise has resolved, the next invocation of the returned function
* will re-invoke the original function again.
*/
export function sharedPromise<P extends any[], V, T>(
fn: (this: T, ...args: P) => Promise<V>
) {
let promise: Promise<V> | null = null;
return function (this: T, ...args: P) {
if (!promise) {
promise = fn.apply(this, args);
promise.finally(() => {
promise = null;
});
}
return promise;
};
}

View File

@@ -1,11 +1,11 @@
import path from 'path';
import { CantParseJSONFile } from './errors-ts';
import readJSONFile from './read-json-file';
import { NowConfig } from './dev/types';
import { VercelConfig } from './dev/types';
import { PackageJson } from '@vercel/build-utils';
interface CustomPackage extends PackageJson {
now?: NowConfig;
now?: VercelConfig;
}
export default async function readPackage(file?: string) {

View File

@@ -7,9 +7,9 @@ import { parse } from 'url';
* google.com => google.com
*/
function toHost(url: string) {
function toHost(url: string): string {
if (/^https?:\/\//.test(url)) {
return parse(url).host;
return parse(url).host!;
}
// Remove any path if present

View File

@@ -9,9 +9,6 @@
"lint": "ng lint",
"e2e": "ng e2e"
},
"engines": {
"node": "10.x"
},
"private": true,
"dependencies": {
"@angular/animations": "8.1.0",

View File

@@ -997,10 +997,10 @@ bluebird@^3.3.0, bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5:
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0:
version "4.11.8"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f"
integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9:
version "4.12.0"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
bn.js@^5.1.1:
version "5.1.1"
@@ -1066,7 +1066,7 @@ braces@~3.0.2:
dependencies:
fill-range "^7.0.1"
brorand@^1.0.1:
brorand@^1.0.1, brorand@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=
@@ -1529,7 +1529,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6:
dependencies:
delayed-stream "~1.0.0"
commander@^2.11.0, commander@^2.12.1, commander@^2.20.0, commander@~2.20.3:
commander@^2.11.0, commander@^2.12.1, commander@^2.20.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
@@ -2088,17 +2088,17 @@ electron-to-chromium@^1.3.164, electron-to-chromium@^1.3.413:
integrity sha512-FtEGg/wRKT765QehmpRqMDaUbRam03Y3brE+6nUfoxCr9XgyEl+zAgN4+EraOJeyTGTGh27u7Mdx5Hl9qAhJPQ==
elliptic@^6.0.0, elliptic@^6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762"
integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==
version "6.5.4"
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb"
integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==
dependencies:
bn.js "^4.4.0"
brorand "^1.0.1"
bn.js "^4.11.9"
brorand "^1.1.0"
hash.js "^1.0.0"
hmac-drbg "^1.0.0"
inherits "^2.0.1"
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.0"
hmac-drbg "^1.0.1"
inherits "^2.0.4"
minimalistic-assert "^1.0.1"
minimalistic-crypto-utils "^1.0.1"
emoji-regex@^7.0.1:
version "7.0.3"
@@ -2842,9 +2842,9 @@ handle-thing@^2.0.0:
integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==
handlebars@^4.0.3:
version "4.7.6"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e"
integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==
version "4.7.7"
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==
dependencies:
minimist "^1.2.5"
neo-async "^2.6.0"
@@ -2955,7 +2955,7 @@ hash.js@^1.0.0, hash.js@^1.0.3:
inherits "^2.0.3"
minimalistic-assert "^1.0.1"
hmac-drbg@^1.0.0:
hmac-drbg@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=
@@ -2965,9 +2965,9 @@ hmac-drbg@^1.0.0:
minimalistic-crypto-utils "^1.0.1"
hosted-git-info@^2.1.4, hosted-git-info@^2.6.0, hosted-git-info@^2.7.1:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
hpack.js@^2.1.6:
version "2.1.6"
@@ -3948,9 +3948,9 @@ lodash.tail@^4.1.1:
integrity sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=
lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.4, lodash@^4.17.5:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log4js@^4.0.0:
version "4.5.1"
@@ -4181,7 +4181,7 @@ minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
minimalistic-crypto-utils@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a"
integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=
@@ -4330,9 +4330,9 @@ negotiator@0.6.2:
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
neo-async@^2.5.0, neo-async@^2.6.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c"
integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==
version "2.6.2"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
nice-try@^1.0.4:
version "1.0.5"
@@ -5192,9 +5192,9 @@ querystring@0.2.0:
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
querystringify@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
version "2.2.0"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.1.0"
@@ -6109,9 +6109,9 @@ sshpk@^1.7.0:
tweetnacl "~0.14.0"
ssri@^6.0.0, ssri@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
version "6.0.2"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
dependencies:
figgy-pudding "^3.5.1"
@@ -6601,11 +6601,9 @@ typescript@3.4.5:
integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==
uglify-js@^3.1.4:
version "3.9.3"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.9.3.tgz#4a285d1658b8a2ebaef9e51366b3a0f7acd79ec2"
integrity sha512-r5ImcL6QyzQGVimQoov3aL2ZScywrOgBXGndbWrdehKoSvGe/RmiE5Jpw/v+GvxODt6l2tpBXwA7n+qZVlHBMA==
dependencies:
commander "~2.20.3"
version "3.13.7"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.7.tgz#25468a3b39b1c875df03f0937b2b7036a93f3fee"
integrity sha512-1Psi2MmnZJbnEsgJJIlfnd7tFlJfitusmR7zDI8lXlFI0ACD4/Rm/xdrU8bh6zF0i74aiVoBtkRiFulkrmh3AA==
ultron@~1.1.0:
version "1.1.1"
@@ -6704,9 +6702,9 @@ urix@^0.1.0:
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
url-parse@^1.4.3:
version "1.4.7"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
version "1.5.1"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b"
integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"

View File

@@ -4571,9 +4571,9 @@ hoopy@^0.1.4:
integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==
hosted-git-info@^2.1.4:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
hpack.js@^2.1.6:
version "2.1.6"
@@ -6056,9 +6056,9 @@ lodash.sortby@^4.7.0:
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.4:
version "4.17.15"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
loglevel@^1.6.3:
version "1.6.8"
@@ -7324,9 +7324,9 @@ querystring@0.2.0:
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
querystringify@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
version "2.2.0"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.1.0"
@@ -8207,9 +8207,9 @@ sshpk@^1.7.0:
tweetnacl "~0.14.0"
ssri@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
version "6.0.2"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
dependencies:
figgy-pudding "^3.5.1"
@@ -8903,9 +8903,9 @@ url-loader@1.1.2:
schema-utils "^1.0.0"
url-parse@^1.4.3:
version "1.4.7"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
version "1.5.1"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b"
integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"

View File

@@ -4580,9 +4580,9 @@ hmac-drbg@^1.0.1:
minimalistic-crypto-utils "^1.0.1"
hosted-git-info@^2.1.4:
version "2.8.8"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
version "2.8.9"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
hpack.js@^2.1.6:
version "2.1.6"
@@ -7896,9 +7896,9 @@ querystring@0.2.0:
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
querystringify@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
version "2.2.0"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
raf@^3.4.1:
version "3.4.1"
@@ -8898,9 +8898,9 @@ sshpk@^1.7.0:
tweetnacl "~0.14.0"
ssri@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
version "6.0.2"
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
dependencies:
figgy-pudding "^3.5.1"
@@ -9529,9 +9529,9 @@ url-loader@1.1.2:
schema-utils "^1.0.0"
url-parse@^1.4.3:
version "1.4.7"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
version "1.5.1"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b"
integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/client",
"version": "10.0.1-canary.3",
"version": "10.1.0",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"homepage": "https://vercel.com",
@@ -40,7 +40,7 @@
]
},
"dependencies": {
"@vercel/build-utils": "2.10.3-canary.3",
"@vercel/build-utils": "2.11.0",
"@zeit/fetch": "5.2.0",
"async-retry": "1.2.3",
"async-sema": "3.0.0",

View File

@@ -55,7 +55,7 @@ export interface Deployment {
| 'DEPLOYING'
| 'READY'
| 'ERROR';
createdAt: string;
createdAt: number;
createdIn: string;
env: Dictionary<string>;
build: {

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/frameworks",
"version": "0.3.3-canary.3",
"version": "0.4.0",
"main": "./dist/frameworks.js",
"types": "./dist/frameworks.d.ts",
"files": [
@@ -20,7 +20,7 @@
"@types/js-yaml": "3.12.1",
"@types/node": "12.0.4",
"@types/node-fetch": "2.5.8",
"@vercel/routing-utils": "1.11.1-canary.1",
"@vercel/routing-utils": "1.11.1",
"ajv": "6.12.2",
"jest": "24.9.0",
"ts-jest": "24.1.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/node",
"version": "1.10.0",
"version": "1.11.0",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/node-js",
@@ -33,7 +33,7 @@
"@types/etag": "1.8.0",
"@types/test-listen": "1.1.0",
"@vercel/ncc": "0.24.0",
"@vercel/nft": "0.10.0",
"@vercel/nft": "0.12.2",
"content-type": "1.0.4",
"cookie": "0.4.0",
"etag": "1.8.1",

View File

@@ -1,5 +1,3 @@
{
"engines": {
"node": "10.x"
}
"private": true
}

View File

@@ -1,5 +1,3 @@
{
"engines": {
"node": "10.x"
}
"private": true
}

View File

@@ -26,7 +26,7 @@ async function getResult(url) {
}
module.exports = async (req, res) => {
const result = await getResult('https://vercel.com/about');
const result = await getResult('https://vercel.com/docs');
if (req && result && result.lhr && result.lhr.categories) {
res.end('lighthouse:RANDOMNESS_PLACEHOLDER');
} else {

View File

@@ -1,10 +1,10 @@
{
"engines": {
"node": "10.x"
"node": "14.x"
},
"dependencies": {
"chrome-aws-lambda": "1.20.4",
"lighthouse": "5.6.0",
"puppeteer-core": "1.20.0"
"chrome-aws-lambda": "7.0.0",
"lighthouse": "7.4.0",
"puppeteer-core": "7.0.0"
}
}

View File

@@ -7,7 +7,8 @@
"config": {
"functions": {
"**/*.js": {
"memory": 3008
"memory": 3008,
"maxDuration": 30
}
}
}

View File

@@ -3,8 +3,5 @@
"dependencies": {
"@builders-transpiled-test/lib": "*"
},
"engines": {
"node": "10.x"
},
"version": "1.0.0"
}

View File

@@ -3,8 +3,5 @@
"dependencies": {
"@builders-typescript-test/lib": "*"
},
"engines": {
"node": "10.x"
},
"version": "1.0.0"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/python",
"version": "2.0.1",
"version": "2.0.3",
"main": "./dist/index.js",
"license": "MIT",
"homepage": "https://vercel.com/docs/runtimes#official-runtimes/python",

View File

@@ -86,6 +86,7 @@ export const build = async ({
await installRequirement({
dependency: 'werkzeug',
version: '1.0.1',
workPath,
meta,
});
@@ -109,6 +110,7 @@ export const build = async ({
const tempDir = await getWriteableDirectory();
await installRequirement({
dependency: 'pipfile-requirements',
version: '0.3.0',
workPath: tempDir,
meta,
args: ['--no-warn-script-location'],

View File

@@ -61,39 +61,28 @@ async function pipInstall(workPath: string, args: string[]) {
// distutils.errors.DistutilsOptionError: can't combine user with
// prefix, exec_prefix/home, or install_(plat)base
process.env.PIP_USER = '0';
debug(
`Running "pip install --disable-pip-version-check --target ${target} --upgrade ${args.join(
' '
)}"...`
);
const cmdArgs = [
'install',
'--disable-pip-version-check',
'--target',
target,
...args,
];
debug(`Running "pip3 ${cmdArgs.join(' ')}"...`);
try {
await execa(
pipPath,
[
'install',
'--disable-pip-version-check',
'--target',
target,
'--upgrade',
...args,
],
{
cwd: workPath,
stdio: 'pipe',
}
);
await execa(pipPath, cmdArgs, {
cwd: workPath,
stdio: 'pipe',
});
} catch (err) {
console.log(
`Failed to run "pip install --disable-pip-version-check --target ${target} --upgrade ${args.join(
' '
)}"...`
);
console.log(`Failed to run "pip3 ${cmdArgs.join(' ')}"`);
throw err;
}
}
interface InstallRequirementArg {
dependency: string;
version: string;
workPath: string;
meta: Meta;
args?: string[];
@@ -101,6 +90,7 @@ interface InstallRequirementArg {
export async function installRequirement({
dependency,
version,
workPath,
meta,
args = [],
@@ -111,7 +101,8 @@ export async function installRequirement({
);
return;
}
await pipInstall(workPath, [dependency, ...args]);
const exact = `${dependency}==${version}`;
await pipInstall(workPath, [exact, ...args]);
}
interface InstallRequirementsFileArg {

View File

@@ -1,6 +1,6 @@
{
"name": "@vercel/routing-utils",
"version": "1.11.1-canary.1",
"version": "1.11.1",
"description": "Vercel routing utilities",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",

192
yarn.lock
View File

@@ -1265,6 +1265,21 @@
npmlog "^4.1.2"
write-file-atomic "^2.3.0"
"@mapbox/node-pre-gyp@^1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.5.tgz#2a0b32fcb416fb3f2250fd24cb2a81421a4f5950"
integrity sha512-4srsKPXWlIxp5Vbqz5uLfBN+du2fJChBoYn/f2h991WLdk7jUvcSk/McVLSv/X+xQIPI8eGD5GjrnygdyHnhPA==
dependencies:
detect-libc "^1.0.3"
https-proxy-agent "^5.0.0"
make-dir "^3.1.0"
node-fetch "^2.6.1"
nopt "^5.0.0"
npmlog "^4.1.2"
rimraf "^3.0.2"
semver "^7.3.4"
tar "^6.1.0"
"@mrmlnc/readdir-enhanced@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
@@ -1737,6 +1752,14 @@
"@types/events" "*"
"@types/node" "*"
"@types/inquirer@7.3.1":
version "7.3.1"
resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-7.3.1.tgz#1f231224e7df11ccfaf4cf9acbcc3b935fea292d"
integrity sha512-osD38QVIfcdgsPCT0V3lD7eH0OFurX71Jft18bZrsVQWVRt6TuxRzlr0GJLrxoHZR2V5ph7/qP8se/dcnI7o0g==
dependencies:
"@types/through" "*"
rxjs "^6.4.0"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.2.tgz#79d7a78bad4219f4c03d6557a1c72d9ca6ba62d5"
@@ -1837,12 +1860,13 @@
dependencies:
"@types/node" "*"
"@types/node-fetch@2.1.4":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.1.4.tgz#093d1beae11541aef25999d70aa09286fd025b1a"
integrity sha512-tR1ekaXUGpmzOcDXWU9BW73YfA2/VW1DF1FH+wlJ82BbCSnWTbdX+JkqWQXWKIGsFPnPsYadbXfNgz28g+ccWg==
"@types/node-fetch@2.5.10":
version "2.5.10"
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.10.tgz#9b4d4a0425562f9fcea70b12cb3fcdd946ca8132"
integrity sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==
dependencies:
"@types/node" "*"
form-data "^3.0.0"
"@types/node-fetch@2.5.4":
version "2.5.4"
@@ -1978,6 +2002,13 @@
resolved "https://registry.yarnpkg.com/@types/text-table/-/text-table-0.2.0.tgz#cec067b522598bbb37186375b834ac30411c9af6"
integrity sha512-om4hNWnI01IKUFCjGQG33JqFcnmt0W5C3WX0G1FVBaucr7oRnL29aAz2hnxpbZnE2t9f8/BR5VOtgcOtsonpLA==
"@types/through@*":
version "0.0.30"
resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.30.tgz#e0e42ce77e897bd6aead6f6ea62aeb135b8a3895"
integrity sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==
dependencies:
"@types/node" "*"
"@types/universal-analytics@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@types/universal-analytics/-/universal-analytics-0.4.2.tgz#d21a122a984bf8261eb206bcb7ccb1c0e8353d04"
@@ -2085,11 +2116,12 @@
resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.24.0.tgz#a2e8783a185caa99b5d8961a57dfc9665de16296"
integrity sha512-crqItMcIwCkvdXY/V3/TzrHJQx6nbIaRqE1cOopJhgGX6izvNov40SmD//nS5flfEvdK54YGjwVVq+zG6crjOg==
"@vercel/nft@0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.10.0.tgz#6dc99c28abd073633467371a1855f08820460d45"
integrity sha512-0WABTmfebmYDR9GKuM9uFNr6MCayfl/zB6uXzkMsWlXrd7LN/ZI7sdbC/Ua+h4HEzJtvEMOrxLkIYYKqfeUf9A==
"@vercel/nft@0.12.2":
version "0.12.2"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.12.2.tgz#67ea9f231d24639b3783e3e69bef173659972d3b"
integrity sha512-H8n44GboVnJaVVX4+WfuOTAaNLDnUIYH4KpMZcXll7KMNIcg0JTd0IFRsIBe/uvuXisqm6nEANp8Tr3/1dlRQw==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.5"
acorn "^8.1.0"
acorn-class-fields "^1.0.0"
acorn-static-class-features "^1.0.0"
@@ -2263,11 +2295,6 @@ agent-base@4, agent-base@^4.1.0, agent-base@^4.3.0:
dependencies:
es6-promisify "^5.0.0"
agent-base@5:
version "5.1.1"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c"
integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==
agent-base@6:
version "6.0.0"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.0.tgz#5d0101f19bbfaed39980b22ae866de153b93f09a"
@@ -3300,6 +3327,11 @@ chownr@^1.0.1, chownr@^1.1.1, chownr@^1.1.2:
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
chownr@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
chunkd@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/chunkd/-/chunkd-1.0.0.tgz#4ead4a3704bcce510c4bb4d4a8be30c557836dd1"
@@ -3443,15 +3475,15 @@ code-point-at@^1.0.0:
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
codecov@3.7.1:
version "3.7.1"
resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.7.1.tgz#434cb8d55f18ef01672e5739d3d266696bebc202"
integrity sha512-JHWxyPTkMLLJn9SmKJnwAnvY09kg2Os2+Ux+GG7LwZ9g8gzDDISpIN5wAsH1UBaafA/yGcd3KofMaorE8qd6Lw==
codecov@3.8.2:
version "3.8.2"
resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.8.2.tgz#ab24f18783998c39e809ea210af899f8dbcc790e"
integrity sha512-6w/kt/xvmPsWMfDFPE/T054txA9RTgcJEw36PNa6MYX+YV29jCHCRFXwbQ3QZBTOgnex1J2WP8bo2AT8TWWz9g==
dependencies:
argv "0.0.2"
ignore-walk "3.0.3"
js-yaml "3.13.1"
teeny-request "6.0.1"
js-yaml "3.14.1"
teeny-request "7.0.1"
urlgrey "0.4.4"
collection-visit@^1.0.0:
@@ -4110,7 +4142,7 @@ detect-indent@^5.0.0:
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50=
detect-libc@^1.0.2:
detect-libc@^1.0.2, detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
@@ -4438,6 +4470,11 @@ es6-promisify@^5.0.0:
dependencies:
es6-promise "^4.0.3"
esbuild@^0.11.20:
version "0.11.23"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.11.23.tgz#c42534f632e165120671d64db67883634333b4b8"
integrity sha512-iaiZZ9vUF5wJV8ob1tl+5aJTrwDczlvGP0JoMmnpC2B0ppiMCu8n8gmy5ZTGl5bcG081XBVn+U+jP+mPFm5T5Q==
escape-goat@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
@@ -5125,6 +5162,13 @@ fs-minipass@^1.2.5:
dependencies:
minipass "^2.6.0"
fs-minipass@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
dependencies:
minipass "^3.0.0"
fs-write-stream-atomic@^1.0.8:
version "1.0.10"
resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
@@ -5693,12 +5737,12 @@ https-proxy-agent@^2.2.3:
agent-base "^4.3.0"
debug "^3.1.0"
https-proxy-agent@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b"
integrity sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==
https-proxy-agent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
dependencies:
agent-base "5"
agent-base "6"
debug "4"
human-signals@^1.1.1:
@@ -6779,6 +6823,14 @@ js-yaml@3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@3.14.1:
version "3.14.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
dependencies:
argparse "^1.0.7"
esprima "^4.0.0"
js-yaml@^3.10.0, js-yaml@^3.13.1:
version "3.14.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
@@ -7315,6 +7367,13 @@ lru-cache@^4.0.1:
pseudomap "^1.0.2"
yallist "^2.1.2"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
dependencies:
yallist "^4.0.0"
lru_map@0.3.3:
version "0.3.3"
resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd"
@@ -7340,7 +7399,7 @@ make-dir@^2.0.0, make-dir@^2.1.0:
pify "^4.0.1"
semver "^5.6.0"
make-dir@^3.0.0:
make-dir@^3.0.0, make-dir@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
@@ -7656,6 +7715,13 @@ minipass@^2.3.3, minipass@^2.3.4, minipass@^2.3.5, minipass@^2.6.0, minipass@^2.
safe-buffer "^5.1.2"
yallist "^3.0.0"
minipass@^3.0.0:
version "3.1.3"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
dependencies:
yallist "^4.0.0"
minizlib@^1.1.0, minizlib@^1.1.1, minizlib@^1.2.1:
version "1.3.3"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
@@ -7663,6 +7729,14 @@ minizlib@^1.1.0, minizlib@^1.1.1, minizlib@^1.2.1:
dependencies:
minipass "^2.9.0"
minizlib@^2.1.1:
version "2.1.2"
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
dependencies:
minipass "^3.0.0"
yallist "^4.0.0"
mississippi@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
@@ -7694,7 +7768,7 @@ mkdirp-promise@5.0.1, mkdirp-promise@^5.0.1:
dependencies:
mkdirp "*"
mkdirp@*:
mkdirp@*, mkdirp@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
@@ -7856,7 +7930,7 @@ node-fetch@2.6.0:
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-fetch@2.6.1, node-fetch@^2.2.0, node-fetch@^2.2.1, node-fetch@^2.3.0, node-fetch@^2.5.0:
node-fetch@2.6.1, node-fetch@^2.2.1, node-fetch@^2.3.0, node-fetch@^2.5.0, node-fetch@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
@@ -7928,6 +8002,13 @@ nopt@^4.0.1:
abbrev "1"
osenv "^0.1.4"
nopt@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
integrity sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==
dependencies:
abbrev "1"
normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@@ -9401,7 +9482,7 @@ rimraf@2.6.3:
dependencies:
glob "^7.1.3"
rimraf@3.0.2, rimraf@^3.0.0:
rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
@@ -9553,6 +9634,13 @@ semver@^7.3.2:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
semver@^7.3.4:
version "7.3.5"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
dependencies:
lru-cache "^6.0.0"
serialize-error@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a"
@@ -9771,7 +9859,7 @@ source-map-support@0.5.12:
buffer-from "^1.0.0"
source-map "^0.6.0"
source-map-support@^0.5.12, source-map-support@^0.5.17, source-map-support@^0.5.6:
source-map-support@^0.5.12, source-map-support@^0.5.17, source-map-support@^0.5.19, source-map-support@^0.5.6:
version "0.5.19"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
@@ -10285,16 +10373,28 @@ tar@^4, tar@^4.4.10, tar@^4.4.12, tar@^4.4.8:
safe-buffer "^5.1.2"
yallist "^3.0.3"
teeny-request@6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-6.0.1.tgz#9b1f512cef152945827ba7e34f62523a4ce2c5b0"
integrity sha512-TAK0c9a00ELOqLrZ49cFxvPVogMUFaWY8dUsQc/0CuQPGF+BOxOQzXfE413BAk2kLomwNplvdtMpeaeGWmoc2g==
tar@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
minipass "^3.0.0"
minizlib "^2.1.1"
mkdirp "^1.0.3"
yallist "^4.0.0"
teeny-request@7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-7.0.1.tgz#bdd41fdffea5f8fbc0d29392cb47bec4f66b2b4c"
integrity sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==
dependencies:
http-proxy-agent "^4.0.0"
https-proxy-agent "^4.0.0"
node-fetch "^2.2.0"
https-proxy-agent "^5.0.0"
node-fetch "^2.6.1"
stream-events "^1.0.5"
uuid "^3.3.2"
uuid "^8.0.0"
temp-dir@^1.0.0:
version "1.0.0"
@@ -10538,6 +10638,14 @@ trim-right@^1.0.1:
resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=
ts-eager@2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/ts-eager/-/ts-eager-2.0.2.tgz#2c1a4d37529effa321f3438793650a84028a87d5"
integrity sha512-xzFPL2z7mgLs0brZXaIHTm91Pjl/Cuu9AMKprgSuK+kIS2LjiG8fqqg4eqz3tgBy9OIdupb9w55pr7ea3JBB+Q==
dependencies:
esbuild "^0.11.20"
source-map-support "^0.5.19"
ts-jest@24.1.0:
version "24.1.0"
resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.1.0.tgz#2eaa813271a2987b7e6c3fefbda196301c131734"
@@ -10893,6 +11001,11 @@ uuid@^3.0.0, uuid@^3.0.1, uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
uuid@^8.0.0:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
v8-compile-cache@^2.0.3:
version "2.1.1"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745"
@@ -11215,6 +11328,11 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yargs-parser@10.x, yargs-parser@^10.0.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8"